rubocop-0.52.1/000077500000000000000000000000001322072016200132435ustar00rootroot00000000000000rubocop-0.52.1/.editorconfig000066400000000000000000000002741322072016200157230ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true [*.md] trim_trailing_whitespace = false rubocop-0.52.1/.gitattributes000066400000000000000000000000311322072016200161300ustar00rootroot00000000000000CHANGELOG.md merge=union rubocop-0.52.1/.github/000077500000000000000000000000001322072016200146035ustar00rootroot00000000000000rubocop-0.52.1/.github/ISSUE_TEMPLATE.md000066400000000000000000000016751322072016200173210ustar00rootroot00000000000000*Be clear, concise and precise in your description of the problem. Open an issue with a descriptive title and a summary in grammatically correct, complete sentences.* *Use the template below when reporting bugs. Please, make sure that you're running the latest stable RuboCop and that the problem you're reporting hasn't been reported (and potentially fixed) already.* *Before filing the ticket you should replace all text above the horizontal rule with your own words.* -------- ## Expected behavior Describe here how you expected RuboCop to behave in this particular situation. ## Actual behavior Describe here what actually happened. ## Steps to reproduce the problem This is extremely important! Providing us with a reliable way to reproduce a problem will expedite its solution. ## RuboCop version Include the output of `rubocop -V`. Here's an example: ``` $ rubocop -V 0.50.0 (using Parser 2.4.0.0, running on ruby 2.4.2 x86_64-linux) ``` rubocop-0.52.1/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000016601322072016200204070ustar00rootroot00000000000000**Replace this text with a summary of the changes in your PR. The more detailed you are, the better.** ----------------- Before submitting the PR make sure the following are checked: * [ ] Wrote [good commit messages][1]. * [ ] Commit message starts with `[Fix #issue-number]` (if the related issue exists). * [ ] Feature branch is up-to-date with `master` (if not - rebase it). * [ ] Squashed related commits together. * [ ] Added tests. * [ ] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new code introduces user-observable changes. See [changelog entry format](../blob/master/CONTRIBUTING.md#changelog-entry-format). * [ ] The PR relates to *only* one subject with a clear title and description in grammatically correct, complete sentences. * [ ] Run `rake default` or `rake parallel`. It executes all tests and RuboCop for itself, and generates the documentation. [1]: http://chris.beams.io/posts/git-commit/ rubocop-0.52.1/.gitignore000066400000000000000000000016121322072016200152330ustar00rootroot00000000000000# rcov generated coverage coverage.data # rdoc generated rdoc # yard generated doc .yardoc # bundler .bundle Gemfile.lock Gemfile.local # rspec /spec/examples.txt /.test_queue_stats # jeweler generated pkg # etags TAGS # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore: # # * Create a file at ~/.gitignore # * Include files you want ignored # * Run: git config --global core.excludesfile ~/.gitignore # # After doing this, these files will be ignored in all your git projects, # saving you from having to 'pollute' every project you touch with them # # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line) # # For MacOS: # #.DS_Store # For TextMate #*.tmproj #tmtags # For emacs: #*~ #\#* #.\#* # For vim: *.swp # For redcar: #.redcar # For rubinius: #*.rbc rubocop-0.52.1/.rspec000066400000000000000000000000361322072016200143570ustar00rootroot00000000000000--color --require spec_helper rubocop-0.52.1/.rubocop.yml000066400000000000000000000032201322072016200155120ustar00rootroot00000000000000# This is the configuration used to check the rubocop source code. inherit_from: .rubocop_todo.yml require: - rubocop/cop/internal_affairs - rubocop-rspec AllCops: Exclude: - 'vendor/**/*' - 'spec/fixtures/**/*' - 'tmp/**/*' TargetRubyVersion: 2.1 Naming/PredicateName: # Method define macros for dynamically generated method. MethodDefinitionMacros: - define_method - define_singleton_method - def_node_matcher - def_node_search Style/FrozenStringLiteralComment: EnforcedStyle: always Style/FormatStringToken: # Because we parse a lot of source codes from strings. Percent arrays # look like unannotated format string tokens to this cop. Exclude: - spec/**/* Layout/EndOfLine: EnforcedStyle: lf Layout/ClassStructure: Enabled: true Categories: module_inclusion: - include - prepend - extend ExpectedOrder: - module_inclusion - constants - public_class_methods - initializer - instance_methods - protected_methods - private_methods Layout/IndentHeredoc: EnforcedStyle: powerpack Lint/AmbiguousBlockAssociation: Exclude: - 'spec/**/*.rb' Lint/InterpolationCheck: Exclude: - 'spec/**/*.rb' Lint/UselessAccessModifier: MethodCreatingMethods: - 'def_matcher' - 'def_node_matcher' Lint/BooleanSymbol: Enabled: false Metrics/BlockLength: Exclude: - 'Rakefile' - '**/*.rake' - 'spec/**/*.rb' Metrics/ModuleLength: Exclude: - 'spec/**/*.rb' Performance/Caller: Exclude: - spec/rubocop/cop/performance/caller_spec.rb RSpec/PredicateMatcher: EnforcedStyle: explicit RSpec/NestedGroups: Max: 7 rubocop-0.52.1/.rubocop_todo.yml000066400000000000000000000061331322072016200165450ustar00rootroot00000000000000# This configuration was generated by # `rubocop --auto-gen-config` # on 2017-12-26 13:52:41 +0900 using RuboCop version 0.52.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: 73 Metrics/AbcSize: Max: 18 # Offense count: 41 # Configuration parameters: CountComments. Metrics/ClassLength: Max: 185 # Offense count: 178 # Configuration parameters: CountComments. Metrics/MethodLength: Max: 14 # Offense count: 4 # Configuration parameters: CountComments. Metrics/ModuleLength: Max: 139 # Offense count: 10 RSpec/AnyInstance: Exclude: - 'spec/rubocop/cli_spec.rb' - 'spec/rubocop/cop/lint/duplicate_methods_spec.rb' - 'spec/rubocop/target_finder_spec.rb' # Offense count: 963 # Configuration parameters: Prefixes. # Prefixes: when, with, without RSpec/ContextWording: Enabled: false # Offense count: 2790 # Configuration parameters: Max. RSpec/ExampleLength: Enabled: false # Offense count: 43 RSpec/ExpectOutput: Exclude: - 'spec/rubocop/cli/cli_auto_gen_config_spec.rb' - 'spec/rubocop/cli/cli_options_spec.rb' - 'spec/rubocop/config_spec.rb' - 'spec/rubocop/cop/cop_spec.rb' - 'spec/rubocop/formatter/base_formatter_spec.rb' - 'spec/rubocop/formatter/disabled_config_formatter_spec.rb' - 'spec/rubocop/formatter/formatter_set_spec.rb' - 'spec/rubocop/options_spec.rb' - 'spec/rubocop/path_util_spec.rb' - 'spec/rubocop/rake_task_spec.rb' - 'spec/rubocop/result_cache_spec.rb' - 'spec/rubocop/target_finder_spec.rb' - 'spec/support/cli_spec_behavior.rb' # Offense count: 37 # Configuration parameters: EnforcedStyle. # SupportedStyles: have_received, receive RSpec/MessageSpies: Exclude: - 'spec/rubocop/cli_spec.rb' - 'spec/rubocop/config_loader_spec.rb' - 'spec/rubocop/config_store_spec.rb' - 'spec/rubocop/cop/commissioner_spec.rb' - 'spec/rubocop/cop/cop_spec.rb' - 'spec/rubocop/cop/force_spec.rb' - 'spec/rubocop/cop/generator_spec.rb' - 'spec/rubocop/formatter/base_formatter_spec.rb' - 'spec/rubocop/formatter/colorizable_spec.rb' - 'spec/rubocop/formatter/formatter_set_spec.rb' - 'spec/rubocop/formatter/progress_formatter_spec.rb' - 'spec/rubocop/rake_task_spec.rb' # Offense count: 1 RSpec/MultipleDescribes: Exclude: - 'spec/rubocop/string_util_spec.rb' # Offense count: 869 RSpec/MultipleExpectations: Max: 25 # Offense count: 21 RSpec/SubjectStub: Exclude: - 'spec/rubocop/config_spec.rb' - 'spec/rubocop/cop/cop_spec.rb' - 'spec/rubocop/formatter/base_formatter_spec.rb' - 'spec/rubocop/formatter/json_formatter_spec.rb' - 'spec/rubocop/formatter/progress_formatter_spec.rb' # Offense count: 37 # Configuration parameters: IgnoreSymbolicNames. RSpec/VerifiedDoubles: Enabled: false # Offense count: 100 # Configuration parameters: EnforcedStyle. # SupportedStyles: annotated, template, unannotated Style/FormatStringToken: Enabled: false rubocop-0.52.1/.travis.rb000066400000000000000000000020221322072016200151520ustar00rootroot00000000000000# frozen_string_literal: true require 'English' require 'benchmark' def jruby? RUBY_ENGINE == 'jruby' end def master? ENV['TRAVIS_BRANCH'] == 'master' && ENV['TRAVIS_PULL_REQUEST'] == 'false' end def test? ENV['TASK'] != 'internal_investigation' end def sh!(command) puts "$ #{command}" time = Benchmark.realtime do system(command) end puts "#{time} seconds" puts raise "`#{command}` is failed" unless $CHILD_STATUS.success? end # Run main task(RSpec or RuboCop). if master? || !test? || jruby? sh!("bundle exec rake #{ENV['TASK']}") else sh!("bundle exec rake parallel:#{ENV['TASK']}") end # Report test coverage sh!('bundle exec codeclimate-test-reporter') if master? && test? # Running YARD under jruby crashes so skip checking manual under jruby unless jruby? sh!('bundle exec rake documentation_syntax_check generate_cops_documentation') end # Check requiring libraries successfully. # See https://github.com/bbatsov/rubocop/pull/4523#issuecomment-309136113 sh!("ruby -I lib -r rubocop -e 'exit 0'") rubocop-0.52.1/.travis.yml000066400000000000000000000012441322072016200153550ustar00rootroot00000000000000sudo: false cache: bundler language: ruby dist: trusty rvm: - jruby-9.1.15.0 - jruby-head - 2.1.10 - 2.2.9 - 2.3.6 - 2.4.3 - 2.5.0 - ruby-head env: global: - JRUBY_OPTS='--debug -J-Xmx1000M' # get more accurate coverage data in JRuby matrix: - 'TASK=spec' - 'TASK=ascii_spec' - 'TASK=internal_investigation' matrix: allow_failures: - rvm: ruby-head - rvm: jruby-head fast_finish: true before_install: - gem update --system - gem update --remote bundler install: - bundle install --retry=3 script: - ruby .travis.rb addons: code_climate: repo_token: a11b66bfbb1acdf220d5cb317b2e945a986fd85adebe29a76d411ad6d74ec31f rubocop-0.52.1/.yardopts000066400000000000000000000000451322072016200151100ustar00rootroot00000000000000--markup markdown --hide-void-return rubocop-0.52.1/CHANGELOG.md000066400000000000000000011155341322072016200150660ustar00rootroot00000000000000# Change log ## master (unreleased) ## 0.52.1 (2017-12-27) ### Bug fixes * [#5241](https://github.com/bbatsov/rubocop/issues/5241): Fix an error for `Layout/AlignHash` when using a hash including only a keyword splat. ([@wata727][]) * [#5245](https://github.com/bbatsov/rubocop/issues/5245): Make `Style/FormatStringToken` to allow regexp token. ([@pocke][]) * [#5224](https://github.com/bbatsov/rubocop/pull/5224): Fix false positives for `Layout/EmptyLinesAroundArguments` operating on blocks. ([@garettarrowood][]) * [#5234](https://github.com/bbatsov/rubocop/issues/5234): Fix a false positive for `Rails/HasManyOrHasOneDependent` when using `class_name` option. ([@koic][]) * [#5273](https://github.com/bbatsov/rubocop/issues/5273): Fix `Style/EvalWithLocation` reporting bad line offset. ([@pocke][]) * [#5228](https://github.com/bbatsov/rubocop/issues/5228): Handle overridden `Metrics/LineLength:Max` for `--auto-gen-config`. ([@jonas054][]) * [#5226](https://github.com/bbatsov/rubocop/issues/5226): Suppress false positives for `Rails/RedundantReceiverInWithOptions` when including another receiver in `with_options`. ([@wata727][]) * [#5259](https://github.com/bbatsov/rubocop/pull/5259): Fix false positives in `Style/CommentedKeyword`. ([@garettarrowood][]) * [#5238](https://github.com/bbatsov/rubocop/pull/5238): Fix error when #present? or #blank? is used in if or unless modifier. ([@eitoball][]) * [#5261](https://github.com/bbatsov/rubocop/issues/5261): Fix a false positive for `Style/MixinUsage` when using inside class or module. ([@koic][]) * [#5289](https://github.com/bbatsov/rubocop/issues/5289): Fix `Layout/SpaceInsideReferenceBrackets` and `Layout/SpaceInsideArrayLiteralBrackets` configuration conflicts. ([@garettarrowood][]) * [#4444](https://github.com/bbatsov/rubocop/issues/4444): Fix `Style/AutoResourceCleanup` shouldn't flag `File.open(...).close`. ([@dpostorivo][]) * [#5278](https://github.com/bbatsov/rubocop/pull/5278): Fix deprecation check to use `loaded_path` in warning. ([@chrishulton][]) * [#5293](https://github.com/bbatsov/rubocop/issues/5293): Fix a regression for `Rails/HasManyOrHasOneDependent` when using a option of `has_many` or `has_one` association. ([@koic][]) * [#5223](https://github.com/bbatsov/rubocop/issues/5223): False offences in :unannotated Style/FormatStringToken. ([@nattfodd][]) * [#5258](https://github.com/bbatsov/rubocop/issues/5258): Fix incorrect autocorrection for `Rails/Presence` when the else block is multiline. ([@wata727][]) * [#5297](https://github.com/bbatsov/rubocop/pull/5297): Improve inspection for `Rails/InverseOf` when including `through` or `polymorphic` options. ([@wata727][]) * [#5281](https://github.com/bbatsov/rubocop/issues/5281): Fix issue where `--auto-gen-config` might fail on invalid YAML. ([@bquorning][]) * [#5313](https://github.com/bbatsov/rubocop/issues/5313): Fix `Style/HashSyntax` from stripping quotes off of symbols during autocorrection for ruby22+. ([@garettarrowood][]) * [#5315](https://github.com/bbatsov/rubocop/issues/5315): Fix a false positive of `Layout/RescueEnsureAlignment` in Ruby 2.5. ([@pocke][]) * [#5236](https://github.com/bbatsov/rubocop/issues/5236): Fix false positives for `Rails/InverseOf` when using `with_options`. ([@wata727][]) * [#5291](https://github.com/bbatsov/rubocop/issues/5291): Fix multiline indent for `Style/BracesAroundHashParameters` autocorrect. ([@flyerhzm][]) * [#3318](https://github.com/bbatsov/rubocop/issues/3318): Look for `.ruby-version` in parent directories. ([@ybiquitous][]) ### Changes * [#5300](https://github.com/bbatsov/rubocop/pull/5300): Display correction candidate if an incorrect cop name is given. ([@yhirano55][]) * [#5233](https://github.com/bbatsov/rubocop/pull/5233): Remove `Style/ExtendSelf` cop. ([@pocke][]) * [#5221](https://github.com/bbatsov/rubocop/issues/5221): Change `Layout/SpaceBeforeBlockBraces`'s `EnforcedStyleForEmptyBraces` from `no_space` to `space`. ([@garettarrowood][]) * [#3558](https://github.com/bbatsov/rubocop/pull/3558): Create `Corrector` classes and move all `autocorrect` methods out of mixin Modules. ([@garettarrowood][]) ## 0.52.0 (2017-12-12) ### New features * [#5101](https://github.com/bbatsov/rubocop/pull/5101): Allow to specify `TargetRubyVersion` 2.5. ([@walf443][]) * [#1575](https://github.com/bbatsov/rubocop/issues/1575): Add new `Layout/ClassStructure` cop that checks whether definitions in a class are in the configured order. This cop is disabled by default. ([@jonatas][]) * New cop `Rails/InverseOf` checks for association arguments that require setting the `inverse_of` option manually. ([@bdewater][]) * [#4811](https://github.com/bbatsov/rubocop/issues/4811): Add new `Layout/SpaceInsideReferenceBrackets` cop. ([@garettarrowood][]) * [#4811](https://github.com/bbatsov/rubocop/issues/4811): Add new `Layout/SpaceInsideArrayLiteralBrackets` cop. ([@garettarrowood][]) * [#4252](https://github.com/bbatsov/rubocop/issues/4252): Add new `Style/TrailingBodyOnMethodDefinition` cop. ([@garettarrowood][]) * Add new `Style/TrailingMethodEndStatment` cop. ([@garettarrowood][]) * [#5074](https://github.com/bbatsov/rubocop/issues/5074): Add Layout/EmptyLinesAroundArguments cop. ([@garettarrowood][]) * [#4650](https://github.com/bbatsov/rubocop/issues/4650): Add new `Style/StringHashKeys` cop. ([@donjar][]) * [#1583](https://github.com/bbatsov/rubocop/issues/1583): Add a quiet formatter. ([@drenmi][]) * Add new `Style/RandomWithOffset` cop. ([@donjar][]) * [#4892](https://github.com/bbatsov/rubocop/issues/4892): Add new `Lint/ShadowedArgument` cop and remove argument shadowing detection from `Lint/UnusedBlockArgument` and `Lint/UnusedMethodArgument`. ([@akhramov][]) * [#4674](https://github.com/bbatsov/rubocop/issues/4674): Add a new `Lint/MissingCopEnableDirective` cop. ([@tdeo][]) * Add new `Rails/EnvironmentComparison` cop. ([@tdeo][]) * Add `AllowedChars` option to `Style/AsciiComments` cop. ([@hedgesky][]) * [#5031](https://github.com/bbatsov/rubocop/pull/5031): Add new `Style/EmptyBlockParameter` and `Style/EmptyLambdaParameter` cops. ([@pocke][]) * [#5057](https://github.com/bbatsov/rubocop/pull/5057): Add new `Gemspec/RequiredRubyVersion` cop. ([@koic][]) * [#5087](https://github.com/bbatsov/rubocop/pull/5087): Add new `Gemspec/RedundantAssignment` cop. ([@koic][]) * Add `unannotated` option to `Style/FormatStringToken` cop. ([@drenmi][]) * [#5077](https://github.com/bbatsov/rubocop/pull/5077): Add new `Rails/CreateTableWithTimestamps` cop. ([@wata727][]) * Add new `Style/ColonMethodDefinition` cop. ([@rrosenblum][]) * Add new `Style/ExtendSelf` cop. ([@drenmi][]) * [#5185](https://github.com/bbatsov/rubocop/pull/5185): Add new `Rails/RedundantReceiverInWithOptions` cop. ([@koic][]) * [#5177](https://github.com/bbatsov/rubocop/pull/5177): Add new `Rails/LexicallyScopedActionFilter` cop. ([@wata727][]) * [#5173](https://github.com/bbatsov/rubocop/pull/5173): Add new `Style/EvalWithLocation` cop. ([@pocke][]) * [#5208](https://github.com/bbatsov/rubocop/pull/5208): Add new `Rails/Presence` cop. ([@wata727][]) * Allow auto-correction of ClassAndModuleChildren. ([@siggymcfried][], [@melch][]) ### Bug fixes * [#5096](https://github.com/bbatsov/rubocop/issues/5096): Fix incorrect detection and autocorrection of multiple extend/include/prepend. ([@marcandre][]) * [#5219](https://github.com/bbatsov/rubocop/issues/5219): Fix incorrect empty line detection for block arguments in `Layout/EmptyLinesAroundArguments`. ([@garettarrowood][]) * [#4662](https://github.com/bbatsov/rubocop/issues/4662): Fix incorrect indent level detection when first line of heredoc is blank. ([@sambostock][]) * [#5016](https://github.com/bbatsov/rubocop/issues/5016): Fix a false positive for `Style/ConstantName` with constant names using non-ASCII capital letters with accents. ([@timrogers][]) * [#4866](https://github.com/bbatsov/rubocop/issues/4866): Prevent `Layout/BlockEndNewline` cop from introducing trailing whitespaces. ([@bgeuken][]) * [#3396](https://github.com/bbatsov/rubocop/issues/3396): Concise error when config. file not found. ([@jaredbeck][]) * [#4881](https://github.com/bbatsov/rubocop/issues/4881): Fix a false positive for `Performance/HashEachMethods` when unused argument(s) exists in other blocks. ([@pocke][]) * [#4883](https://github.com/bbatsov/rubocop/pull/4883): Fix auto-correction for `Performance/HashEachMethods`. ([@pocke][]) * [#4896](https://github.com/bbatsov/rubocop/pull/4896): Fix Style/DateTime wrongly triggered on classes `...::DateTime`. ([@dpostorivo][]) * [#4938](https://github.com/bbatsov/rubocop/pull/4938): Fix behavior of `Lint/UnneededDisable`, which was returning offenses even after being disabled in a comment. ([@tdeo][]) * [#4887](https://github.com/bbatsov/rubocop/pull/4887): Add undeclared configuration option `EnforcedStyleForEmptyBraces` for `Layout/SpaceBeforeBlockBraces` cop. ([@drenmi][]) * [#4987](https://github.com/bbatsov/rubocop/pull/4987): Skip permission check when using stdin option. ([@mtsmfm][]) * [#4909](https://github.com/bbatsov/rubocop/issues/4909): Make `Rails/HasManyOrHasOneDependent` aware of multiple associations in `with_options`. ([@koic][]) * [#4794](https://github.com/bbatsov/rubocop/issues/4794): Fix an error in `Layout/MultilineOperationIndentation` when an operation spans multiple lines and contains a ternary expression. ([@rrosenblum][]) * [#4885](https://github.com/bbatsov/rubocop/issues/4885): Fix false offense detected by `Style/MixinUsage` cop. ([@koic][]) * [#3363](https://github.com/bbatsov/rubocop/pull/3363): Fix `Style/EmptyElse` autocorrection removes comments from branches. ([@dpostorivo][]) * [#5025](https://github.com/bbatsov/rubocop/issues/5025): Fix error with Layout/MultilineMethodCallIndentation cop and lambda.(...). ([@dpostorivo][]) * [#4781](https://github.com/bbatsov/rubocop/issues/4781): Prevent `Style/UnneededPercentQ` from breaking on strings that are concated with backslash. ([@pocke][]) * [#4363](https://github.com/bbatsov/rubocop/issues/4363): Fix `Style/PercentLiteralDelimiters` incorrectly automatically modifies escaped percent literal delimiter. ([@koic][]) * [#5053](https://github.com/bbatsov/rubocop/issues/5053): Fix `Naming/ConstantName` false offense on assigning to a nonoffensive assignment. ([@garettarrowood][]) * [#5019](https://github.com/bbatsov/rubocop/pull/5019): Fix auto-correct for `Style/HashSyntax` cop when hash is used as unspaced argument. ([@drenmi][]) * [#5052](https://github.com/bbatsov/rubocop/pull/5052): Improve accuracy of `Style/BracesAroundHashParameters` auto-correction. ([@garettarrowood][]) * [#5059](https://github.com/bbatsov/rubocop/issues/5059): Fix a false positive for `Style/MixinUsage` when `include` call is a method argument. ([@koic][]) * [#5071](https://github.com/bbatsov/rubocop/pull/5071): Fix a false positive in `Lint/UnneededSplatExpansion`, when `Array.new` resides in an array literal. ([@akhramov][]) * [#4071](https://github.com/bbatsov/rubocop/issues/4071): Prevent generating wrong code by Style/ColonMethodCall and Style/RedundantSelf. ([@pocke][]) * [#5089](https://github.com/bbatsov/rubocop/issues/5089): Fix false positive for `Style/SafeNavigation` when safe guarding arithmetic operation or assignment. ([@tiagotex][]) * [#5099](https://github.com/bbatsov/rubocop/pull/5099): Prevent `Style/MinMax` from breaking on implicit receivers. ([@drenmi][]) * [#5079](https://github.com/bbatsov/rubocop/issues/5079): Fix false positive for `Style/SafeNavigation` when safe guarding comparisons. ([@tiagotex][]) * [#5075](https://github.com/bbatsov/rubocop/issues/5075): Fix auto-correct for `Style/RedundantParentheses` cop when unspaced ternary is present. ([@tiagotex][]) * [#5155](https://github.com/bbatsov/rubocop/issues/5155): Fix a false negative for `Naming/ConstantName` cop when using frozen object assignment. ([@koic][]) * Fix a false positive in `Style/SafeNavigation` when the right hand side is negated. ([@rrosenblum][]) * [#5128](https://github.com/bbatsov/rubocop/issues/5128): Fix `Bundler/OrderedGems` when gems are references from variables (ignores them in the sorting). ([@tdeo][]) ### Changes * [#4848](https://github.com/bbatsov/rubocop/pull/4848): Exclude lambdas and procs from `Metrics/ParameterLists`. ([@reitermarkus][]) * [#5120](https://github.com/bbatsov/rubocop/pull/5120): Improve speed of RuboCop::PathUtil#smart_path. ([@walf443][]) * [#4888](https://github.com/bbatsov/rubocop/pull/4888): Improve offense message of `Style/StderrPuts`. ([@jaredbeck][]) * [#4886](https://github.com/bbatsov/rubocop/issues/4886): Fix false offense for Style/CommentedKeyword. ([@michniewicz][]) * [#4977](https://github.com/bbatsov/rubocop/pull/4977): Make `Lint/RedundantWithIndex` cop aware of offset argument. ([@koic][]) * [#2679](https://github.com/bbatsov/rubocop/issues/2679): Handle dependencies to `Metrics/LineLength: Max` when generating `.rubocop_todo.yml`. ([@jonas054][]) * [#4943](https://github.com/bbatsov/rubocop/pull/4943): Make cop generator compliant with the repo's rubocop config. ([@tdeo][]) * [#5011](https://github.com/bbatsov/rubocop/pull/5011): Remove `SupportedStyles` from "Configuration parameters" in `.rubocop_todo.yml`. ([@pocke][]) * `Lint/RescueWithoutErrorClass` has been replaced by `Style/RescueStandardError`. ([@rrosenblum][]) * [#4811](https://github.com/bbatsov/rubocop/issues/4811): Remove `Layout/SpaceInsideBrackets` in favor of two new configurable cops. ([@garettarrowood][]) * [#5042](https://github.com/bbatsov/rubocop/pull/5042): Make offense locations of metrics cops to contain whole a method. ([@pocke][]) * [#5044](https://github.com/bbatsov/rubocop/pull/5044): Add last_line and last_column into outputs of the JSON formatter. ([@pocke][]) * [#4633](https://github.com/bbatsov/rubocop/issues/4633): Make metrics cops aware of `define_method`. ([@pocke][]) * [#5037](https://github.com/bbatsov/rubocop/pull/5037): Make display cop names to enable by default. ([@pocke][]) * [#4449](https://github.com/bbatsov/rubocop/issues/4449): Make `Layout/IndentHeredoc` aware of line length. ([@pocke][]) * [#5146](https://github.com/bbatsov/rubocop/pull/5146): Make `--show-cops` option aware of `--force-default-config`. ([@pocke][]) * [#3001](https://github.com/bbatsov/rubocop/issues/3001): Add configuration to `Lint/MissingCopEnableDirective` cop. ([@tdeo][]) * [#4932](https://github.com/bbatsov/rubocop/issues/4932): Do not fail if configuration contains `Lint/Syntax` cop with the same settings as the default. ([@tdeo][]) * [#5175](https://github.com/bbatsov/rubocop/pull/5175): Make Style/RedundantBegin aware of do-end block in Ruby 2.5. ([@pocke][]) ## 0.51.0 (2017-10-18) ### New features * [#4791](https://github.com/bbatsov/rubocop/pull/4791): Add new `Rails/UnknownEnv` cop. ([@pocke][]) * [#4690](https://github.com/bbatsov/rubocop/issues/4690): Add new `Lint/UnneededRequireStatement` cop. ([@koic][]) * [#4813](https://github.com/bbatsov/rubocop/pull/4813): Add new `Style/StderrPuts` cop. ([@koic][]) * [#4796](https://github.com/bbatsov/rubocop/pull/4796): Add new `Lint/RedundantWithObject` cop. ([@koic][]) * [#4663](https://github.com/bbatsov/rubocop/issues/4663): Add new `Style/CommentedKeyword` cop. ([@donjar][]) * Add `IndentationWidth` configuration for `Layout/Tab` cop. ([@rrosenblum][]) * [#4854](https://github.com/bbatsov/rubocop/pull/4854): Add new `Lint/RegexpAsCondition` cop. ([@pocke][]) * [#4862](https://github.com/bbatsov/rubocop/pull/4862): Add `MethodDefinitionMacros` option to `Naming/PredicateName` cop. ([@koic][]) * [#4874](https://github.com/bbatsov/rubocop/pull/4874): Add new `Gemspec/OrderedDependencies` cop. ([@sue445][]) * [#4840](https://github.com/bbatsov/rubocop/pull/4840): Add new `Style/MixinUsage` cop. ([@koic][]) * [#1952](https://github.com/bbatsov/rubocop/issues/1952): Add new `Style/DateTime` cop. ([@dpostorivo][]) ### Bug fixes * [#3312](https://github.com/bbatsov/rubocop/issues/3312): Make `Rails/Date` Correct false positive on `#to_time` for strings ending in UTC-"Z".([@erikdstock][]) * [#4741](https://github.com/bbatsov/rubocop/issues/4741): Make `Style/SafeNavigation` correctly exclude methods called without dot. ([@drenmi][]) * [#4740](https://github.com/bbatsov/rubocop/issues/4740): Make `Lint/RescueWithoutErrorClass` aware of modifier form `rescue`. ([@drenmi][]) * [#4745](https://github.com/bbatsov/rubocop/issues/4745): Make `Style/SafeNavigation` ignore negated continuations. ([@drenmi][]) * [#4732](https://github.com/bbatsov/rubocop/issues/4732): Prevent `Performance/HashEachMethods` from registering an offense when `#each` follows `#to_a`. ([@drenmi][]) * [#4730](https://github.com/bbatsov/rubocop/issues/4730): False positive on Lint/InterpolationCheck. ([@koic][]) * [#4751](https://github.com/bbatsov/rubocop/issues/4751): Prevent `Rails/HasManyOrHasOneDependent` cop from registering offense if `:through` option was specified. ([@smakagon][]) * [#4737](https://github.com/bbatsov/rubocop/issues/4737): Fix ReturnInVoidContext cop when `return` is in top scope. ([@frodsan][]) * [#4776](https://github.com/bbatsov/rubocop/issues/4776): Non utf-8 magic encoding comments are now respected. ([@deivid-rodriguez][]) * [#4241](https://github.com/bbatsov/rubocop/issues/4241): Prevent `Rails/Blank` and `Rails/Present` from breaking when there is no explicit receiver. ([@rrosenblum][]) * [#4814](https://github.com/bbatsov/rubocop/issues/4814): Prevent `Rails/Blank` from breaking on send with an argument. ([@pocke][]) * [#4759](https://github.com/bbatsov/rubocop/issues/4759): Make `Naming/HeredocDelimiterNaming` and `Naming/HeredocDelimiterCase` aware of more delimiter patterns. ([@drenmi][]) * [#4823](https://github.com/bbatsov/rubocop/issues/4823): Make `Lint/UnusedMethodArgument` and `Lint/UnusedBlockArgument` aware of overriding assignments. ([@akhramov][]) * [#4830](https://github.com/bbatsov/rubocop/issues/4830): Prevent `Lint/BooleanSymbol` from truncating symbol's value in the message when offense is located in the new syntax hash. ([@akhramov][]) * [#4747](https://github.com/bbatsov/rubocop/issues/4747): Fix `Rails/HasManyOrHasOneDependent` cop incorrectly flags `with_options` blocks. ([@koic][]) * [#4836](https://github.com/bbatsov/rubocop/issues/4836): Make `Rails/OutputSafety` aware of safe navigation operator. ([@drenmi][]) * [#4843](https://github.com/bbatsov/rubocop/issues/4843): Make `Lint/ShadowedException` cop aware of same system error code. ([@koic][]) * [#4757](https://github.com/bbatsov/rubocop/issues/4757): Make `Style/TrailingUnderscoreVariable` work for nested assignments. ([@donjar][]) * [#4597](https://github.com/bbatsov/rubocop/pull/4597): Fix `Style/StringLiterals` cop not registering an offense on single quoted strings containing an escaped single quote when configured to use double quotes. ([@promisedlandt][]) * [#4850](https://github.com/bbatsov/rubocop/issues/4850): `Lint/UnusedMethodArgument` respects `IgnoreEmptyMethods` setting by ignoring unused method arguments for singleton methods. ([@jmks][]) * [#2040](https://github.com/bbatsov/rubocop/issues/2040): Document how to write a custom cop. ([@jonatas][]) ### Changes * [#4746](https://github.com/bbatsov/rubocop/pull/4746): The `Lint/InvalidCharacterLiteral` cop has been removed since it was never being actually triggered. ([@deivid-rodriguez][]) * [#4789](https://github.com/bbatsov/rubocop/pull/4789): Analyzing code that needs to support MRI 1.9 is no longer supported. ([@deivid-rodriguez][]) * [#4582](https://github.com/bbatsov/rubocop/issues/4582): `Severity` and other common parameters can be configured on department level. ([@jonas054][]) * [#4787](https://github.com/bbatsov/rubocop/pull/4787): Analyzing code that needs to support MRI 2.0 is no longer supported. ([@deivid-rodriguez][]) * [#4787](https://github.com/bbatsov/rubocop/pull/4787): RuboCop no longer installs on MRI 2.0. ([@deivid-rodriguez][]) * [#4266](https://github.com/bbatsov/rubocop/issues/4266): Download the inherited config files of a remote file from the same remote. ([@tdeo][]) * [#4853](https://github.com/bbatsov/rubocop/pull/4853): Make `Lint/LiteralInCondition` cop aware of `!` and `not`. ([@pocke][]) * [#4864](https://github.com/bbatsov/rubocop/pull/4864): Rename `Lint/LiteralInCondition` to `Lint/LiteralAsCondition`. ([@pocke][]) ## 0.50.0 (2017-09-14) ### New features * [#4464](https://github.com/bbatsov/rubocop/pull/4464): Add `EnforcedStyleForEmptyBraces` parameter to `Layout/SpaceBeforeBlockBraces` cop. ([@palkan][]) * [#4453](https://github.com/bbatsov/rubocop/pull/4453): New cop `Style/RedundantConditional` checks for conditionals that return true/false. ([@petehamilton][]) * [#4448](https://github.com/bbatsov/rubocop/pull/4448): Add new `TapFormatter`. ([@cyberdelia][]) * [#4467](https://github.com/bbatsov/rubocop/pull/4467): Add new `Style/HeredocDelimiters` cop(Note: This cop was renamed to `Naming/HeredocDelimiterNaming`). ([@drenmi][]) * [#4153](https://github.com/bbatsov/rubocop/issues/4153): New cop `Lint/ReturnInVoidContext` checks for the use of a return with a value in a context where it will be ignored. ([@harold-s][]) * [#4506](https://github.com/bbatsov/rubocop/pull/4506): Add auto-correct support to `Lint/ScriptPermission`. ([@rrosenblum][]) * [#4514](https://github.com/bbatsov/rubocop/pull/4514): Add configuration options to `Style/YodaCondition` to support checking all comparison operators or equality operators only. ([@smakagon][]) * [#4515](https://github.com/bbatsov/rubocop/pull/4515): Add new `Lint/BooleanSymbol` cop. ([@droptheplot][]) * [#4535](https://github.com/bbatsov/rubocop/pull/4535): Make `Rails/PluralizationGrammar` use singular methods for `-1` / `-1.0`. ([@promisedlandt][]) * [#4541](https://github.com/bbatsov/rubocop/pull/4541): Add new `Rails/HasManyOrHasOneDependent` cop. ([@oboxodo][]) * [#4552](https://github.com/bbatsov/rubocop/pull/4552): Add new `Style/Dir` cop. ([@drenmi][]) * [#4548](https://github.com/bbatsov/rubocop/pull/4548): Add new `Style/HeredocDelimiterCase` cop(Note: This cop is renamed to `Naming/HeredocDelimiterCase`). ([@drenmi][]) * [#2943](https://github.com/bbatsov/rubocop/pull/2943): Add new `Lint/RescueWithoutErrorClass` cop. ([@drenmi][]) * [#4568](https://github.com/bbatsov/rubocop/pull/4568): Fix autocorrection for `Style/TrailingUnderscoreVariable`. ([@smakagon][]) * [#4586](https://github.com/bbatsov/rubocop/pull/4586): Add new `Performance/UnfreezeString` cop. ([@pocke][]) * [#2976](https://github.com/bbatsov/rubocop/issues/2976): Add `Whitelist` configuration option to `Style/NestedParenthesizedCalls` cop. ([@drenmi][]) * [#3965](https://github.com/bbatsov/rubocop/issues/3965): Add new `Style/OrAssignment` cop. ([@donjar][]) * [#4655](https://github.com/bbatsov/rubocop/pull/4655): Make `rake new_cop` create parent directories if they do not already exist. ([@highb][]) * [#4368](https://github.com/bbatsov/rubocop/issues/4368): Make `Performance/HashEachMethod` inspect send nodes with any receiver. ([@gohdaniel15][]) * [#4508](https://github.com/bbatsov/rubocop/issues/4508): Add new `Style/ReturnNil` cop. ([@donjar][]) * [#4629](https://github.com/bbatsov/rubocop/issues/4629): Add Metrics/MethodLength cop for `define_method`. ([@jekuta][]) * [#4702](https://github.com/bbatsov/rubocop/pull/4702): Add new `Lint/UriEscapeUnescape` cop. ([@koic][]) * [#4696](https://github.com/bbatsov/rubocop/pull/4696): Add new `Performance/UriDefaultParser` cop. ([@koic][]) * [#4694](https://github.com/bbatsov/rubocop/pull/4694): Add new `Lint/UriRegexp` cop. ([@koic][]) * [#4711](https://github.com/bbatsov/rubocop/pull/4711): Add new `Style/MinMax` cop. ([@drenmi][]) * [#4720](https://github.com/bbatsov/rubocop/pull/4720): Add new `Bundler/InsecureProtocolSource` cop. ([@koic][]) * [#4708](https://github.com/bbatsov/rubocop/pull/4708): Add new `Lint/RedundantWithIndex` cop. ([@koic][]) * [#4480](https://github.com/bbatsov/rubocop/pull/4480): Add new `Lint/InterpolationCheck` cop. ([@GauthamGoli][]) * [#4628](https://github.com/bbatsov/rubocop/issues/4628): Add new `Lint/NestedPercentLiteral` cop. ([@asherkach][]) ### Bug fixes * [#4709](https://github.com/bbatsov/rubocop/pull/4709): Use cached remote config on network failure. ([@kristjan][]) * [#4688](https://github.com/bbatsov/rubocop/pull/4688): Accept yoda condition which isn't commutative. ([@fujimura][]) * [#4676](https://github.com/bbatsov/rubocop/issues/4676): Make `Style/RedundantConditional` cop work with elsif. ([@akhramov][]) * [#4656](https://github.com/bbatsov/rubocop/issues/4656): Modify `Style/ConditionalAssignment` autocorrection to work with unbracketed arrays. ([@akhramov][]) * [#4615](https://github.com/bbatsov/rubocop/pull/4615): Don't consider `<=>` a comparison method. ([@iGEL][]) * [#4664](https://github.com/bbatsov/rubocop/pull/4664): Fix typos in Rails/HttpPositionalArguments. ([@JoeCohen][]) * [#4618](https://github.com/bbatsov/rubocop/pull/4618): Fix `Lint/FormatParameterMismatch` false positive if format string includes `%%5B` (CGI encoded left bracket). ([@barthez][]) * [#4604](https://github.com/bbatsov/rubocop/pull/4604): Fix `Style/LambdaCall` to autocorrect `obj.call` to `obj.`. ([@iGEL][]) * [#4443](https://github.com/bbatsov/rubocop/pull/4443): Prevent `Style/YodaCondition` from breaking `not LITERAL`. ([@pocke][]) * [#4434](https://github.com/bbatsov/rubocop/issues/4434): Prevent bad auto-correct in `Style/Alias` for non-literal arguments. ([@drenmi][]) * [#4451](https://github.com/bbatsov/rubocop/issues/4451): Make `Style/AndOr` cop aware of comparison methods. ([@drenmi][]) * [#4457](https://github.com/bbatsov/rubocop/pull/4457): Fix false negative in `Lint/Void` with initialize and setter methods. ([@pocke][]) * [#4418](https://github.com/bbatsov/rubocop/issues/4418): Register an offense in `Style/ConditionalAssignment` when the assignment line is the longest line, and it does not exceed the max line length. ([@rrosenblum][]) * [#4491](https://github.com/bbatsov/rubocop/issues/4491): Prevent bad auto-correct in `Style/EmptyElse` for nested `if`. ([@pocke][]) * [#4485](https://github.com/bbatsov/rubocop/pull/4485): Handle 304 status for remote config files. ([@daniloisr][]) * [#4529](https://github.com/bbatsov/rubocop/pull/4529): Make `Lint/UnreachableCode` aware of `if` and `case`. ([@pocke][]) * [#4469](https://github.com/bbatsov/rubocop/issues/4469): Include permissions in file cache. ([@pocke][]) * [#4270](https://github.com/bbatsov/rubocop/issues/4270): Fix false positive in `Performance/RegexpMatch` for named captures. ([@pocke][]) * [#4525](https://github.com/bbatsov/rubocop/pull/4525): Fix regexp for checking comment config of `rubocop:disable all` in `Lint/UnneededDisable`. ([@meganemura][]) * [#4555](https://github.com/bbatsov/rubocop/issues/4555): Make `Style/VariableName` aware of optarg, kwarg and other arguments. ([@pocke][]) * [#4481](https://github.com/bbatsov/rubocop/issues/4481): Prevent `Style/WordArray` and `Style/SymbolArray` from registering offenses where percent arrays don't work. ([@drenmi][]) * [#4447](https://github.com/bbatsov/rubocop/issues/4447): Prevent `Layout/EmptyLineBetweenDefs` from removing too many lines. ([@drenmi][]) * [#3892](https://github.com/bbatsov/rubocop/issues/3892): Make `Style/NumericPredicate` ignore numeric comparison of global variables. ([@drenmi][]) * [#4101](https://github.com/bbatsov/rubocop/issues/4101): Skip auto-correct for literals with trailing comment and chained method call in `Layout/Multiline*BraceLayout`. ([@jonas054][]) * [#4518](https://github.com/bbatsov/rubocop/issues/4518): Fix bug where `Style/SafeNavigation` does not register an offense when there are chained method calls. ([@rrosenblum][]) * [#3040](https://github.com/bbatsov/rubocop/issues/3040): Ignore safe navigation in `Rails/Delegate`. ([@cgriego][]) * [#4587](https://github.com/bbatsov/rubocop/pull/4587): Fix false negative for void unary operators in `Lint/Void` cop. ([@pocke][]) * [#4589](https://github.com/bbatsov/rubocop/issues/4589): Fix false positive in `Performance/RegexpMatch` cop for `=~` is in a class method. ([@pocke][]) * [#4578](https://github.com/bbatsov/rubocop/issues/4578): Fix false positive in `Lint/FormatParameterMismatch` for format with "asterisk" (`*`) width and precision. ([@smakagon][]) * [#4285](https://github.com/bbatsov/rubocop/issues/4285): Make `Lint/DefEndAlignment` aware of multiple modifiers. ([@drenmi][]) * [#4634](https://github.com/bbatsov/rubocop/issues/4634): Handle heredoc that contains empty lines only in `Layout/IndentHeredoc` cop. ([@pocke][]) * [#4646](https://github.com/bbatsov/rubocop/issues/4646): Make `Lint/Debugger` aware of `Kernel` and cbase. ([@pocke][]) * [#4643](https://github.com/bbatsov/rubocop/issues/4643): Modify `Style/InverseMethods` to not register a separate offense for an inverse method nested inside of the block of an inverse method offense. ([@rrosenblum][]) * [#4593](https://github.com/bbatsov/rubocop/issues/4593): Fix false positive in `Rails/SaveBang` when `save/update_attribute` is used with a `case` statement. ([@theRealNG][]) * [#4322](https://github.com/bbatsov/rubocop/issues/4322): Fix Style/MultilineMemoization from autocorrecting to invalid ruby. ([@dpostorivo][]) * [#4722](https://github.com/bbatsov/rubocop/pull/4722): Fix `rake new_cop` problem that doesn't add `require` line. ([@koic][]) * [#4723](https://github.com/bbatsov/rubocop/issues/4723): Fix `RaiseArgs` auto-correction issue for `raise` with 3 arguments. ([@smakagon][]) ### Changes * [#4470](https://github.com/bbatsov/rubocop/issues/4470): Improve the error message for `Lint/AssignmentInCondition`. ([@brandonweiss][]) * [#4553](https://github.com/bbatsov/rubocop/issues/4553): Add `node_modules` to default excludes. ([@iainbeeston][]) * [#4445](https://github.com/bbatsov/rubocop/pull/4445): Make `Style/Encoding` cop enabled by default. ([@deivid-rodriguez][]) * [#4452](https://github.com/bbatsov/rubocop/pull/4452): Add option to `Rails/Delegate` for enforcing the prefixed method name case. ([@klesse413][]) * [#4493](https://github.com/bbatsov/rubocop/pull/4493): Make `Lint/Void` cop aware of `Enumerable#each` and `for`. ([@pocke][]) * [#4492](https://github.com/bbatsov/rubocop/pull/4492): Make `Lint/DuplicateMethods` aware of `alias` and `alias_method`. ([@pocke][]) * [#4478](https://github.com/bbatsov/rubocop/issues/4478): Fix confusing message of `Performance/Caller` cop. ([@pocke][]) * [#4543](https://github.com/bbatsov/rubocop/pull/4543): Make `Lint/DuplicateMethods` aware of `attr_*` methods. ([@pocke][]) * [#4550](https://github.com/bbatsov/rubocop/pull/4550): Mark `RuboCop::CLI#run` as a public API. ([@yujinakayama][]) * [#4551](https://github.com/bbatsov/rubocop/pull/4551): Make `Performance/Caller` aware of `caller_locations`. ([@pocke][]) * [#4547](https://github.com/bbatsov/rubocop/pull/4547): Rename `Style/HeredocDelimiters` to `Style/HeredocDelimiterNaming`. ([@drenmi][]) * [#4157](https://github.com/bbatsov/rubocop/issues/4157): Enhance offense message for `Style/RedudantReturn` cop. ([@gohdaniel15][]) * [#4521](https://github.com/bbatsov/rubocop/issues/4521): Move naming related cops into their own `Naming` department. ([@drenmi][]) * [#4600](https://github.com/bbatsov/rubocop/pull/4600): Make `Style/RedundantSelf` aware of arguments of a block. ([@Envek][]) * [#4658](https://github.com/bbatsov/rubocop/issues/4658): Disable auto-correction for `Performance/TimesMap` by default. ([@Envek][]) ## 0.49.1 (2017-05-29) ### Bug fixes * [#4411](https://github.com/bbatsov/rubocop/issues/4411): Handle properly safe navigation in `Style/YodaCondition`. ([@bbatsov][]) * [#4412](https://github.com/bbatsov/rubocop/issues/4412): Handle properly literal comparisons in `Style/YodaCondition`. ([@bbatsov][]) * Handle properly class variables and global variables in `Style/YodaCondition`. ([@bbatsov][]) * [#4392](https://github.com/bbatsov/rubocop/issues/4392): Fix the auto-correct of `Style/Next` when the `end` is misaligned. ([@rrosenblum][]) * [#4407](https://github.com/bbatsov/rubocop/issues/4407): Prevent `Performance/RegexpMatch` from blowing up on `match` without arguments. ([@pocke][]) * [#4414](https://github.com/bbatsov/rubocop/issues/4414): Handle pseudo-assignments in `for` loops in `Style/ConditionalAssignment`. ([@bbatsov][]) * [#4419](https://github.com/bbatsov/rubocop/issues/4419): Handle combination `AllCops: DisabledByDefault: true` and `Rails: Enabled: true`. ([@jonas054][]) * [#4422](https://github.com/bbatsov/rubocop/issues/4422): Fix missing space in message for `Style/MultipleComparison`. ([@timrogers][]) * [#4420](https://github.com/bbatsov/rubocop/issues/4420): Ensure `Style/EmptyMethod` honours indentation when auto-correcting. ([@drenmi][]) * [#4442](https://github.com/bbatsov/rubocop/pull/4442): Prevent `Style/WordArray` from breaking on strings that aren't valid UTF-8. ([@pocke][]) * [#4441](https://github.com/bbatsov/rubocop/pull/4441): Prevent `Layout/SpaceAroundBlockParameters` from breaking on lambda. ([@pocke][]) ### Changes * [#4436](https://github.com/bbatsov/rubocop/pull/4436): Display 'Running parallel inspection' only with --debug. ([@pocke][]) ## 0.49.0 (2017-05-24) ### New features * [#117](https://github.com/bbatsov/rubocop/issues/117): Add `--parallel` option for running RuboCop in multiple processes or threads. ([@jonas054][]) * Add auto-correct support to `Style/MixinGrouping`. ([@rrosenblum][]) * [#4236](https://github.com/bbatsov/rubocop/issues/4236): Add new `Rails/ApplicationJob` and `Rails/ApplicationRecord` cops. ([@tjwp][]) * [#4078](https://github.com/bbatsov/rubocop/pull/4078): Add new `Performance/Caller` cop. ([@alpaca-tc][]) * [#4314](https://github.com/bbatsov/rubocop/pull/4314): Check slow hash accessing in `Array#sort` by `Performance/CompareWithBlock`. ([@pocke][]) * [#3438](https://github.com/bbatsov/rubocop/issues/3438): Add new `Style/FormatStringToken` cop. ([@backus][]) * [#4342](https://github.com/bbatsov/rubocop/pull/4342): Add new `Lint/ScriptPermission` cop. ([@yhirano55][]) * [#4145](https://github.com/bbatsov/rubocop/issues/4145): Add new `Style/YodaCondition` cop. ([@smakagon][]) * [#4403](https://github.com/bbatsov/rubocop/pull/4403): Add public API `Cop.autocorrect_incompatible_with` for specifying other cops that should not autocorrect together. ([@backus][]) * [#4354](https://github.com/bbatsov/rubocop/pull/4354): Add autocorrect to `Style/FormatString`. ([@hoshinotsuyoshi][]) * [#4021](https://github.com/bbatsov/rubocop/pull/4021): Add new `Style/MultipleComparison` cop. ([@dabroz][]) * New `Lint/RescueType` cop. ([@rrosenblum][]) * [#4328](https://github.com/bbatsov/rubocop/issues/4328): Add `--ignore-parent-exclusion` flag to ignore AllCops/Exclude inheritance. ([@nelsonjr][]) ### Changes * [#4262](https://github.com/bbatsov/rubocop/pull/4262): Add new `MinSize` configuration to `Style/SymbolArray`, consistent with the same configuration in `Style/WordArray`. ([@scottmatthewman][]) * [#3400](https://github.com/bbatsov/rubocop/issues/3400): Remove auto-correct support from Lint/Debugger. ([@ilansh][]) * [#4278](https://github.com/bbatsov/rubocop/pull/4278): Move all cops dealing with whitespace into a new department called `Layout`. ([@jonas054][]) * [#4320](https://github.com/bbatsov/rubocop/pull/4320): Update `Rails/OutputSafety` to disallow wrapping `raw` or `html_safe` with `safe_join`. ([@klesse413][]) * [#4336](https://github.com/bbatsov/rubocop/issues/4336): Store `rubocop_cache` in safer directories. ([@jonas054][]) * [#4361](https://github.com/bbatsov/rubocop/pull/4361): Use relative path for offense message in `Lint/DuplicateMethods`. ([@pocke][]) * [#4385](https://github.com/bbatsov/rubocop/pull/4385): Include `.jb` file by default. ([@pocke][]) ### Bug fixes * [#4265](https://github.com/bbatsov/rubocop/pull/4265): Require a space before first argument of a method call in `Style/SpaceBeforeFirstArg` cop. ([@cjlarose][]) * [#4237](https://github.com/bbatsov/rubocop/pull/4237): Fix false positive in `Lint/AmbiguousBlockAssociation` cop for lambdas. ([@smakagon][]) * [#4242](https://github.com/bbatsov/rubocop/issues/4242): Add `Capfile` to the list of known Ruby filenames. ([@bbatsov][]) * [#4240](https://github.com/bbatsov/rubocop/issues/4240): Handle `||=` in `Rails/RelativeDateConstant`. ([@bbatsov][]) * [#4241](https://github.com/bbatsov/rubocop/issues/4241): Prevent `Rails/Blank` and `Rails/Present` from breaking when there is no explicit receiver. ([@rrosenblum][]) * [#4249](https://github.com/bbatsov/rubocop/issues/4249): Handle multiple assignment in `Rails/RelativeDateConstant`. ([@bbatsov][]) * [#4250](https://github.com/bbatsov/rubocop/issues/4250): Improve a bit the Ruby code detection config. ([@bbatsov][]) * [#4283](https://github.com/bbatsov/rubocop/issues/4283): Fix `Style/EmptyCaseCondition` autocorrect bug - when first `when` branch includes comma-delimited alternatives. ([@ilansh][]) * [#4268](https://github.com/bbatsov/rubocop/issues/4268): Handle end-of-line comments when autocorrecting Style/EmptyLinesAroundAccessModifier. ([@vergenzt][]) * [#4275](https://github.com/bbatsov/rubocop/issues/4275): Prevent `Style/MethodCallWithArgsParentheses` from blowing up on `yield`. ([@drenmi][]) * [#3969](https://github.com/bbatsov/rubocop/issues/3969): Handle multiline method call alignment for arguments to methods. ([@jonas054][]) * [#4304](https://github.com/bbatsov/rubocop/pull/4304): Allow enabling whole departments when `DisabledByDefault` is `true`. ([@jonas054][]) * [#4264](https://github.com/bbatsov/rubocop/issues/4264): Prevent `Rails/SaveBang` from blowing up when using the assigned variable in a hash. ([@drenmi][]) * [#4310](https://github.com/bbatsov/rubocop/pull/4310): Treat paths containing invalid byte sequences as non-matches. ([@mclark][]) * [#4063](https://github.com/bbatsov/rubocop/issues/4063): Fix Rails/ReversibleMigration misdetection. ([@gprado][]) * [#4339](https://github.com/bbatsov/rubocop/pull/4339): Fix false positive in `Security/Eval` cop for multiline string lietral. ([@pocke][]) * [#4339](https://github.com/bbatsov/rubocop/pull/4339): Fix false negative in `Security/Eval` cop for `Binding#eval`. ([@pocke][]) * [#4327](https://github.com/bbatsov/rubocop/issues/4327): Prevent `Layout/SpaceInsidePercentLiteralDelimiters` from registering offenses on execute-strings. ([@drenmi][]) * [#4371](https://github.com/bbatsov/rubocop/issues/4371): Prevent `Style/MethodName` from complaining about unary operator definitions. ([@drenmi][]) * [#4366](https://github.com/bbatsov/rubocop/issues/4366): Prevent `Performance/RedundantMerge` from blowing up on double splat arguments. ([@drenmi][]) * [#4352](https://github.com/bbatsov/rubocop/issues/4352): Fix the auto-correct of `Style/AndOr` when Enumerable accessors (`[]`) are used. ([@rrosenblum][]) * [#4393](https://github.com/bbatsov/rubocop/issues/4393): Prevent `Style/InverseMethods` from registering an offense for methods that are double negated. ([@rrosenblum][]) * [#4394](https://github.com/bbatsov/rubocop/issues/4394): Prevent some cops from breaking on safe navigation operator. ([@drenmi][]) * [#4260](https://github.com/bbatsov/rubocop/issues/4260): Prevent `Rails/SkipsModelValidations` from registering an offense for `FileUtils.touch`. ([@rrosenblum][]) ## 0.48.1 (2017-04-03) ### Changes * [#4219](https://github.com/bbatsov/rubocop/issues/4219): Add a link to style guide for `Style/IndentationConsistency` cop. ([@pocke][]) * [#4168](https://github.com/bbatsov/rubocop/issues/4168): Removed `-n` option. ([@sadovnik][]) * [#4039](https://github.com/bbatsov/rubocop/pull/4039): Change `Style/PercentLiteralDelimiters` default configuration to match Style Guide update. ([@drenmi][]) * [#4235](https://github.com/bbatsov/rubocop/pull/4235): Improved copy of offense message in `Lint/AmbiguousBlockAssociation` cop. ([@smakagon][]) ### Bug fixes * [#4171](https://github.com/bbatsov/rubocop/pull/4171): Prevent `Rails/Blank` from breaking when RHS of `or` is a naked falsiness check. ([@drenmi][]) * [#4189](https://github.com/bbatsov/rubocop/pull/4189): Make `Lint/AmbiguousBlockAssociation` aware of lambdas passed as arguments. ([@drenmi][]) * [#4179](https://github.com/bbatsov/rubocop/pull/4179): Prevent `Rails/Blank` from breaking when LHS of `or` is a naked falsiness check. ([@rrosenblum][]) * [#4172](https://github.com/bbatsov/rubocop/pull/4172): Fix false positives in `Style/MixinGrouping` cop. ([@drenmi][]) * [#4185](https://github.com/bbatsov/rubocop/pull/4185): Make `Lint/NestedMethodDefinition` aware of `#*_exec` class of methods. ([@drenmi][]) * [#4197](https://github.com/bbatsov/rubocop/pull/4197): Fix false positive in `Style/RedundantSelf` cop with parallel assignment. ([@drenmi][]) * [#4199](https://github.com/bbatsov/rubocop/issues/4199): Fix incorrect auto correction in `Style/SymbolArray` and `Style/WordArray` cop. ([@pocke][]) * [#4218](https://github.com/bbatsov/rubocop/pull/4218): Make `Lint/NestedMethodDefinition` aware of class shovel scope. ([@drenmi][]) * [#4198](https://github.com/bbatsov/rubocop/pull/4198): Make `Lint/AmbguousBlockAssociation` aware of operator methods. ([@drenmi][]) * [#4152](https://github.com/bbatsov/rubocop/pull/4152): Make `Style/MethodCallWithArgsParentheses` not require parens on setter methods. ([@drenmi][]) * [#4226](https://github.com/bbatsov/rubocop/pull/4226): Show in `--help` output that `--stdin` takes a file name argument. ([@jonas054][]) * [#4217](https://github.com/bbatsov/rubocop/pull/4217): Fix false positive in `Rails/FilePath` cop with non string argument. ([@soutaro][]) * [#4106](https://github.com/bbatsov/rubocop/pull/4106): Make `Style/TernaryParentheses` unsafe autocorrect detector aware of literals and constants. ([@drenmi][]) * [#4228](https://github.com/bbatsov/rubocop/pull/4228): Fix false positive in `Lint/AmbiguousBlockAssociation` cop. ([@smakagon][]) * [#4234](https://github.com/bbatsov/rubocop/pull/4234): Fix false positive in `Rails/RelativeDate` for lambdas and procs. ([@smakagon][]) ## 0.48.0 (2017-03-26) ### New features * [#4107](https://github.com/bbatsov/rubocop/pull/4107): New `TargetRailsVersion` configuration parameter can be used to specify which version of Rails the inspected code is intended to run on. ([@maxbeizer][]) * [#4104](https://github.com/bbatsov/rubocop/pull/4104): Add `prefix` and `postfix` styles to `Style/NegatedIf`. ([@brandonweiss][]) * [#4083](https://github.com/bbatsov/rubocop/pull/4083): Add new configuration `NumberOfEmptyLines` for `Style/EmptyLineBetweenDefs`. ([@dorian][]) * [#4045](https://github.com/bbatsov/rubocop/pull/4045): Add new configuration `Strict` for `Style/NumericLiteral` to make the change to this cop in 0.47.0 configurable. ([@iGEL][]) * [#4005](https://github.com/bbatsov/rubocop/issues/4005): Add new `AllCops/EnabledByDefault` option. ([@betesh][]) * [#3893](https://github.com/bbatsov/rubocop/issues/3893): Add a new configuration, `IncludeActiveSupportAliases`, to `Performance/DoublStartEndWith`. This configuration will check for ActiveSupport's `starts_with?` and `ends_with?`. ([@rrosenblum][]) * [#3889](https://github.com/bbatsov/rubocop/pull/3889): Add new `Style/EmptyLineAfterMagicComment` cop. ([@backus][]) * [#3800](https://github.com/bbatsov/rubocop/issues/3800): Make `Style/EndOfLine` configurable with `lf`, `crlf`, and `native` (default) styles. ([@jonas054][]) * [#3936](https://github.com/bbatsov/rubocop/issues/3936): Add new `Style/MixinGrouping` cop. ([@drenmi][]) * [#4003](https://github.com/bbatsov/rubocop/issues/4003): Add new `Rails/RelativeDateConstant` cop. ([@sinsoku][]) * [#3984](https://github.com/bbatsov/rubocop/pull/3984): Add new `Style/EmptyLinesAroundBeginBody` cop. ([@pocke][]) * [#3995](https://github.com/bbatsov/rubocop/pull/3995): Add new `Style/EmptyLinesAroundExceptionHandlingKeywords` cop. ([@pocke][]) * [#4019](https://github.com/bbatsov/rubocop/pull/4019): Make configurable `Style/MultilineMemoization` cop. ([@pocke][]) * [#4018](https://github.com/bbatsov/rubocop/pull/4018): Add autocorrect `Lint/EmptyEnsure` cop. ([@pocke][]) * [#4028](https://github.com/bbatsov/rubocop/pull/4028): Add new `Style/IndentHeredoc` cop. ([@pocke][]) * [#3931](https://github.com/bbatsov/rubocop/issues/3931): Add new `Lint/AmbiguousBlockAssociation` cop. ([@smakagon][]) * Add new `Style/InverseMethods` cop. ([@rrosenblum][]) * [#4038](https://github.com/bbatsov/rubocop/pull/4038): Allow `default` key in the `Style/PercentLiteralDelimiters` cop config to set all preferred delimiters. ([@kddeisz][]) * Add `IgnoreMacros` option to `Style/MethodCallWithArgsParentheses`. ([@drenmi][]) * [#3937](https://github.com/bbatsov/rubocop/issues/3937): Add new `Rails/ActiveSupportAliases` cop. ([@tdeo][]) * Add new `Rails/Blank` cop. ([@rrosenblum][]) * Add new `Rails/Present` cop. ([@rrosenblum][]) * [#4004](https://github.com/bbatsov/rubocop/issues/4004): Allow not treating comment lines as group separators in `Bundler/OrderedGems` cop. ([@konto-andrzeja][]) ### Changes * [#4100](https://github.com/bbatsov/rubocop/issues/4100): Rails/SaveBang should flag `update_attributes`. ([@andriymosin][]) * [#4083](https://github.com/bbatsov/rubocop/pull/4083): `Style/EmptyLineBetweenDefs` doesn't allow more than one empty line between method definitions by default (see `NumberOfEmptyLines`). ([@dorian][]) * [#3997](https://github.com/bbatsov/rubocop/pull/3997): Include all ruby files by default and exclude non-ruby files. ([@dorian][]) * [#4012](https://github.com/bbatsov/rubocop/pull/4012): Mark `foo[:bar]` as not complex in `Style/TernaryParentheses` cop with `require_parentheses_when_complex` style. ([@onk][]) * [#3915](https://github.com/bbatsov/rubocop/issues/3915): Make configurable whitelist for `Lint/SafeNavigationChain` cop. ([@pocke][]) * [#3944](https://github.com/bbatsov/rubocop/issues/3944): Allow keyword arguments in `Style/RaiseArgs` cop. ([@mikegee][]) * Add auto-correct to `Performance/DoubleStartEndWith`. ([@rrosenblum][]) * [#3951](https://github.com/bbatsov/rubocop/pull/3951): Make `Rails/Date` cop to register an offence for a string without timezone. ([@sinsoku][]) * [#4020](https://github.com/bbatsov/rubocop/pull/4020): Fixed `new_cop.rake` suggested path. ([@dabroz][]) * [#4055](https://github.com/bbatsov/rubocop/pull/4055): Add parameters count to offense message for `Metrics/ParameterLists` cop. ([@pocke][]) * [#4081](https://github.com/bbatsov/rubocop/pull/4081): Allow `Marshal.load` if argument is a `Marshal.dump` in `Security/MarshalLoad` cop. ([@droptheplot][]) * [#4124](https://github.com/bbatsov/rubocop/issues/4124): Make `Style/SymbolArray` cop to enable by default. ([@pocke][]) * [#3331](https://github.com/bbatsov/rubocop/issues/3331): Change `Style/MultilineMethodCallIndentation` `indented_relative_to_receiver` to indent relative to the receiver and not relative to the caller. ([@jfelchner][]) * [#4137](https://github.com/bbatsov/rubocop/pull/4137): Allow lines to be exempted from `IndentationWidth` by regex. ([@jfelchner][]) ### Bug fixes * [#4007](https://github.com/bbatsov/rubocop/pull/4007): Skip `Rails/SkipsModelValidations` for methods that don't accept arguments. ([@dorian][]) * [#3923](https://github.com/bbatsov/rubocop/issues/3923): Allow asciibetical sorting in `Bundler/OrderedGems`. ([@mikegee][]) * [#3855](https://github.com/bbatsov/rubocop/issues/3855): Make `Lint/NonLocalExitFromIterator` aware of method definitions. ([@drenmi][]) * [#2643](https://github.com/bbatsov/rubocop/issues/2643): Allow uppercase and dashes in `MagicComment`. ([@mikegee][]) * [#3959](https://github.com/bbatsov/rubocop/issues/3959): Don't wrap "percent arrays" with extra brackets when autocorrecting `Style/MutableConstant`. ([@mikegee][]) * [#3978](https://github.com/bbatsov/rubocop/pull/3978): Fix false positive in `Performance/RegexpMatch` with `English` module. ([@pocke][]) * [#3242](https://github.com/bbatsov/rubocop/issues/3242): Ignore `Errno::ENOENT` during cache cleanup from `File.mtime` too. ([@mikegee][]) * [#3958](https://github.com/bbatsov/rubocop/issues/3958): `Style/SpaceInsideHashLiteralBraces` doesn't add and offence when checking an hash where a value is a left brace string (e.g. { k: '{' }). ([@nodo][]) * [#4006](https://github.com/bbatsov/rubocop/issues/4006): Prevent `Style/WhileUntilModifier` from breaking on a multiline modifier. ([@drenmi][]) * [#3345](https://github.com/bbatsov/rubocop/issues/3345): Allow `Style/WordArray`'s `WordRegex` configuration value to be an instance of `String`. ([@mikegee][]) * [#4013](https://github.com/bbatsov/rubocop/pull/4013): Follow redirects for RemoteConfig. ([@buenaventure][]) * [#3917](https://github.com/bbatsov/rubocop/issues/3917): Rails/FilePath Match nodes in a method call only once. ([@unmanbearpig][]) * [#3673](https://github.com/bbatsov/rubocop/issues/3673): Fix regression on `Style/RedundantSelf` when assigning to same local variable. ([@bankair][]) * [#4047](https://github.com/bbatsov/rubocop/issues/4047): Allow `find_zone` and `find_zone!` methods in `Rails/TimeZone`. ([@attilahorvath][]) * [#3457](https://github.com/bbatsov/rubocop/issues/3457): Clear a warning and prevent new warnings. ([@mikegee][]) * [#4066](https://github.com/bbatsov/rubocop/issues/4066): Register an offense in `Lint/ShadowedException` when an exception is shadowed and there is an implicit begin. ([@rrosenblum][]) * [#4001](https://github.com/bbatsov/rubocop/issues/4001): Lint/UnneededDisable of Metrics/LineLength that isn't unneeded. ([@wkurniawan07][]) * [#3960](https://github.com/bbatsov/rubocop/issues/3960): Let `Include`/`Exclude` paths in all files beginning with `.rubocop` be relative to the configuration file's directory and not to the current directory. ([@jonas054][]) * [#4049](https://github.com/bbatsov/rubocop/pull/4049): Bugfix for `Style/EmptyLiteral` cop. ([@ota42y][]) * [#4112](https://github.com/bbatsov/rubocop/pull/4112): Fix false positives about double quotes in `Style/StringLiterals`, `Style/UnneededCapitalW` and `Style/UnneededPercentQ` cops. ([@pocke][]) * [#4109](https://github.com/bbatsov/rubocop/issues/4109): Fix incorrect auto correction in `Style/SelfAssignment` cop. ([@pocke][]) * [#4110](https://github.com/bbatsov/rubocop/issues/4110): Fix incorrect auto correction in `Style/BracesAroundHashParameters` cop. ([@musialik][]) * [#4084](https://github.com/bbatsov/rubocop/issues/4084): Fix incorrect auto correction in `Style/TernaryParentheses` cop. ([@musialik][]) * [#4102](https://github.com/bbatsov/rubocop/issues/4102): Fix `Security/JSONLoad`, `Security/MarshalLoad` and `Security/YAMLLoad` cops patterns not matching ::Const. ([@musialik][]) * [#3580](https://github.com/bbatsov/rubocop/issues/3580): Handle combinations of `# rubocop:disable all` and `# rubocop:disable SomeCop`. ([@jonas054][]) * [#4124](https://github.com/bbatsov/rubocop/issues/4124): Fix auto correction bugs in `Style/SymbolArray` cop. ([@pocke][]) * [#4128](https://github.com/bbatsov/rubocop/issues/4128): Prevent `Style/CaseIndentation` cop from registering offenses on single-line case statements. ([@drenmi][]) * [#4143](https://github.com/bbatsov/rubocop/issues/4143): Prevent `Style/IdenticalConditionalBranches` from registering offenses when a case statement has an empty when. ([@dpostorivo][]) * [#4160](https://github.com/bbatsov/rubocop/pull/4160): Fix a regression where `UselessAssignment` cop may not properly detect useless assignments when there's only a single conditional expression in the top level scope. ([@yujinakayama][]) * [#4162](https://github.com/bbatsov/rubocop/pull/4162): Fix a false negative in `UselessAssignment` cop with nested conditionals. ([@yujinakayama][]) ## 0.47.1 (2017-01-18) ### Bug fixes * [#3911](https://github.com/bbatsov/rubocop/issues/3911): Prevent a crash in `Performance/RegexpMatch` cop with module definition. ([@pocke][]) * [#3908](https://github.com/bbatsov/rubocop/issues/3908): Prevent `Style/AlignHash` from breaking on a keyword splat when using enforced `table` style. ([@drenmi][]) * [#3918](https://github.com/bbatsov/rubocop/issues/3918): Prevent `Rails/EnumUniqueness` from breaking on a non-literal hash value. ([@drenmi][]) * [#3914](https://github.com/bbatsov/rubocop/pull/3914): Fix department resolution for third party cops required through configuration. ([@backus][]) * [#3846](https://github.com/bbatsov/rubocop/issues/3846): `NodePattern` works for hyphenated node types. ([@alexdowad][]) * [#3922](https://github.com/bbatsov/rubocop/issues/3922): Prevent `Style/NegatedIf` from breaking on negated ternary. ([@drenmi][]) * [#3915](https://github.com/bbatsov/rubocop/issues/3915): Fix a false positive in `Lint/SafeNavigationChain` cop with `try` method. ([@pocke][]) ## 0.47.0 (2017-01-16) ### New features * [#3822](https://github.com/bbatsov/rubocop/pull/3822): Add `Rails/FilePath` cop. ([@iguchi1124][]) * [#3821](https://github.com/bbatsov/rubocop/pull/3821): Add `Security/YAMLLoad` cop. ([@cyberdelia][]) * [#3816](https://github.com/bbatsov/rubocop/pull/3816): Add `Security/MarshalLoad` cop. ([@cyberdelia][]) * [#3757](https://github.com/bbatsov/rubocop/pull/3757): Add Auto-Correct for `Bundler/OrderedGems` cop. ([@pocke][]) * `Style/FrozenStringLiteralComment` now supports the style `never` that will remove the `frozen_string_literal` comment. ([@rrosenblum][]) * [#3795](https://github.com/bbatsov/rubocop/pull/3795): Add `Lint/MultipleCompare` cop. ([@pocke][]) * [#3772](https://github.com/bbatsov/rubocop/issues/3772): Allow exclusion of certain methods for `Metrics/BlockLength`. ([@NobodysNightmare][]) * [#3804](https://github.com/bbatsov/rubocop/pull/3804): Add new `Lint/SafeNavigationChain` cop. ([@pocke][]) * [#3670](https://github.com/bbatsov/rubocop/pull/3670): Add `CountBlocks` boolean option to `Metrics/BlockNesting`. It allows blocks to be counted towards the nesting limit. ([@georgyangelov][]) * [#2992](https://github.com/bbatsov/rubocop/issues/2992): Add a configuration to `Style/ConditionalAssignment` to toggle offenses for ternary expressions. ([@rrosenblum][]) * [#3824](https://github.com/bbatsov/rubocop/pull/3824): Add new `Performance/RegexpMatch` cop. ([@pocke][]) * [#3825](https://github.com/bbatsov/rubocop/pull/3825): Add new `Rails/SkipsModelValidations` cop. ([@rahulcs][]) * [#3737](https://github.com/bbatsov/rubocop/issues/3737): Add new `Style/MethodCallWithArgsParentheses` cop. ([@dominh][]) * Renamed `MethodCallParentheses` to `MethodCallWithoutArgsParentheses`. ([@dominh][]) * [#3854](https://github.com/bbatsov/rubocop/pull/3854): Add new `Rails/ReversibleMigration` cop. ([@sue445][]) * [#3872](https://github.com/bbatsov/rubocop/pull/3872): Detect `String#%` with hash literal. ([@backus][]) * [#2731](https://github.com/bbatsov/rubocop/issues/2731): Allow configuration of method calls that create methods for `Lint/UselessAccessModifier`. ([@pat][]) ### Changes * [#3820](https://github.com/bbatsov/rubocop/pull/3820): Rename `Lint/Eval` to `Security/Eval`. ([@cyberdelia][]) * [#3725](https://github.com/bbatsov/rubocop/issues/3725): Disable `Style/SingleLineBlockParams` by default. ([@tejasbubane][]) * [#3765](https://github.com/bbatsov/rubocop/pull/3765): Add a validation for supported styles other than EnforcedStyle. `AlignWith`, `IndentWhenRelativeTo` and `EnforcedMode` configurations are renamed. ([@pocke][]) * [#3782](https://github.com/bbatsov/rubocop/pull/3782): Add check for `add_reference` method by `Rails/NotNullColumn` cop. ([@pocke][]) * [#3761](https://github.com/bbatsov/rubocop/pull/3761): Update `Style/RedundantFreeze` message from `Freezing immutable objects is pointless.` to `Do not freeze immutable objects, as freezing them has no effect.`. ([@lucasuyezu][]) * [#3753](https://github.com/bbatsov/rubocop/issues/3753): Change error message of `Bundler/OrderedGems` to mention `Alphabetize Gems`. ([@tejasbubane][]) * [#3802](https://github.com/bbatsov/rubocop/pull/3802): Ignore case when checking Gemfile order. ([@breckenedge][]) * Add missing examples in `Lint` cops documentation. ([@enriikke][]) * Make `Style/EmptyMethod` cop aware of class methods. ([@drenmi][]) * [#3871](https://github.com/bbatsov/rubocop/pull/3871): Add check for void `defined?` and `self` by `Lint/Void` cop. ([@pocke][]) * Allow ignoring methods in `Style/BlockDelimiters` when using any style. ([@twe4ked][]) ### Bug fixes * [#3751](https://github.com/bbatsov/rubocop/pull/3751): Avoid crash in `Rails/EnumUniqueness` cop. ([@pocke][]) * [#3766](https://github.com/bbatsov/rubocop/pull/3766): Avoid crash in `Style/ConditionalAssignment` cop with masgn. ([@pocke][]) * [#3770](https://github.com/bbatsov/rubocop/pull/3770): `Style/RedundantParentheses` Don't flag raised to a power negative numeric literals, since removing the parentheses would change the meaning of the expressions. ([@amogil][]) * [#3750](https://github.com/bbatsov/rubocop/issues/3750): Register an offense in `Style/ConditionalAssignment` when the assignment spans multiple lines. ([@rrosenblum][]) * [#3775](https://github.com/bbatsov/rubocop/pull/3775): Avoid crash in `Style/HashSyntax` cop with an empty hash. ([@pocke][]) * [#3783](https://github.com/bbatsov/rubocop/pull/3783): Maintain parentheses in `Rails/HttpPositionalArguments` when methods are defined with them. ([@kevindew][]) * [#3786](https://github.com/bbatsov/rubocop/pull/3786): Avoid crash `Style/ConditionalAssignment` cop with mass assign method. ([@pocke][]) * [#3749](https://github.com/bbatsov/rubocop/pull/3749): Detect corner case of `Style/NumericLitterals`. ([@kamaradclimber][]) * [#3788](https://github.com/bbatsov/rubocop/pull/3788): Prevent bad auto-correct in `Style/Next` when block has nested conditionals. ([@drenmi][]) * [#3807](https://github.com/bbatsov/rubocop/pull/3807): Prevent `Style/Documentation` and `Style/DocumentationMethod` from mistaking RuboCop directives for class documentation. ([@drenmi][]) * [#3815](https://github.com/bbatsov/rubocop/pull/3815): Fix false positive in `Style/IdenticalConditionalBranches` cop when branches have same line at leading. ([@pocke][]) * Fix false negative in `Rails/HttpPositionalArguments` where offense would go undetected if one of the request parameter names matched one of the special keyword arguments. ([@deivid-rodriguez][]) * Fix false negative in `Rails/HttpPositionalArguments` where offense would go undetected if the `:format` keyword was used with other non-special keywords. ([@deivid-rodriguez][]) * [#3406](https://github.com/bbatsov/rubocop/issues/3406): Enable cops if Enabled is not explicitly set to false. ([@metcalf][]) * Fix `Lint/FormatParameterMismatch` for splatted last argument. ([@zverok][]) * [#3853](https://github.com/bbatsov/rubocop/pull/3853): Fix false positive in `RedundantParentheses` cop with multiple expression. ([@pocke][]) * [#3870](https://github.com/bbatsov/rubocop/pull/3870): Avoid crash in `Rails/HttpPositionalArguments`. ([@pocke][]) * [#3869](https://github.com/bbatsov/rubocop/pull/3869): Prevent `Lint/FormatParameterMismatch` from breaking when `#%` is passed an empty array. ([@drenmi][]) * [#3879](https://github.com/bbatsov/rubocop/pull/3879): Properly handle Emacs and Vim magic comments for `FrozenStringLiteralComment`. ([@backus][]) * [#3736](https://github.com/bbatsov/rubocop/issues/3736): Fix to remove accumulator return value by auto-correction in `Style/EachWithObject`. ([@pocke][]) ## 0.46.0 (2016-11-30) ### New features * [#3600](https://github.com/bbatsov/rubocop/issues/3600): Add new `Bundler/DuplicatedGem` cop. ([@jmks][]) * [#3624](https://github.com/bbatsov/rubocop/pull/3624): Add new configuration option `empty_lines_special` to `Style/EmptyLinesAroundClassBody` and `Style/EmptyLinesAroundModuleBody`. ([@legendetm][]) * Add new `Style/EmptyMethod` cop. ([@drenmi][]) * `Style/EmptyLiteral` will now auto-correct `Hash.new` when it is the first argument being passed to a method. The arguments will be wrapped with parenthesis. ([@rrosenblum][]) * [#3713](https://github.com/bbatsov/rubocop/pull/3713): Respect `DisabledByDefault` in parent configs. ([@aroben][]) * New cop `Rails/EnumUniqueness` checks for duplicate values defined in enum config. ([@olliebennett][]) * New cop `Rails/EnumUniqueness` checks for duplicate values defined in enum config hash. ([@olliebennett][]) * [#3451](https://github.com/bbatsov/rubocop/issues/3451): Add new `require_parentheses_when_complex` style to `Style/TernaryParentheses` cop. ([@swcraig][]) * [#3600](https://github.com/bbatsov/rubocop/issues/3600): Add new `Bundler/OrderedGems` cop. ([@tdeo][]) * [#3479](https://github.com/bbatsov/rubocop/issues/3479): Add new configuration option `IgnoredPatterns` to `Metrics/LineLength`. ([@jonas054][]) ### Changes * The offense range for `Performance/FlatMap` now includes any parameters that are passed to `flatten`. ([@rrosenblum][]) * [#1747](https://github.com/bbatsov/rubocop/issues/1747): Update `Style/SpecialGlobalVars` messages with a reminder to `require 'English'`. ([@ivanovaleksey][]) * Checks `binding.irb` call by `Lint/Debugger` cop. ([@pocke][]) * [#3742](https://github.com/bbatsov/rubocop/pull/3742): Checks `min` and `max` call by `Performance/CompareWithBlock` cop. ([@pocke][]) ### Bug fixes * [#3662](https://github.com/bbatsov/rubocop/issues/3662): Fix the auto-correction of `Lint/UnneededSplatExpansion` when the splat expansion is inside of another array. ([@rrosenblum][]) * [#3699](https://github.com/bbatsov/rubocop/issues/3699): Fix false positive in `Style/VariableNumber` on variable names ending with an underscore. ([@bquorning][]) * [#3687](https://github.com/bbatsov/rubocop/issues/3687): Fix the fact that `Style/TernaryParentheses` cop claims to correct uncorrected offenses. ([@Ana06][]) * [#3568](https://github.com/bbatsov/rubocop/issues/3568): Fix `--auto-gen-config` behavior for `Style/VariableNumber`. ([@jonas054][]) * Add `format` as an acceptable keyword argument for `Rails/HttpPositionalArguments`. ([@aesthetikx][]) * [#3598](https://github.com/bbatsov/rubocop/issues/3598): In `Style/NumericPredicate`, don't report `x != 0` or `x.nonzero?` as the expressions have different values. ([@jonas054][]) * [#3690](https://github.com/bbatsov/rubocop/issues/3690): Do not register an offense for multiline braces with content in `Style/SpaceInsideBlockBraces`. ([@rrosenblum][]) * [#3746](https://github.com/bbatsov/rubocop/issues/3746): `Lint/NonLocalExitFromIterator` does not warn about `return` in a block which is passed to `Object#define_singleton_method`. ([@AlexWayfer][]) ## 0.45.0 (2016-10-31) ### New features * [#3615](https://github.com/bbatsov/rubocop/pull/3615): Add autocorrection for `Lint/EmptyInterpolation`. ([@pocke][]) * Make `PercentLiteralDelimiters` enforce delimiters around `%I()` too. ([@bronson][]) * [#3408](https://github.com/bbatsov/rubocop/issues/3408): Add check for repeated values in case conditionals. ([@swcraig][]) * [#3646](https://github.com/bbatsov/rubocop/pull/3646): Add new `Lint/EmptyWhen` cop. ([@drenmi][]) * [#3246](https://github.com/bbatsov/rubocop/issues/3246): Add list of all cops to the manual (generated automatically from a rake task). ([@sihu][]) * [#3647](https://github.com/bbatsov/rubocop/issues/3647): Add `--force-default-config` option. ([@jawshooah][]) * [#3570](https://github.com/bbatsov/rubocop/issues/3570): Add new `MultilineIfModifier` cop to avoid usage of if/unless-modifiers on multiline statements. ([@tessi][]) * [#3631](https://github.com/bbatsov/rubocop/issues/3631): Add new `Style/SpaceInLambdaLiteral` cop to check for spaces in lambda literals. ([@swcraig][]) * Add new `Lint/EmptyExpression` cop. ([@drenmi][]) ### Bug fixes * [#3553](https://github.com/bbatsov/rubocop/pull/3553): Make `Style/RedundantSelf` cop to not register an offence for `self.()`. ([@iGEL][]) * [#3474](https://github.com/bbatsov/rubocop/issues/3474): Make the `Rails/TimeZone` only analyze functions which have "Time" in the receiver. ([@b-t-g][]) * [#3607](https://github.com/bbatsov/rubocop/pull/3607): Fix `Style/RedundantReturn` cop for empty if body. ([@pocke][]) * [#3291](https://github.com/bbatsov/rubocop/issues/3291): Improve detection of `raw` and `html_safe` methods in `Rails/OutputSafety`. ([@lumeet][]) * Redundant return style now properly handles empty `when` blocks. ([@albus522][]) * [#3622](https://github.com/bbatsov/rubocop/pull/3622): Fix false positive for `Metrics/MethodLength` and `Metrics/BlockLength`. ([@meganemura][]) * [#3625](https://github.com/bbatsov/rubocop/pull/3625): Fix some cops errors when condition is empty brace. ([@pocke][]) * [#3468](https://github.com/bbatsov/rubocop/issues/3468): Fix bug regarding alignment inside `begin`..`end` block in `Style/MultilineMethodCallIndentation`. ([@jonas054][]) * [#3644](https://github.com/bbatsov/rubocop/pull/3644): Fix generation incorrect documentation. ([@pocke][]) * [#3637](https://github.com/bbatsov/rubocop/issues/3637): Fix Style/NonNilCheck crashing for ternary condition. ([@tejasbubane][]) * [#3654](https://github.com/bbatsov/rubocop/pull/3654): Add missing keywords for `Rails/HttpPositionalArguments`. ([@eitoball][]) * [#3652](https://github.com/bbatsov/rubocop/issues/3652): Avoid crash Rails/HttpPositionalArguments for lvar params when auto-correct. ([@pocke][]) * Fix bug in `Style/SafeNavigation` where there is a check for an object in an elsif statement with a method call on that object in the branch. ([@rrosenblum][]) * [#3660](https://github.com/bbatsov/rubocop/pull/3660): Fix false positive for Rails/SafeNavigation when without receiver. ([@pocke][]) * [#3650](https://github.com/bbatsov/rubocop/issues/3650): Fix `Style/VariableNumber` registering an offense for variables with double digit numbers. ([@rrosenblum][]) * [#3494](https://github.com/bbatsov/rubocop/issues/3494): Check `rails` style indentation also inside blocks in `Style/IndentationWidth`. ([@jonas054][]) * [#3676](https://github.com/bbatsov/rubocop/issues/3676): Ignore raw and html_safe invocations when wrapped inside a safe_join. ([@b-t-g][]) ### Changes * [#3601](https://github.com/bbatsov/rubocop/pull/3601): Change default args for `Style/SingleLineBlockParams`. This cop checks that `reduce` and `inject` use the variable names `a` and `e` for block arguments. These defaults are uncommunicative variable names and thus conflict with the ["Uncommunicative Variable Name" check in Reek](https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md). Default args changed to `acc` and `elem`.([@jessieay][]) * [#3645](https://github.com/bbatsov/rubocop/pull/3645): Fix bug with empty case when nodes in `Style/RedundantReturn`. ([@tiagocasanovapt][]) * [#3263](https://github.com/bbatsov/rubocop/issues/3263): Fix auto-correct of if statements inside of unless else statements in `Style/ConditionalAssignment`. ([@rrosenblum][]) * Bump default Ruby version to 2.1. ([@drenmi][]) ## 0.44.1 (2016-10-13) ### Bug fixes * Remove a debug `require`. ([@bbatsov][]) ## 0.44.0 (2016-10-13) ### New features * [#3560](https://github.com/bbatsov/rubocop/pull/3560): Add a configuration option `empty_lines_except_namespace` to `Style/EmptyLinesAroundClassBody` and `Style/EmptyLinesAroundModuleBody`. ([@legendetm][]) * [#3370](https://github.com/bbatsov/rubocop/issues/3370): Add new `Rails/HttpPositionalArguments` cop to check your Rails 5 test code for existence of positional args usage. ([@logicminds][]) * [#3510](https://github.com/bbatsov/rubocop/issues/3510): Add a configuration option, `ConvertCodeThatCanStartToReturnNil`, to `Style/SafeNavigation` to check for code that could start returning `nil` if safe navigation is used. ([@rrosenblum][]) * Add a new `AllCops/StyleGuideBaseURL` setting that allows the use of relative paths and/or fragments within each cop's `StyleGuide` setting, to make forking of custom style guides easier. ([@scottmatthewman][]) * [#3566](https://github.com/bbatsov/rubocop/issues/3566): Add new `Metric/BlockLength` cop to ensure blocks don't get too long. ([@savef][]) * [#3428](https://github.com/bbatsov/rubocop/issues/3428): Add support for configuring `Style/PreferredHashMethods` with either `short` or `verbose` style method names. ([@abrom][]) * [#3455](https://github.com/bbatsov/rubocop/issues/3455): Add new `Rails/DynamicFindBy` cop. ([@pocke][]) * [#3542](https://github.com/bbatsov/rubocop/issues/3542): Add a configuration option, `IgnoreCopDirectives`, to `Metrics/LineLength` to stop cop directives (`# rubocop:disable Metrics/AbcSize`) from being counted when considering line length. ([@jmks][]) * Add new `Rails/DelegateAllowBlank` cop. ([@connorjacobsen][]) * Add new `Style/MultilineMemoization` cop. ([@drenmi][]) ### Bug fixes * [#3103](https://github.com/bbatsov/rubocop/pull/3103): Make `Style/ExtraSpacing` cop register an offense for extra spaces present in single-line hash literals. ([@tcdowney][]) * [#3513](https://github.com/bbatsov/rubocop/pull/3513): Fix false positive in `Style/TernaryParentheses` for a ternary with ranges. ([@dreyks][]) * [#3520](https://github.com/bbatsov/rubocop/issues/3520): Fix regression causing `Lint/AssignmentInCondition` false positive. ([@savef][]) * [#3514](https://github.com/bbatsov/rubocop/issues/3514): Make `Style/VariableNumber` cop not register an offense when valid normal case variable names have an integer after the first `_`. ([@b-t-g][]) * [#3516](https://github.com/bbatsov/rubocop/issues/3516): Make `Style/VariableNumber` cop not register an offense when valid normal case variable names have an integer in the middle. ([@b-t-g][]) * [#3436](https://github.com/bbatsov/rubocop/issues/3436): Make `Rails/SaveBang` cop not register an offense when return value of a non-bang method is returned by the parent method. ([@coorasse][]) * [#3540](https://github.com/bbatsov/rubocop/issues/3540): Fix `Style/GuardClause` to register offense for instance and singleton methods. ([@tejasbubane][]) * [#3311](https://github.com/bbatsov/rubocop/issues/3311): Detect incompatibilities with the external encoding to prevent bad autocorrections in `Style/StringLiterals`. ([@deivid-rodriguez][]) * [#3499](https://github.com/bbatsov/rubocop/issues/3499): Ensure `Lint/UnusedBlockArgument` doesn't make recommendations that would change arity for methods defined using `#define_method`. ([@drenmi][]) * [#3430](https://github.com/bbatsov/rubocop/issues/3430): Fix exception in `Performance/RedundantMerge` when inspecting a `#merge!` with implicit receiver. ([@drenmi][]) * [#3411](https://github.com/bbatsov/rubocop/issues/3411): Avoid auto-correction crash for single `when` in `Performance/CaseWhenSplat`. ([@jonas054][]) * [#3286](https://github.com/bbatsov/rubocop/issues/3286): Allow `self.a, self.b = b, a` in `Style/ParallelAssignment`. ([@jonas054][]) * [#3419](https://github.com/bbatsov/rubocop/issues/3419): Report offense for `unless x.nil?` in `Style/NonNilCheck` if `IncludeSemanticChanges` is `true`. ([@jonas054][]) * [#3382](https://github.com/bbatsov/rubocop/issues/3382): Avoid auto-correction crash for multiple elsifs in `Style/EmptyElse`. ([@lumeet][]) * [#3334](https://github.com/bbatsov/rubocop/issues/3334): Do not register an offense for a literal space (`\s`) in `Style/UnneededCapitalW`. ([@rrosenblum][]) * [#3390](https://github.com/bbatsov/rubocop/issues/3390): Fix SaveBang cop for multiple conditional. ([@tejasbubane][]) * [#3577](https://github.com/bbatsov/rubocop/issues/3577): Fix `Style/RaiseArgs` not allowing compact raise with splatted args. ([@savef][]) * [#3578](https://github.com/bbatsov/rubocop/issues/3578): Fix safe navigation method call counting in `Metrics/AbcSize`. ([@savef][]) * [#3592](https://github.com/bbatsov/rubocop/issues/3592): Fix `Style/RedundantParentheses` for indexing with literals. ([@thegedge][]) * [#3597](https://github.com/bbatsov/rubocop/issues/3597): Fix the autocorrect of `Performance/CaseWhenSplat` when trying to rearange splat expanded variables to the end of a when condition. ([@rrosenblum][]) ### Changes * [#3512](https://github.com/bbatsov/rubocop/issues/3512): Change error message of `Lint/UnneededSplatExpansion` for array in method parameters. ([@tejasbubane][]) * [#3510](https://github.com/bbatsov/rubocop/issues/3510): Fix some issues with `Style/SafeNavigation`. Fix auto-correct of multiline if expressions, and do not register an offense for scenarios using `||` and ternary expression. ([@rrosenblum][]) * [#3503](https://github.com/bbatsov/rubocop/issues/3503): Change misleading message of `Style/EmptyLinesAroundAccessModifier`. ([@bquorning][]) * [#3407](https://github.com/bbatsov/rubocop/issues/3407): Turn off autocorrect for unsafe rules by default. ([@ptarjan][]) * [#3521](https://github.com/bbatsov/rubocop/issues/3521): Turn off autocorrect for `Security/JSONLoad` by default. ([@savef][]) * [#2903](https://github.com/bbatsov/rubocop/issues/2903): `Style/RedundantReturn` looks for redundant `return` inside conditional branches. ([@lumeet][]) ## 0.43.0 (2016-09-19) ### New features * [#3379](https://github.com/bbatsov/rubocop/issues/3379): Add table of contents at the beginning of HTML formatted output. ([@hedgesky][]) * [#2968](https://github.com/bbatsov/rubocop/issues/2968): Add new `Style/DocumentationMethod` cop. ([@sooyang][]) * [#3360](https://github.com/bbatsov/rubocop/issues/3360): Add `RequireForNonPublicMethods` configuration option to `Style/DocumentationMethod` cop. ([@drenmi][]) * Add new `Rails/SafeNavigation` cop to convert `try!` to `&.`. ([@rrosenblum][]) * [#3415](https://github.com/bbatsov/rubocop/pull/3415): Add new `Rails/NotNullColumn` cop. ([@pocke][]) * [#3167](https://github.com/bbatsov/rubocop/issues/3167): Add new `Style/VariableNumber` cop. ([@sooyang][]) * Add new style `no_mixed_keys` to `Style/HashSyntax` to only check for hashes with mixed keys. ([@daviddavis][]) * Allow including multiple configuration files from a single gem. ([@tjwallace][]) * Add check for `persisted?` method call when using a create method in `Rails/SaveBang`. ([@QuinnHarris][]) * Add new `Style/SafeNavigation` cop to convert method calls safeguarded by a non `nil` check for the object to `&.`. ([@rrosenblum][]) * Add new `Performance/SortWithBlock` cop to use `sort_by(&:foo)` instead of `sort { |a, b| a.foo <=> b.foo }`. ([@koic][]) * [#3492](https://github.com/bbatsov/rubocop/pull/3492): Add new `UnifiedInteger` cop. ([@pocke][]) ### Bug fixes * [#3383](https://github.com/bbatsov/rubocop/issues/3383): Fix the local variable reset issue with `Style/RedundantSelf` cop. ([@bankair][]) * [#3445](https://github.com/bbatsov/rubocop/issues/3445): Fix bad autocorrect for `Style/AndOr` cop. ([@mikezter][]) * [#3349](https://github.com/bbatsov/rubocop/issues/3349): Fix bad autocorrect for `Style/Lambda` cop. ([@metcalf][]) * [#3351](https://github.com/bbatsov/rubocop/issues/3351): Fix bad auto-correct for `Performance/RedundantMatch` cop. ([@annaswims][]) * [#3347](https://github.com/bbatsov/rubocop/issues/3347): Prevent infinite loop in `Style/TernaryParentheses` cop when used together with `Style/RedundantParentheses`. ([@drenmi][]) * [#3209](https://github.com/bbatsov/rubocop/issues/3209): Remove faulty line length check from `Style/GuardClause` cop. ([@drenmi][]) * [#3366](https://github.com/bbatsov/rubocop/issues/3366): Make `Style/MutableConstant` cop aware of splat assignments. ([@drenmi][]) * [#3372](https://github.com/bbatsov/rubocop/pull/3372): Fix RuboCop crash with empty brackets in `Style/Next` cop. ([@pocke][]) * [#3358](https://github.com/bbatsov/rubocop/issues/3358): Make `Style/MethodMissing` cop aware of class scope. ([@drenmi][]) * [#3342](https://github.com/bbatsov/rubocop/issues/3342): Fix error in `Lint/ShadowedException` cop if last rescue does not have parameter. ([@soutaro][]) * [#3380](https://github.com/bbatsov/rubocop/issues/3380): Fix false positive in `Style/TrailingUnderscoreVariable` cop. ([@drenmi][]) * [#3388](https://github.com/bbatsov/rubocop/issues/3388): Fix bug where `Lint/ShadowedException` would register an offense when rescuing different numbers of custom exceptions in multiple rescue groups. ([@rrosenblum][]) * [#3386](https://github.com/bbatsov/rubocop/issues/3386): Make `VariableForce` understand an empty RegExp literal as LHS to `=~`. ([@drenmi][]) * [#3421](https://github.com/bbatsov/rubocop/pull/3421): Fix clobbering `inherit_from` additions when not using Namespaces in the configs. ([@nicklamuro][]) * [#3425](https://github.com/bbatsov/rubocop/pull/3425): Fix bug for invalid bytes in UTF-8 in `Lint/PercentStringArray` cop. ([@pocke][]) * [#3374](https://github.com/bbatsov/rubocop/issues/3374): Make `SpaceInsideBlockBraces` and `SpaceBeforeBlockBraces` not depend on `BlockDelimiters` configuration. ([@jonas054][]) * Fix error in `Lint/ShadowedException` cop for higher number of rescue groups. ([@groddeck][]) * [#3456](https://github.com/bbatsov/rubocop/pull/3456): Don't crash on a multiline empty brace in `Style/MultilineMethodCallBraceLayout`. ([@pocke][]) * [#3423](https://github.com/bbatsov/rubocop/issues/3423): Checks if .rubocop is a file before parsing. ([@joejuzl][]) * [#3439](https://github.com/bbatsov/rubocop/issues/3439): Fix variable assignment check not working properly when a block is used in `Rails/SaveBang`. ([@QuinnHarris][]) * [#3401](https://github.com/bbatsov/rubocop/issues/3401): Read file contents in binary mode so `Style/EndOfLine` works on Windows. ([@jonas054][]) * [#3450](https://github.com/bbatsov/rubocop/issues/3450): Prevent `Style/TernaryParentheses` cop from making unsafe corrections. ([@drenmi][]) * [#3460](https://github.com/bbatsov/rubocop/issues/3460): Fix false positives in `Style/InlineComment` cop. ([@drenmi][]) * [#3485](https://github.com/bbatsov/rubocop/issues/3485): Make OneLineConditional cop not register offense for empty else. ([@tejasbubane][]) * [#3508](https://github.com/bbatsov/rubocop/pull/3508): Fix false negatives in `Rails/NotNullColumn`. ([@pocke][]) * [#3462](https://github.com/bbatsov/rubocop/issues/3462): Don't create MultilineMethodCallBraceLayout offenses for single-line method calls when receiver spans multiple lines. ([@maxjacobson][]) ### Changes * [#3341](https://github.com/bbatsov/rubocop/issues/3341): Exclude RSpec tests from inspection by `Style/NumericPredicate` cop. ([@drenmi][]) * Rename `Lint/UselessArraySplat` to `Lint/UnneededSplatExpansion`, and add functionality to check for unnecessary expansion of other literals. ([@rrosenblum][]) * No longer register an offense for splat expansion of an array literal in `Performance/CaseWhenSplat`. `Lint/UnneededSplatExpansion` now handles this behavior. ([@rrosenblum][]) * `Lint/InheritException` restricts inheriting from standard library subclasses of `Exception`. ([@metcalf][]) * No longer register an offense if the first line of code starts with `#\` in `Style/LeadingCommentSpace`. `config.ru` files consider such lines as options. ([@scottohara][]) * [#3292](https://github.com/bbatsov/rubocop/issues/3292): Remove `Performance/PushSplat` as it can produce code that is slower or even cause failure. ([@jonas054][]) ## 0.42.0 (2016-07-25) ### New features * [#3306](https://github.com/bbatsov/rubocop/issues/3306): Add autocorrection for `Style/EachWithObject`. ([@owst][]) * Add new `Style/TernaryParentheses` cop. ([@drenmi][]) * [#3136](https://github.com/bbatsov/rubocop/issues/3136): Add config for `UselessAccessModifier` so it can be made aware of ActiveSupport's `concerning` and `class_methods` methods. ([@maxjacobson][]) * [#3128](https://github.com/bbatsov/rubocop/issues/3128): Add new `Rails/SaveBang` cop. ([@QuinnHarris][]) * Add new `Style/NumericPredicate` cop. ([@drenmi][]) ### Bug fixes * [#3271](https://github.com/bbatsov/rubocop/issues/3271): Fix bad auto-correct for `Style/EachForSimpleLoop` cop. ([@drenmi][]) * [#3288](https://github.com/bbatsov/rubocop/issues/3288): Fix auto-correct of word and symbol arrays in `Style/ParallelAssignment` cop. ([@jonas054][]) * [#3307](https://github.com/bbatsov/rubocop/issues/3307): Fix exception when inspecting an operator assignment with `Style/MethodCallParentheses` cop. ([@drenmi][]) * [#3316](https://github.com/bbatsov/rubocop/issues/3316): Fix error for blocks without arguments in `Style/SingleLineBlockParams` cop. ([@owst][]) * [#3320](https://github.com/bbatsov/rubocop/issues/3320): Make `Style/OpMethod` aware of the backtick method. ([@drenmi][]) * Do not register an offense in `Lint/ShadowedException` when rescuing an exception built into Ruby before a custom exception. ([@rrosenblum][]) ### Changes * [#2645](https://github.com/bbatsov/rubocop/issues/2645): `Style/EmptyLiteral` no longer generates an offense for `String.new` when using frozen string literals. ([@drenmi][]) * [#3308](https://github.com/bbatsov/rubocop/issues/3308): Make `Lint/NextWithoutAccumulator` aware of nested enumeration. ([@drenmi][]) * Extend `Style/MethodMissing` cop to check for the conditions in the style guide. ([@drenmi][]) * [#3325](https://github.com/bbatsov/rubocop/issues/3325): Drop support for MRI 1.9.3. ([@drenmi][]) * Add support for MRI 2.4. ([@dvandersluis][]) * [#3256](https://github.com/bbatsov/rubocop/issues/3256): Highlight the closing brace in `Style/Multiline...BraceLayout` cops. ([@jonas054][]) * Always register an offense when rescuing `Exception` before or along with any other exception in `Lint/ShadowedException`. ([@rrosenblum][]) ## 0.41.2 (2016-07-07) ### Bug fixes * [#3248](https://github.com/bbatsov/rubocop/issues/3248): Support 'ruby-' prefix in `.ruby-version`. ([@tjwp][]) * [#3250](https://github.com/bbatsov/rubocop/pull/3250): Make regexp for cop names less restrictive in CommentConfig lines. ([@tjwp][]) * [#3261](https://github.com/bbatsov/rubocop/pull/3261): Prefer `TargetRubyVersion` to `.ruby-version`. ([@tjwp][]) * [#3249](https://github.com/bbatsov/rubocop/issues/3249): Account for `rescue nil` in `Style/ShadowedException`. ([@rrosenblum][]) * Modify the highlighting in `Style/ShadowedException` to be more useful. Highlight just `rescue` area. ([@rrosenblum][]) * [#3129](https://github.com/bbatsov/rubocop/issues/3129): Fix `Style/MethodCallParentheses` to work with multiple assignments. ([@tejasbubane][]) * [#3247](https://github.com/bbatsov/rubocop/issues/3247): Ensure whitespace after beginning of block in `Style/BlockDelimiters`. ([@tjwp][]) * [#2941](https://github.com/bbatsov/rubocop/issues/2941): Make sure `Lint/UnneededDisable` can do auto-correction. ([@jonas054][]) * [#3269](https://github.com/bbatsov/rubocop/pull/3269): Fix `Lint/ShadowedException` to block arbitrary code execution. ([@pocke][]) * [#3266](https://github.com/bbatsov/rubocop/issues/3266): Handle empty parentheses in `Performance/RedundantBlockCall` auto-correct. ([@jonas054][]) * [#3272](https://github.com/bbatsov/rubocop/issues/3272): Add escape character missing to LITERAL_REGEX. ([@pocke][]) * [#3255](https://github.com/bbatsov/rubocop/issues/3255): Fix auto-correct for `Style/RaiseArgs` when constructing exception without arguments. ([@drenmi][]) * [#3294](https://github.com/bbatsov/rubocop/pull/3294): Allow to use `Time.zone_default`. ([@Tei][]) * [#3300](https://github.com/bbatsov/rubocop/issues/3300): Do not replace `%q()`s containing escaped non-backslashes. ([@owst][]) ### Changes * [#3230](https://github.com/bbatsov/rubocop/issues/3230): Improve highlighting for `Style/AsciiComments` cop. ([@drenmi][]) * Improve highlighting for `Style/AsciiIdentifiers` cop. ([@drenmi][]) * [#3265](https://github.com/bbatsov/rubocop/issues/3265): Include --no-offense-counts in .rubocop_todo.yml. ([@vergenzt][]) ## 0.41.1 (2016-06-26) ### Bug fixes * [#3245](https://github.com/bbatsov/rubocop/pull/3245): Fix `UniqBeforePluck` cop by solving difference of config name. ([@pocke][]) ## 0.41.0 (2016-06-25) ### New features * [#2956](https://github.com/bbatsov/rubocop/issues/2956): Prefer `.ruby-version` to `TargetRubyVersion`. ([@pclalv][]) * [#3095](https://github.com/bbatsov/rubocop/issues/3095): Add `IndentationWidth` configuration parameter for `Style/AlignParameters` cop. ([@alexdowad][]) * [#3066](https://github.com/bbatsov/rubocop/issues/3066): Add new `Style/ImplicitRuntimeError` cop which advises the use of an explicit exception class when raising an error. ([@alexdowad][]) * [#3018](https://github.com/bbatsov/rubocop/issues/3018): Add new `Style/EachForSimpleLoop` cop which advises the use of `Integer#times` for simple loops which iterate a fixed number of times. ([@alexdowad][]) * [#2595](https://github.com/bbatsov/rubocop/issues/2595): New `compact` style for `Style/SpaceInsideLiteralHashBraces`. ([@alexdowad][]) * [#2927](https://github.com/bbatsov/rubocop/issues/2927): Add autocorrect for `Rails/Validation` cop. ([@neodelf][]) * [#3135](https://github.com/bbatsov/rubocop/pull/3135): Add new `Rails/OutputSafety` cop. ([@josh][]) * [#3164](https://github.com/bbatsov/rubocop/pull/3164): Add [Fastlane](https://fastlane.tools/)'s Fastfile to the default Includes. ([@jules2689][]) * [#3173](https://github.com/bbatsov/rubocop/pull/3173): Make `Style/ModuleFunction` configurable with `module_function` and `extend_self` styles. ([@tjwp][]) * [#3105](https://github.com/bbatsov/rubocop/issues/3105): Add new `Rails/RequestReferer` cop. ([@giannileggio][]) * [#3200](https://github.com/bbatsov/rubocop/pull/3200): Add autocorrect for `Style/EachForSimpleLoop` cop. ([@tejasbubane][]) * [#3058](https://github.com/bbatsov/rubocop/issues/3058): Add new `Style/SpaceInsideArrayPercentLiteral` cop. ([@owst][]) * [#3058](https://github.com/bbatsov/rubocop/issues/3058): Add new `Style/SpaceInsidePercentLiteralDelimiters` cop. ([@owst][]) * [#3179](https://github.com/bbatsov/rubocop/pull/3179): Expose files to support testings Cops using RSpec. ([@tjwp][]) * [#3191](https://github.com/bbatsov/rubocop/issues/3191): Allow arbitrary comments after cop names in CommentConfig lines (e.g. rubocop:enable). ([@owst][]) * [#3165](https://github.com/bbatsov/rubocop/pull/3165): Add new `Lint/PercentStringArray` cop. ([@owst][]) * [#3165](https://github.com/bbatsov/rubocop/pull/3165): Add new `Lint/PercentSymbolArray` cop. ([@owst][]) * [#3177](https://github.com/bbatsov/rubocop/pull/3177): Add new `Style/NumericLiteralPrefix` cop. ([@tejasbubane][]) * [#1646](https://github.com/bbatsov/rubocop/issues/1646): Add configuration style `indented_relative_to_receiver` for `Style/MultilineMethodCallIndentation`. ([@jonas054][]) * New cop `Lint/ShadowedException` checks for the order which exceptions are rescued to avoid rescueing a less specific exception before a more specific exception. ([@rrosenblum][]) * [#3127](https://github.com/bbatsov/rubocop/pull/3127): New cop `Lint/InheritException` checks for error classes inheriting from `Exception`, and instead suggests `RuntimeError` or `StandardError`. ([@drenmi][]) * Add new `Performance/PushSplat` cop. ([@segiddins][]) * [#3089](https://github.com/bbatsov/rubocop/issues/3089): Add new `Rails/Exit` cop. ([@sgringwe][]) * [#3104](https://github.com/bbatsov/rubocop/issues/3104): Add new `Style/MethodMissing` cop. ([@haziqhafizuddin][]) ### Bug fixes * [#3005](https://github.com/bbatsov/rubocop/issues/3005): Symlink protection prevents use of caching in CI context. ([@urbanautomaton][]) * [#3037](https://github.com/bbatsov/rubocop/issues/3037): `Style/StringLiterals` understands that a bare '#', not '#@variable' or '#{interpolation}', does not require double quotes. ([@alexdowad][]) * [#2722](https://github.com/bbatsov/rubocop/issues/2722): `Style/ExtraSpacing` does not attempt to align an equals sign in an argument list with one in an assignment statement. ([@alexdowad][]) * [#3133](https://github.com/bbatsov/rubocop/issues/3133): `Style/MultilineMethodCallBraceLayout` does not register offenses for single-line calls. ([@alexdowad][]) * [#3170](https://github.com/bbatsov/rubocop/issues/3170): `Style/MutableConstant` does not infinite-loop when correcting an array with no brackets. ([@alexdowad][]) * [#3150](https://github.com/bbatsov/rubocop/issues/3150): Fix auto-correct for Style/MultilineArrayBraceLayout. ([@jspanjers][]) * [#3192](https://github.com/bbatsov/rubocop/pull/3192): Fix `Lint/UnusedBlockArgument`'s `IgnoreEmptyBlocks` parameter from being removed from configuration. ([@jfelchner][]) * [#3114](https://github.com/bbatsov/rubocop/issues/3114): Fix alignment `end` when auto-correcting `Style/EmptyElse`. ([@rrosenblum][]) * [#3120](https://github.com/bbatsov/rubocop/issues/3120): Fix `Lint/UselessAccessModifier` reporting useless access modifiers inside {Class,Module,Struct}.new blocks. ([@owst][]) * [#3125](https://github.com/bbatsov/rubocop/issues/3125): Fix `Rails/UniqBeforePluck` to ignore `uniq` with block. ([@tejasbubane][]) * [#3116](https://github.com/bbatsov/rubocop/issues/3116): `Style/SpaceAroundKeyword` allows `&.` method calls after `super` and `yield`. ([@segiddins][]) * [#3131](https://github.com/bbatsov/rubocop/issues/3131): Fix `Style/ZeroLengthPredicate` to ignore `size` and `length` variables. ([@tejasbubane][]) * [#3146](https://github.com/bbatsov/rubocop/pull/3146): Fix `NegatedIf` and `NegatedWhile` to ignore double negations. ([@natalzia-paperless][]) * [#3140](https://github.com/bbatsov/rubocop/pull/3140): `Style/FrozenStringLiteralComment` works with file doesn't have any tokens. ([@pocke][]) * [#3154](https://github.com/bbatsov/rubocop/issues/3154): Fix handling of `()` in `Style/RedundantParentheses`. ([@lumeet][]) * [#3155](https://github.com/bbatsov/rubocop/issues/3155): Fix `Style/SpaceAfterNot` reporting on the `not` keyword. ([@NobodysNightmare][]) * [#3160](https://github.com/bbatsov/rubocop/pull/3160): `Style/Lambda` fix whitespacing when auto-correcting unparenthesized arguments. ([@palkan][]) * [#2944](https://github.com/bbatsov/rubocop/issues/2944): Don't crash on strings that span multiple lines but only have one pair of delimiters in `Style/StringLiterals`. ([@jonas054][]) * [#3157](https://github.com/bbatsov/rubocop/issues/3157): Don't let `LineEndConcatenation` and `UnneededInterpolation` make changes to the same string during auto-correct. ([@jonas054][]) * [#3187](https://github.com/bbatsov/rubocop/issues/3187): Let `Style/BlockDelimiters` ignore blocks in *all* method arguments. ([@jonas054][]) * Modify `Style/ParallelAssignment` to use implicit begins when parallel assignment uses a `rescue` modifier and is the only thing in the method. ([@rrosenblum][]) * [#3217](https://github.com/bbatsov/rubocop/pull/3217): Fix output of ellipses for multi-line offense ranges in HTML formatter. ([@jonas054][]) * [#3207](https://github.com/bbatsov/rubocop/issues/3207): Auto-correct modifier `while`/`until` and `begin`..`end` + `while`/`until` in `Style/InfiniteLoop`. ([@jonas054][]) * [#3202](https://github.com/bbatsov/rubocop/issues/3202): Fix `Style/EmptyElse` registering wrong offenses and thus making RuboCop crash. ([@deivid-rodriguez][]) * [#3183](https://github.com/bbatsov/rubocop/issues/3183): Ensure `Style/SpaceInsideBlockBraces` reports offenses for multi-line blocks. ([@owst][]) * [#3017](https://github.com/bbatsov/rubocop/issues/3017): Fix `Style/StringLiterals` to register offenses on non-ascii strings. ([@deivid-rodriguez][]) * [#3056](https://github.com/bbatsov/rubocop/issues/3056): Fix `Style/StringLiterals` to register offenses on non-ascii strings. ([@deivid-rodriguez][]) * [#2986](https://github.com/bbatsov/rubocop/issues/2986): Fix `RedundantBlockCall` to not report calls that pass block arguments, or where the block has been overridden. ([@owst][]) * [#3223](https://github.com/bbatsov/rubocop/issues/3223): Return can take many arguments. ([@ptarjan][]) * [#3239](https://github.com/bbatsov/rubocop/pull/3239): Fix bug with --auto-gen-config and a file that does not exist. ([@meganemura][]) * [#3138](https://github.com/bbatsov/rubocop/issues/3138): Fix RuboCop crashing when config file contains utf-8 characters and external encoding is not utf-8. ([@deivid-rodriguez][]) * [#3175](https://github.com/bbatsov/rubocop/pull/3175): Generate 'Exclude' list for the cops with configurable enforced style to `.rubocop_todo.yml` if different styles are used. ([@flexoid][]) * [#3231](https://github.com/bbatsov/rubocop/pull/3231): Make `Rails/UniqBeforePluck` more conservative. ([@tjwp][]) ### Changes * [#3149](https://github.com/bbatsov/rubocop/pull/3149): Make `Style/HashSyntax` configurable to not report hash rocket syntax for symbols ending with ? or ! when using ruby19 style. ([@owst][]) * [#1758](https://github.com/bbatsov/rubocop/issues/1758): Let `Style/ClosingParenthesisIndentation` follow `Style/AlignParameters` configuration for method calls. ([@jonas054][]) * [#3224](https://github.com/bbatsov/rubocop/issues/3224): Rename `Style/DeprecatedHashMethods` to `Style/PreferredHashMethods`. ([@tejasbubane][]) ## 0.40.0 (2016-05-09) ### New features * [#2997](https://github.com/bbatsov/rubocop/pull/2997): `Performance/CaseWhenSplat` can now identify multiple offenses in the same branch and offenses that do not occur as the first argument. ([@rrosenblum][]) * [#2928](https://github.com/bbatsov/rubocop/issues/2928): `Style/NestedParenthesizedCalls` cop can auto-correct. ([@drenmi][]) * `Style/RaiseArgs` cop can auto-correct. ([@drenmi][]) * [#2993](https://github.com/bbatsov/rubocop/pull/2993): `Style/SpaceAfterColon` now checks optional keyword arguments. ([@owst][]) * [#3003](https://github.com/bbatsov/rubocop/pull/3003): Read command line options from `.rubocop` file and `RUBOCOP_OPTS` environment variable. ([@bolshakov][]) * [#2857](https://github.com/bbatsov/rubocop/issues/2857): `Style/MultilineArrayBraceLayout` enforced style is configurable and supports `symmetrical` and `new_line` options. ([@panthomakos][]) * [#2857](https://github.com/bbatsov/rubocop/issues/2857): `Style/MultilineHashBraceLayout` enforced style is configurable and supports `symmetrical` and `new_line` options. ([@panthomakos][]) * [#2857](https://github.com/bbatsov/rubocop/issues/2857): `Style/MultilineMethodCallBraceLayout` enforced style is configurable and supports `symmetrical` and `new_line` options. ([@panthomakos][]) * [#2857](https://github.com/bbatsov/rubocop/issues/2857): `Style/MultilineMethodDefinitionBraceLayout` enforced style is configurable and supports `symmetrical` and `new_line` options. ([@panthomakos][]) * [#3052](https://github.com/bbatsov/rubocop/pull/3052): `Style/MultilineArrayBraceLayout` enforced style supports `same_line` option. ([@panthomakos][]) * [#3052](https://github.com/bbatsov/rubocop/pull/3052): `Style/MultilineHashBraceLayout` enforced style supports `same_line` option. ([@panthomakos][]) * [#3052](https://github.com/bbatsov/rubocop/pull/3052): `Style/MultilineMethodCallBraceLayout` enforced style supports `same_line` option. ([@panthomakos][]) * [#3052](https://github.com/bbatsov/rubocop/pull/3052): `Style/MultilineMethodDefinitionBraceLayout` enforced style supports `same_line` option. ([@panthomakos][]) * [#3019](https://github.com/bbatsov/rubocop/issues/3019): Add new `Style/EmptyCaseCondition` cop. ([@owst][], [@rrosenblum][]) * [#3072](https://github.com/bbatsov/rubocop/pull/3072): Add new `Lint/UselessArraySplat` cop. ([@owst][]) * [#3022](https://github.com/bbatsov/rubocop/issues/3022): `Style/Lambda` enforced style supports `literal` option. ([@drenmi][]) * [#2909](https://github.com/bbatsov/rubocop/issues/2909): `Style/Lambda` enforced style supports `lambda` option. ([@drenmi][]) * [#3092](https://github.com/bbatsov/rubocop/pull/3092): Allow `Style/Encoding` to enforce using no encoding comments. ([@NobodysNightmare][]) * New cop `Rails/UniqBeforePluck` checks that `uniq` is used before `pluck`. ([@tjwp][]) ### Bug fixes * [#3112](https://github.com/bbatsov/rubocop/issues/3112): Fix `Style/ClassAndModuleChildren` for nested classes with explicit superclass. ([@jspanjers][]) * [#3032](https://github.com/bbatsov/rubocop/issues/3032): Fix autocorrecting parentheses for predicate methods without space before args. ([@graemeboy][]) * [#3000](https://github.com/bbatsov/rubocop/pull/3000): Fix encoding crash on HTML output. ([@gerrywastaken][]) * [#2983](https://github.com/bbatsov/rubocop/pull/2983): `Style/AlignParameters` message was clarified for `with_fixed_indentation` style. ([@dylanahsmith][]) * [#2314](https://github.com/bbatsov/rubocop/pull/2314): Ignore `UnusedBlockArgument` for keyword arguments. ([@volkert][]) * [#2975](https://github.com/bbatsov/rubocop/issues/2975): Make comment indentation before `)` consistent with comment indentation before `}` or `]`. ([@jonas054][]) * [#3010](https://github.com/bbatsov/rubocop/issues/3010): Fix double reporting/correction of spaces after ternary operator colons (now only reported by `Style/SpaceAroundOperators`, and not `Style/SpaceAfterColon` too). ([@owst][]) * [#3006](https://github.com/bbatsov/rubocop/issues/3006): Register an offense for calling `merge!` on a method on a variable inside `each_with_object` in `Performance/RedundantMerge`. ([@lumeet][], [@rrosenblum][]) * [#2886](https://github.com/bbatsov/rubocop/issues/2886): Custom cop changes now bust the cache. ([@ptarjan][]) * [#3043](https://github.com/bbatsov/rubocop/issues/3043): `Style/SpaceAfterNot` will now register an offense for a receiver that is wrapped in parentheses. ([@rrosenblum][]) * [#3039](https://github.com/bbatsov/rubocop/issues/3039): Accept `match` without a receiver in `Performance/EndWith`. ([@lumeet][]) * [#3039](https://github.com/bbatsov/rubocop/issues/3039): Accept `match` without a receiver in `Performance/StartWith`. ([@lumeet][]) * [#3048](https://github.com/bbatsov/rubocop/issues/3048): `Lint/NestedMethodDefinition` shouldn't flag methods defined on Structs. ([@owst][]) * [#2912](https://github.com/bbatsov/rubocop/issues/2912): Check whether a line is aligned with the following line if the preceding line is not an assignment. ([@akihiro17][]) * [#3036](https://github.com/bbatsov/rubocop/issues/3036): Don't let `Lint/UnneededDisable` inspect files that are excluded for the cop. ([@jonas054][]) * [#2874](https://github.com/bbatsov/rubocop/issues/2874): Fix bug when the closing parenthesis is preceded by a newline in array and hash literals in `Style/RedundantParentheses`. ([@lumeet][]) * [#3049](https://github.com/bbatsov/rubocop/issues/3049): Make `Lint/UselessAccessModifier` detect conditionally defined methods and correctly handle dynamically defined methods and singleton class methods. ([@owst][]) * [#3004](https://github.com/bbatsov/rubocop/pull/3004): Don't add `Style/Alias` offenses for use of `alias` in `instance_eval` blocks, since object instances don't respond to `alias_method`. ([@magni-][]) * [#3061](https://github.com/bbatsov/rubocop/pull/3061): Custom cops now show up in --show-cops. ([@ptarjan][]) * [#3088](https://github.com/bbatsov/rubocop/pull/3088): Ignore offenses that involve conflicting HEREDOCs in the `Style/Multiline*BraceLayout` cops. ([@panthomakos][]) * [#3083](https://github.com/bbatsov/rubocop/issues/3083): Do not register an offense for splat block args in `Style/SymbolProc`. ([@rrosenblum][]) * [#3063](https://github.com/bbatsov/rubocop/issues/3063): Don't auto-correct `a + \` into `a + \\` in `Style/LineEndConcatenation`. ([@jonas054][]) * [#3034](https://github.com/bbatsov/rubocop/issues/3034): Report offenses for `RuntimeError.new(msg)` in `Style/RedundantException`. ([@jonas054][]) * [#3016](https://github.com/bbatsov/rubocop/issues/3016): `Style/SpaceAfterComma` now uses `Style/SpaceInsideHashLiteralBraces`'s setting. ([@ptarjan][]) ### Changes * [#2995](https://github.com/bbatsov/rubocop/issues/2995): Removed deprecated path matching syntax. ([@gerrywastaken][]) * [#3025](https://github.com/bbatsov/rubocop/pull/3025): Removed deprecation warnings for `rubocop-todo.yml`. ([@ptarjan][]) * [#3028](https://github.com/bbatsov/rubocop/pull/3028): Add `define_method` to the default list of `IgnoredMethods` of `Style/SymbolProc`. ([@jastkand][]) * [#3064](https://github.com/bbatsov/rubocop/pull/3064): `Style/SpaceAfterNot` highlights the entire expression instead of just the exlamation mark. ([@rrosenblum][]) * [#3085](https://github.com/bbatsov/rubocop/pull/3085): Enable `Style/MultilineArrayBraceLayout` and `Style/MultilineHashBraceLayout` with the `symmetrical` style by default. ([@panthomakos][]) * [#3091](https://github.com/bbatsov/rubocop/pull/3091): Enable `Style/MultilineMethodCallBraceLayout` and `Style/MultilineMethodDefinitionBraceLayout` with the `symmetrical` style by default. ([@panthomakos][]) * [#1830](https://github.com/bbatsov/rubocop/pull/1830): `Style/PredicateName` now ignores the `spec/` directory, since there is a strong convention for using `have_*` and `be_*` helper methods in RSpec. ([@gylaz][]) ## 0.39.0 (2016-03-27) ### New features * `Performance/TimesMap` cop can auto-correct. ([@lumeet][]) * `Style/ZeroLengthPredicate` cop can auto-correct. ([@lumeet][]) * [#2828](https://github.com/bbatsov/rubocop/issues/2828): `Style/ConditionalAssignment` is now configurable to enforce assignment inside of conditions or to enforce assignment to conditions. ([@rrosenblum][]) * [#2862](https://github.com/bbatsov/rubocop/pull/2862): `Performance/Detect` and `Performance/Count` have a new configuration `SafeMode` that is defaulted to `true`. These cops have known issues with `Rails` and other ORM frameworks. With this default configuration, these cops will not run if the `Rails` cops are enabled. ([@rrosenblum][]) * `Style/IfUnlessModifierOfIfUnless` cop added. ([@amuino][]) ### Bug fixes * [#2948](https://github.com/bbatsov/rubocop/issues/2948): `Style/SpaceAroundKeyword` should allow `yield[n]` and `super[n]`. ([@laurelfan][]) * [#2950](https://github.com/bbatsov/rubocop/issues/2950): Fix auto-correcting cases in which precedence has changed in `Style/OneLineConditional`. ([@lumeet][]) * [#2947](https://github.com/bbatsov/rubocop/issues/2947): Fix auto-correcting `if-then` in `Style/Next`. ([@lumeet][]) * [#2904](https://github.com/bbatsov/rubocop/issues/2904): `Style/RedundantParentheses` doesn't flag `-(1.method)` or `+(1.method)`, since removing the parentheses would change the meaning of these expressions. ([@alexdowad][]) * [#2958](https://github.com/bbatsov/rubocop/issues/2958): `Style/MultilineMethodCallIndentation` doesn't fail when inspecting unary ops which span multiple lines. ([@alexdowad][]) * [#2959](https://github.com/bbatsov/rubocop/issues/2959): `Lint/LiteralInInterpolation` doesn't report offenses for iranges and eranges with non-literal endpoints. ([@alexdowad][]) * [#2960](https://github.com/bbatsov/rubocop/issues/2960): `Lint/AssignmentInCondition` catches method assignments (like `obj.attr = val`) in a condition. ([@alexdowad][]) * [#2871](https://github.com/bbatsov/rubocop/issues/2871): Second solution for possible encoding incompatibility when outputting an HTML report. ([@jonas054][]) * [#2967](https://github.com/bbatsov/rubocop/pull/2967): Fix auto-correcting of `===`, `<=`, and `>=` in `Style/ConditionalAssignment`. ([@rrosenblum][]) * [#2977](https://github.com/bbatsov/rubocop/issues/2977): Fix auto-correcting of `"#{$!}"` in `Style/SpecialGlobalVars`. ([@lumeet][]) * [#2935](https://github.com/bbatsov/rubocop/issues/2935): Make configuration loading work if `SafeYAML.load` is private. ([@jonas054][]) ### Changes * `require:` only does relative includes when it starts with a `.`. ([@ptarjan][]) * `Style/IfUnlessModifier` does not trigger if the body is another conditional. ([@amuino][]) * [#2963](https://github.com/bbatsov/rubocop/pull/2963): `Performance/RedundantMerge` will now register an offense inside of `each_with_object`. ([@rrosenblum][]) ## 0.38.0 (2016-03-09) ### New features * `Style/UnlessElse` cop can auto-correct. ([@lumeet][]) * [#2629](https://github.com/bbatsov/rubocop/pull/2629): Add a new public API method, `highlighted_area` to offense. This method returns the range of the highlighted portion of an offense. ([@rrosenblum][]) * `Style/OneLineConditional` cop can auto-correct. ([@lumeet][]) * [#2905](https://github.com/bbatsov/rubocop/issues/2905): `Style/ZeroLengthPredicate` flags code like `array.length < 1`, `1 > array.length`, and so on. ([@alexdowad][]) * [#2892](https://github.com/bbatsov/rubocop/issues/2892): `Lint/BlockAlignment` cop can be configured to be stricter. ([@ptarjan][]) * `Style/Not` is able to autocorrect in cases where parentheses must be added to preserve the meaning of an expression. ([@alexdowad][]) * `Style/Not` auto-corrects comparison expressions by removing `not` and using the opposite comparison. ([@alexdowad][]) ### Bug fixes * Add `require 'time'` to `remote_config.rb` to avoid "undefined method \`rfc2822'". ([@necojackarc][]) * Replace `Rake::TaskManager#last_comment` with `Rake::TaskManager#last_description` for Rake 11 compatibility. ([@tbrisker][]) * Fix false positive in `Style/TrailingCommaInArguments` & `Style/TrailingCommaInLiteral` cops with consistent_comma style. ([@meganemura][]) * [#2861](https://github.com/bbatsov/rubocop/pull/2861): Fix false positive in `Style/SpaceAroundKeyword` for `rescue(...`. ([@rrosenblum][]) * [#2832](https://github.com/bbatsov/rubocop/issues/2832): `Style/MultilineOperationIndentation` treats operations inside blocks inside other operations correctly. ([@jonas054][]) * [#2865](https://github.com/bbatsov/rubocop/issues/2865): Change `require:` in config to be relative to the `.rubocop.yml` file itself. ([@ptarjan][]) * [#2845](https://github.com/bbatsov/rubocop/issues/2845): Handle heredocs in `Style/MultilineLiteralBraceLayout` auto-correct. ([@jonas054][]) * [#2848](https://github.com/bbatsov/rubocop/issues/2848): Handle comments inside arrays in `Style/MultilineArrayBraceLayout` auto-correct. ([@jonas054][]) * `Style/TrivialAccessors` allows predicate methods by default. ([@alexdowad][]) * [#2869](https://github.com/bbatsov/rubocop/issues/2869): Offenses which occur in the body of a `when` clause with multiple arguments will not be missed. ([@alexdowad][]) * `Lint/UselessAccessModifier` recognizes method defs inside a `begin` block. ([@alexdowad][]) * [#2870](https://github.com/bbatsov/rubocop/issues/2870): `Lint/UselessAccessModifier` recognizes method definitions which are passed as an argument to a method call. ([@alexdowad][]) * [#2859](https://github.com/bbatsov/rubocop/issues/2859): `Style/RedundantParentheses` doesn't consider the parentheses in `(!receiver.method arg)` to be redundant, since they might change the meaning of an expression, depending on precedence. ([@alexdowad][]) * [#2852](https://github.com/bbatsov/rubocop/issues/2852): `Performance/Casecmp` doesn't flag uses of `downcase`/`upcase` which are not redundant. ([@alexdowad][]) * [#2850](https://github.com/bbatsov/rubocop/issues/2850): `Style/FileName` doesn't choke on empty files with spaces in their names. ([@alexdowad][]) * [#2834](https://github.com/bbatsov/rubocop/issues/2834): When configured as `ConsistentQuotesInMultiline: true`, `Style/StringLiterals` doesn't error out when inspecting a heredoc with differing indentation across multiple lines. ([@alexdowad][]) * [#2876](https://github.com/bbatsov/rubocop/issues/2876): `Style/ConditionalAssignment` behaves correctly when assignment statement uses a character which has a special meaning in a regex. ([@alexdowad][]) * [#2877](https://github.com/bbatsov/rubocop/issues/2877): `Style/SpaceAroundKeyword` doesn't flag `!super.method`, `!yield.method`, and so on. ([@alexdowad][]) * [#2631](https://github.com/bbatsov/rubocop/issues/2631): `Style/Encoding` can remove unneeded encoding comment when autocorrecting with `when_needed` style. ([@alexdowad][]) * [#2860](https://github.com/bbatsov/rubocop/issues/2860): Fix false positive in `Rails/Date` when `to_time` is chained with safe method. ([@palkan][]) * [#2898](https://github.com/bbatsov/rubocop/issues/2898): `Lint/NestedMethodDefinition` allows methods defined inside `Class.new(S)` blocks. ([@segiddins][]) * [#2894](https://github.com/bbatsov/rubocop/issues/2894): Fix auto-correct an unless with a comparison operator. ([@jweir][]) * [#2911](https://github.com/bbatsov/rubocop/issues/2911): `Style/ClassAndModuleChildren` doesn't flag nested class definitions, where the outer class has an explicit superclass (because such definitions can't be converted to `compact` style). ([@alexdowad][]) * [#2871](https://github.com/bbatsov/rubocop/issues/2871): Don't crash when offense messages are read back from cache with `ASCII-8BIT` encoding and output as HTML or JSON. ([@jonas054][]) * [#2901](https://github.com/bbatsov/rubocop/issues/2901): Don't crash when `ENV['HOME']` is undefined. ([@mikegee][]) * [#2627](https://github.com/bbatsov/rubocop/issues/2627): `Style/BlockDelimiters` does not flag blocks delimited by `{}` when a block call is the final value in a hash with implicit braces (one which is the last argument to an outer method call). ([@alexdowad][]) ### Changes * Update Rake to version 11. ([@tbrisker][]) * [#2629](https://github.com/bbatsov/rubocop/pull/2629): Change the offense range for metrics cops to default to `expression` instead of `keyword` (the offense now spans the entire method, class, or module). ([@rrosenblum][]) * [#2891](https://github.com/bbatsov/rubocop/pull/2891): Change the caching of remote configs to live alongside the parent file. ([@Fryguy][]) * [#2662](https://github.com/bbatsov/rubocop/issues/2662): When setting options for Rake task, nested arrays can be used in the `options`, `formatters`, and `requires` arrays. ([@alexdowad][]) * [#2925](https://github.com/bbatsov/rubocop/pull/2925): Bump unicode-display_width dependency to >= 1.0.1. ([@jspanjers][]) * [#2875](https://github.com/bbatsov/rubocop/issues/2875): `Style/SignalException` does not flag calls to `fail` if a custom method named `fail` is defined in the same file. ([@alexdowad][]) * [#2923](https://github.com/bbatsov/rubocop/issues/2923): `Style/FileName` considers file names which contain a ? or ! character to still be "snake case". ([@alexdowad][]) * [#2879](https://github.com/bbatsov/rubocop/issues/2879): When autocorrecting, `Lint/UnusedMethodArgument` removes unused block arguments rather than simply prefixing them with an underscore. ([@alexdowad][]) ## 0.37.2 (2016-02-11) ### Bug fixes * Fix auto-correction of array and hash literals in `Lint/LiteralInInterpolation`. ([@lumeet][]) * [#2815](https://github.com/bbatsov/rubocop/pull/2815): Fix missing assets for html formatter. ([@prsimp][]) * `Style/RedundantParentheses` catches offenses involving the 2nd argument to a method call without parentheses, if the 2nd argument is a hash. ([@alexdowad][]) * `Style/RedundantParentheses` catches offenses inside an array literal. ([@alexdowad][]) * `Style/RedundantParentheses` doesn't flag `method (:arg) {}`, since removing the parentheses would change the meaning of the expression. ([@alexdowad][]) * `Performance/Detect` doesn't flag code where `first` or `last` takes an argument, as it cannot be transformed to equivalent code using `detect`. ([@alexdowad][]) * `Style/SpaceAroundOperators` ignores aref assignments. ([@alexdowad][]) * `Style/RescueModifier` indents code correctly when auto-correcting. ([@alexdowad][]) * `Style/RedundantMerge` indents code correctly when auto-correcting, even if the corrected hash had multiple keys, and even if the corrected code was indented to start with. ([@alexdowad][]) * [#2831](https://github.com/bbatsov/rubocop/issues/2831): `Performance/RedundantMerge` doesn't break code by autocorrecting a `#merge!` call which occurs at tail position in a block. ([@alexdowad][]) ### Changes * Handle auto-correction of nested interpolations in `Lint/LiteralInInterpolation`. ([@lumeet][]) * RuboCop results cache uses different directory names when there are many (or long) CLI options, to avoid a very long path which could cause failures on some filesystems. ([@alexdowad][]) ## 0.37.1 (2016-02-09) ### New features * [#2798](https://github.com/bbatsov/rubocop/pull/2798): `Rails/FindEach` cop works with `where.not`. ([@pocke][]) * `Style/MultilineBlockLayout` can correct offenses which involve argument destructuring. ([@alexdowad][]) * `Style/SpaceAroundKeyword` checks `super` nodes with no args. ([@alexdowad][]) * `Style/SpaceAroundKeyword` checks `defined?` nodes. ([@alexdowad][]) * [#2719](https://github.com/bbatsov/rubocop/issues/2719): `Style/ConditionalAssignment` handles correcting the alignment of `end`. ([@rrosenblum][]) ### Bug fixes * Fix auto-correction of `not` with parentheses in `Style/Not`. ([@lumeet][]) * [#2784](https://github.com/bbatsov/rubocop/issues/2784): RuboCop can inspect `super { ... }` and `super(arg) { ... }`. ([@alexdowad][]) * [#2781](https://github.com/bbatsov/rubocop/issues/2781): `Performance/RedundantMerge` doesn't flag calls to `#update`, since many classes have methods by this name (not only `Hash`). ([@alexdowad][]) * [#2780](https://github.com/bbatsov/rubocop/issues/2780): `Lint/DuplicateMethods` does not flag method definitions inside dynamic `Class.new` blocks. ([@alexdowad][]) * [#2775](https://github.com/bbatsov/rubocop/issues/2775): `Style/SpaceAroundKeyword` doesn't flag `yield.method`. ([@alexdowad][]) * [#2774](https://github.com/bbatsov/rubocop/issues/2774): `Style/SpaceAroundOperators` doesn't flag calls to `#[]`. ([@alexdowad][]) * [#2772](https://github.com/bbatsov/rubocop/issues/2772): RuboCop doesn't crash when `AllCops` section in configuration file is empty (rather, it displays a warning as intended). ([@alexdowad][]) * [#2737](https://github.com/bbatsov/rubocop/issues/2737): `Style/GuardClause` handles `elsif` clauses correctly. ([@alexdowad][]) * [#2735](https://github.com/bbatsov/rubocop/issues/2735): `Style/MultilineBlockLayout` doesn't cause an infinite loop by moving `end` onto the same line as the block args. ([@alexdowad][]) * [#2715](https://github.com/bbatsov/rubocop/issues/2715): `Performance/RedundantMatch` doesn't flag calls to `#match` which take a block. ([@alexdowad][]) * [#2704](https://github.com/bbatsov/rubocop/issues/2704): `Lint/NestedMethodDefinition` doesn't flag singleton defs which define a method on the value of a local variable. ([@alexdowad][]) * [#2660](https://github.com/bbatsov/rubocop/issues/2660): `Style/TrailingUnderscoreVariable` shows recommended code in its offense message. ([@alexdowad][]) * [#2671](https://github.com/bbatsov/rubocop/issues/2671): `Style/WordArray` doesn't attempt to inspect strings with invalid encoding, to avoid failing with an encoding error. ([@alexdowad][]) ### Changes * [#2739](https://github.com/bbatsov/rubocop/issues/2739): Change the configuration option `when_needed` in `Style/FrozenStringLiteralComment` to add a `frozen_string_literal` comment to all files when the `TargetRubyVersion` is set to 2.3+. ([@rrosenblum][]) ## 0.37.0 (2016-02-04) ### New features * [#2620](https://github.com/bbatsov/rubocop/pull/2620): New cop `Style/ZeroLengthPredicate` checks for `object.size == 0` and variants, and suggests replacing them with an appropriate `empty?` predicate. ([@drenmi][]) * [#2657](https://github.com/bbatsov/rubocop/pull/2657): Floating headers in HTML output. ([@mattparlane][]) * Add new `Style/SpaceAroundKeyword` cop. ([@lumeet][]) * [#2745](https://github.com/bbatsov/rubocop/pull/2745): New cop `Style/MultilineHashBraceLayout` checks that the closing brace in a hash literal is symmetrical with respect to the opening brace and the hash elements. ([@panthomakos][]) * [#2761](https://github.com/bbatsov/rubocop/pull/2761): New cop `Style/MultilineMethodDefinitionBraceLayout` checks that the closing brace in a method definition is symmetrical with respect to the opening brace and the method parameters. ([@panthomakos][]) * [#2699](https://github.com/bbatsov/rubocop/pull/2699): `Performance/Casecmp` can register offenses when `str.downcase` or `str.upcase` are passed to an equality method. ([@rrosenblum][]) * [#2766](https://github.com/bbatsov/rubocop/pull/2766): New cop `Style/MultilineMethodCallBraceLayout` checks that the closing brace in a method call is symmetrical with respect to the opening brace and the method arguments. ([@panthomakos][]) * `Style/Semicolon` can autocorrect useless semicolons at the beginning of a line. ([@alexdowad][]) ### Bug fixes * [#2723](https://github.com/bbatsov/rubocop/issues/2723): Fix NoMethodError in Style/GuardClause. ([@drenmi][]) * [#2674](https://github.com/bbatsov/rubocop/issues/2674): Also check for Hash#update alias in `Performance/RedundantMerge`. ([@drenmi][]) * [#2630](https://github.com/bbatsov/rubocop/issues/2630): Take frozen string literals into account in `Style/MutableConstant`. ([@segiddins][]) * [#2642](https://github.com/bbatsov/rubocop/issues/2642): Support assignment via `||=` in `Style/MutableConstant`. ([@segiddins][]) * [#2646](https://github.com/bbatsov/rubocop/issues/2646): Fix auto-correcting assignment to a constant in `Style/ConditionalAssignment`. ([@segiddins][]) * [#2614](https://github.com/bbatsov/rubocop/issues/2614): Check for zero return value from `casecmp` in `Performance/casecmp`. ([@segiddins][]) * [#2647](https://github.com/bbatsov/rubocop/issues/2647): Allow `xstr` interpolations in `Lint/LiteralInInterpolation`. ([@segiddins][]) * Report a violation when `freeze` is called on a frozen string literal in `Style/RedundantFreeze`. ([@segiddins][]) * [#2641](https://github.com/bbatsov/rubocop/issues/2641): Fix crashing on empty methods with block args in `Performance/RedundantBlockCall`. ([@segiddins][]) * `Lint/DuplicateMethods` doesn't crash when `class_eval` is used with an implicit receiver. ([@lumeet][]) * [#2654](https://github.com/bbatsov/rubocop/issues/2654): Fix handling of unary operations in `Style/RedundantParentheses`. ([@lumeet][]) * [#2661](https://github.com/bbatsov/rubocop/issues/2661): `Style/Next` doesn't crash when auto-correcting modifier `if/unless`. ([@lumeet][]) * [#2665](https://github.com/bbatsov/rubocop/pull/2665): Make specs pass when running on Windows. ([@jonas054][]) * [#2691](https://github.com/bbatsov/rubocop/pull/2691): Do not register an offense in `Performance/TimesMap` for calling `map` or `collect` on a variable named `times`. ([@rrosenblum][]) * [#2689](https://github.com/bbatsov/rubocop/pull/2689): Change `Performance/RedundantBlockCall` to respect parentheses usage. ([@rrosenblum][]) * [#2694](https://github.com/bbatsov/rubocop/issues/2694): Fix caching when using a different JSON gem such as Oj. ([@georgyangelov][]) * [#2707](https://github.com/bbatsov/rubocop/pull/2707): Change `Lint/NestedMethodDefinition` to respect `Class.new` and `Module.new`. ([@owst][]) * [#2701](https://github.com/bbatsov/rubocop/pull/2701): Do not consider assignments to the same variable as useless if later assignments are within a loop. ([@owst][]) * [#2696](https://github.com/bbatsov/rubocop/issues/2696): `Style/NestedModifier` adds parentheses around a condition when needed. ([@lumeet][]) * [#2666](https://github.com/bbatsov/rubocop/issues/2666): Fix bug when auto-correcting symbol literals in `Lint/LiteralInInterpolation`. ([@lumeet][]) * [#2664](https://github.com/bbatsov/rubocop/issues/2664): `Performance/Casecmp` can auto-correct case comparison to variables and method calls without error. ([@rrosenblum][]) * [#2729](https://github.com/bbatsov/rubocop/issues/2729): Fix handling of hash literal as the first argument in `Style/RedundantParentheses`. ([@lumeet][]) * [#2703](https://github.com/bbatsov/rubocop/issues/2703): Handle byte order mark in `Style/IndentationWidth`, `Style/ElseAlignment`, `Lint/EndAlignment`, and `Lint/DefEndAlignment`. ([@jonas054][]) * [#2710](https://github.com/bbatsov/rubocop/pull/2710): Fix handling of fullwidth characters in some cops. ([@seikichi][]) * [#2690](https://github.com/bbatsov/rubocop/issues/2690): Fix alignment of operands that are part of an assignment in `Style/MultilineOperationIndentation`. ([@jonas054][]) * [#2228](https://github.com/bbatsov/rubocop/issues/2228): Use the config of a related cop whether it's enabled or not. ([@madwort][]) * [#2721](https://github.com/bbatsov/rubocop/issues/2721): Do not register an offense for constants wrapped in parentheses passed to `rescue` in `Style/RedundantParentheses`. ([@rrosenblum][]) * [#2742](https://github.com/bbatsov/rubocop/issues/2742): Fix `Style/TrailingCommaInArguments` & `Style/TrailingCommaInLiteral` for inline single element arrays. ([@annih][]) * [#2768](https://github.com/bbatsov/rubocop/issues/2768): Allow parentheses after keyword `not` in `Style/MethodCallParentheses`. ([@lumeet][]) * [#2758](https://github.com/bbatsov/rubocop/issues/2758): Allow leading underscores in camel case variable names.([@mmcguinn][]) ### Changes * Remove `Style/SpaceAfterControlKeyword` and `Style/SpaceBeforeModifierKeyword` as the more generic `Style/SpaceAroundKeyword` handles the same cases. ([@lumeet][]) * Handle comparisons with `!=` in `Performance/casecmp`. ([@segiddins][]) * [#2684](https://github.com/bbatsov/rubocop/pull/2684): Do not base `Style/FrozenStringLiteralComment` on the version of Ruby that is running. ([@rrosenblum][]) * [#2732](https://github.com/bbatsov/rubocop/issues/2732): Change the default style of `Style/SignalException` to `only_raise`. ([@bbatsov][]) ## 0.36.0 (2016-01-14) ### New features * [#2598](https://github.com/bbatsov/rubocop/pull/2598): New cop `Lint/RandOne` checks for `rand(1)`, `Kernel.rand(1.0)` and similar calls. Such call are most likely a mistake because they always return `0`. ([@DNNX][]) * [#2590](https://github.com/bbatsov/rubocop/pull/2590): New cop `Performance/DoubleStartEndWith` checks for two `start_with?` (or `end_with?`) calls joined by `||` with the same receiver, like `str.start_with?('x') || str.start_with?('y')` and suggests using one call instead: `str.start_with?('x', 'y')`. ([@DNNX][]) * [#2583](https://github.com/bbatsov/rubocop/pull/2583): New cop `Performance/TimesMap` checks for `x.times.map{}` and suggests replacing them with `Array.new(x){}`. ([@DNNX][]) * [#2581](https://github.com/bbatsov/rubocop/pull/2581): New cop `Lint/NextWithoutAccumulator` finds bare `next` in `reduce`/`inject` blocks which assigns `nil` to the accumulator. ([@mvidner][]) * [#2529](https://github.com/bbatsov/rubocop/pull/2529): Add EnforcedStyle config parameter to IndentArray. ([@jawshooah][]) * [#2479](https://github.com/bbatsov/rubocop/pull/2479): Add option `AllowHeredoc` to `Metrics/LineLength`. ([@fphilipe][]) * [#2416](https://github.com/bbatsov/rubocop/pull/2416): New cop `Style/ConditionalAssignment` checks for assignment of the same variable in all branches of conditionals and replaces them with a single assignment to the return of the conditional. ([@rrosenblum][]) * [#2410](https://github.com/bbatsov/rubocop/pull/2410): New cop `Style/IndentAssignment` checks the indentation of the first line of the right-hand-side of a multi-line assignment. ([@panthomakos][]) * [#2431](https://github.com/bbatsov/rubocop/issues/2431): Add `IgnoreExecutableScripts` option to `Style/FileName`. ([@sometimesfood][]) * [#2460](https://github.com/bbatsov/rubocop/pull/2460): New cop `Style/UnneededInterpolation` checks for strings that are just an interpolated expression. ([@cgriego][]) * [#2361](https://github.com/bbatsov/rubocop/pull/2361): `Style/MultilineAssignmentLayout` cop checks for a newline after the assignment operator in a multi-line assignment. ([@panthomakos][]) * [#2462](https://github.com/bbatsov/rubocop/issues/2462): `Lint/UselessAccessModifier` can catch more types of useless access modifiers. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/Casecmp` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/RangeInclude` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/RedundantSortBy` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/LstripRstrip` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/StartWith` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/EndWith` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/RedundantMerge` cop. ([@alexdowad][]) * `Lint/Debugger` cop can now auto-correct offenses. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/RedundantMatch` cop. ([@alexdowad][]) * [#1677](https://github.com/bbatsov/rubocop/issues/1677): Add new `Performance/RedundantBlockCall` cop. ([@alexdowad][]) * [#1954](https://github.com/bbatsov/rubocop/issues/1954): `Lint/UnneededDisable` can now autocorrect. ([@alexdowad][]) * [#2501](https://github.com/bbatsov/rubocop/issues/2501): Add new `Lint/ImplicitStringConcatenation` cop. ([@alexdowad][]) * Add new `Style/RedundantParentheses` cop. ([@lumeet][]) * [#1346](https://github.com/bbatsov/rubocop/issues/1346): `Style/SpecialGlobalVars` can be configured to use either `use_english_names` or `use_perl_names` styles. ([@alexdowad][]) * [#2426](https://github.com/bbatsov/rubocop/issues/2426): New `Style/NestedParenthesizedCalls` cop checks for non-parenthesized method calls nested inside a parenthesized call, like `method1(method2 arg)`. ([@alexdowad][]) * [#2502](https://github.com/bbatsov/rubocop/issues/2502): The `--stdin` and `--auto-correct` CLI options can be combined, and if you do so, corrected code is printed to stdout. ([@alexdowad][]) * `Style/ConditionalAssignment` works on conditionals with a common aref assignment (like `array[index] = val`) or attribute assignment (like `self.attribute = val`). ([@alexdowad][]) * [#2476](https://github.com/bbatsov/rubocop/issues/2476): `Style/GuardClause` catches if..else nodes with one branch which terminates the execution of the current scope. ([@alexdowad][]) * New `Style/IdenticalConditionalBranches` flags `if..else` and `case..when..else` constructs with an identical line at the end of each branch. ([@alexdowad][]) * [#207](https://github.com/bbatsov/rubocop/issues/207): Add new `Lint/FloatOutOfRange` cop which catches floating-point literals which are too large or too small for Ruby to represent. ([@alexdowad][]) * `Style/GuardClause` doesn't report offenses in places where correction would make a line too long. ([@alexdowad][]) * `Lint/DuplicateMethods` can find duplicate method definitions in many more circumstances, even across multiple files; however, it ignores definitions inside `if` or something which could be a DSL method. ([@alexdowad][]) * A warning is printed if an invalid `EnforcedStyle` is configured. ([@alexdowad][]) * [#1367](https://github.com/bbatsov/rubocop/issues/1367): New `Lint/IneffectiveAccessModifier` checks for access modifiers which are erroneously applied to a singleton method, where they have no effect. ([@alexdowad][]) * [#1614](https://github.com/bbatsov/rubocop/issues/1614): `Lint/BlockAlignment` aligns block end with splat operator when applied to a splatted method call. ([@alexdowad][]) * [#2263](https://github.com/bbatsov/rubocop/issues/2263): Warn if `task.options = %w(--format ...)` is used when configuring `RuboCop::RakeTask`; this should be `task.formatters = ...` instead. ([@alexdowad][]) * [#2511](https://github.com/bbatsov/rubocop/issues/2511): `--no-offense-counts` CLI option suppresses the inclusion of offense count lines in auto-generated config. ([@alexdowad][]) * [#2504](https://github.com/bbatsov/rubocop/issues/2504): New `AllowForAlignment` config parameter for `Style/SingleSpaceBeforeFirstArg` allows the insertion of extra spaces before the first argument if it aligns it with something on the preceding or following line. ([@alexdowad][]) * [#2478](https://github.com/bbatsov/rubocop/issues/2478): `Style/ExtraSpacing` has new `ForceEqualSignAlignment` config parameter which forces = signs on consecutive lines to be aligned, and it can auto-correct. ([@alexdowad][]) * `Lint/BlockAlignment` aligns block end with unary operators like ~, -, or ! when such operators are applied to the method call taking the block. ([@alexdowad][]) * [#1460](https://github.com/bbatsov/rubocop/issues/1460): `Style/Alias` supports both `prefer_alias` and `prefer_alias_method` styles. ([@alexdowad][]) * [#1569](https://github.com/bbatsov/rubocop/issues/1569): New `ExpectMatchingDefinition` config parameter for `Style/FileName` makes it check for a class or module definition in each file which corresponds to the file name and path. ([@alexdowad][]) * [#2480](https://github.com/bbatsov/rubocop/pull/2480): Add a configuration to `Style/ConditionalAssignment` to check and correct conditionals that contain multiple assignments. ([@rrosenblum][]) * [#2480](https://github.com/bbatsov/rubocop/pull/2480): Allow `Style/ConditionalAssignment` to correct assignment in ternary operations. ([@rrosenblum][]) * [#2480](https://github.com/bbatsov/rubocop/pull/2480): Allow `Style/ConditionalAssignment` to correct comparable methods. ([@rrosenblum][]) * [#1633](https://github.com/bbatsov/rubocop/issues/1633): New cop `Style/MultilineMethodCallIndentation` takes over the responsibility for checking alignment of methods from the `Style/MultilineOperationIndentation` cop. ([@jonas054][]) * [#2472](https://github.com/bbatsov/rubocop/pull/2472): New cop `Style/MultilineArrayBraceLayout` checks that the closing brace in an array literal is symmetrical with respect to the opening brace and the array elements. ([@panthomakos][]) * [#1543](https://github.com/bbatsov/rubocop/issues/1543): `Style/WordArray` has both `percent` and `brackets` (which enforces the use of bracketed arrays for strings) styles. ([@alexdowad][]) * `Style/SpaceAroundOperators` has `AllowForAlignment` config parameter which allows extra spaces on the left if they serve to align the operator with another. ([@alexdowad][]) * `Style/SymbolArray` has both `percent` and `brackets` (which enforces the user of bracketed arrays for symbols) styles. ([@alexdowad][]) * [#2343](https://github.com/bbatsov/rubocop/issues/2343): Entire cop types (or "departments") can be disabled using in .rubocop.yml using config like `Style: Enabled: false`. ([@alexdowad][]) * [#2399](https://github.com/bbatsov/rubocop/issues/2399): New `start_of_line` style for `Lint/EndAlignment` aligns a closing `end` keyword with the start of the line where the opening keyword appears. ([@alexdowad][]) * [#1545](https://github.com/bbatsov/rubocop/issues/1545): New `Regex` config parameter for `Style/FileName` allows user to provide their own regex for validating file names. ([@alexdowad][]) * [#2253](https://github.com/bbatsov/rubocop/issues/2253): New `DefaultFormatter` config parameter can be used to set formatter from within .rubocop.yml. ([@alexdowad][]) * [#2481](https://github.com/bbatsov/rubocop/issues/2481): New `WorstOffendersFormatter` prints a list of files with offenses (and offense counts), showing the files with the most offenses first. ([@alexdowad][]) * New `IfInsideElse` cop catches `if..end` nodes which can be converted into an `elsif` instead, reducing the nesting level. ([@alexdowad][]) * [#1725](https://github.com/bbatsov/rubocop/issues/1725): --color CLI option forces color output, even when not printing to a TTY. ([@alexdowad][]) * [#2549](https://github.com/bbatsov/rubocop/issues/2549): New `ConsistentQuotesInMultiline` config param for `Style/StringLiterals` forces all literals which are concatenated using \ to use the same quote style. ([@alexdowad][]) * [#2560](https://github.com/bbatsov/rubocop/issues/2560): `Style/AccessModifierIndentation`, `Style/CaseIndentation`, `Style/FirstParameterIndentation`, `Style/IndentArray`, `Style/IndentAssignment`, `Style/IndentHash`, `Style/MultilineMethodCallIndentation`, and `Style/MultilineOperationIndentation` all have a new `IndentationWidth` parameter which can be used to override the indentation width from `Style/IndentationWidth`. ([@alexdowad][]) * Add new `Performance/HashEachMethods` cop. ([@ojab][]) * New cop `Style/FrozenStringLiteralComment` will check for and add the comment `# frozen_string_literal: true` to the top of files. This will help with upgrading to Ruby 3.0. ([@rrosenblum][]) ### Bug Fixes * [#2594](https://github.com/bbatsov/rubocop/issues/2594): `Style/EmptyLiteral` autocorrector respects `Style/StringLiterals:EnforcedStyle` config. ([@DNNX][]) * [#2411](https://github.com/bbatsov/rubocop/issues/2411): Make local inherited configuration override configuration loaded from gems. ([@jonas054][]) * [#2413](https://github.com/bbatsov/rubocop/issues/2413): Allow `%Q` for dynamic strings with double quotes inside them. ([@jonas054][]) * [#2404](https://github.com/bbatsov/rubocop/issues/2404): `Style/Next` does not remove comments when auto-correcting. ([@lumeet][]) * `Style/Next` handles auto-correction of nested offenses. ([@lumeet][]) * `Style/VariableInterpolation` now detects non-numeric regex back references. ([@cgriego][]) * `ProgressFormatter` fully respects the `--no-color` switch. ([@savef][]) * Replace `Time.zone.current` with `Time.current` on `Rails::TimeZone` cop message. ([@volmer][]) * [#2451](https://github.com/bbatsov/rubocop/issues/2451): `Style/StabbyLambdaParentheses` does not treat method calls named `lambda` as lambdas. ([@domcleal][]) * [#2463](https://github.com/bbatsov/rubocop/issues/2463): Allow comments before an access modifier. ([@codebeige][]) * [#2471](https://github.com/bbatsov/rubocop/issues/2471): `Style/MethodName` doesn't choke on methods which are defined inside methods. ([@alexdowad][]) * [#2449](https://github.com/bbatsov/rubocop/issues/2449): `Style/StabbyLambdaParentheses` only checks lambdas in the arrow form. ([@lumeet][]) * [#2456](https://github.com/bbatsov/rubocop/issues/2456): `Lint/NestedMethodDefinition` doesn't register offenses for method definitions inside an eval block (either `instance_eval`, `class_eval`, or `module_eval`). ([@alexdowad][]) * [#2464](https://github.com/bbatsov/rubocop/issues/2464): `Style/ParallelAssignment` understands aref and attribute assignments, and doesn't warn if they can't be correctly rearranged into a series of single assignments. ([@alexdowad][]) * [#2482](https://github.com/bbatsov/rubocop/issues/2482): `Style/AndOr` doesn't raise an exception when trying to autocorrect `!variable or ...`. ([@alexdowad][]) * [#2446](https://github.com/bbatsov/rubocop/issues/2446): `Style/Tab` doesn't register errors for leading tabs which occur inside a string literal (including heredoc). ([@alexdowad][]) * [#2452](https://github.com/bbatsov/rubocop/issues/2452): `Style/TrailingComma` incorrectly categorizes single-line hashes in methods calls. ([@panthomakos][]) * [#2441](https://github.com/bbatsov/rubocop/issues/2441): `Style/AlignParameters` doesn't crash if it finds nested offenses. ([@alexdowad][]) * [#2436](https://github.com/bbatsov/rubocop/issues/2436): `Style/SpaceInsideHashLiteralBraces` doesn't mangle a hash literal which is not surrounded by curly braces, but has another hash literal which does as its first key. ([@alexdowad][]) * [#2483](https://github.com/bbatsov/rubocop/issues/2483): `Style/Attr` differentiate between attr_accessor and attr_reader. ([@weh][]) * `Style/ConditionalAssignment` doesn't crash if it finds a `case` with an empty branch. ([@lumeet][]) * [#2506](https://github.com/bbatsov/rubocop/issues/2506): `Lint/FormatParameterMismatch` understands `%{}` and `%<>` interpolations. ([@alexdowad][]) * [#2145](https://github.com/bbatsov/rubocop/issues/2145): `Lint/ParenthesesAsGroupedExpression` ignores calls with multiple arguments, since they are not ambiguous. ([@alexdowad][]) * [#2484](https://github.com/bbatsov/rubocop/issues/2484): Remove two vulnerabilities in cache handling. ([@jonas054][]) * [#2517](https://github.com/bbatsov/rubocop/issues/2517): `Lint/UselessAccessModifier` doesn't think that an access modifier applied to `attr_writer` is useless. ([@alexdowad][]) * [#2518](https://github.com/bbatsov/rubocop/issues/2518): `Style/ConditionalAssignment` doesn't think that branches using `<<` and `[]=` should be combined. ([@alexdowad][]) * `CharacterLiteral` auto-corrector now properly corrects `?'`. ([@bfontaine][]) * [#2313](https://github.com/bbatsov/rubocop/issues/2313): `Rails/FindEach` doesn't break code which uses `order(...).each`, `limit(...).each`, and so on. ([@alexdowad][]) * [#1938](https://github.com/bbatsov/rubocop/issues/1938): `Rails/FindBy` doesn't autocorrect `where(...).first` to `find_by`, since the returned record is often different. ([@alexdowad][]) * [#1801](https://github.com/bbatsov/rubocop/issues/1801): `EmacsFormatter` strips newlines out of error messages, if there are any. ([@alexdowad][]) * [#2534](https://github.com/bbatsov/rubocop/issues/2534): `Style/RescueEnsureAlignment` works on `rescue` nested inside a `class` or `module` block. ([@alexdowad][]) * `Lint/BlockAlignment` does not refer to a block terminator as `end` when it is actually `}`. ([@alexdowad][]) * [#2540](https://github.com/bbatsov/rubocop/issues/2540): `Lint/FormatParameterMismatch` understands format specifiers with multiple flags. ([@alexdowad][]) * [#2538](https://github.com/bbatsov/rubocop/issues/2538): `Style/SpaceAroundOperators` doesn't eat newlines. ([@alexdowad][]) * [#2531](https://github.com/bbatsov/rubocop/issues/2531): `Style/AndOr` autocorrects in cases where parentheses must be added, even inside a nested begin node. ([@alexdowad][]) * [#2450](https://github.com/bbatsov/rubocop/issues/2450): `Style/Next` adjusts indentation when auto-correcting, to avoid introducing new offenses. ([@alexdowad][]) * [#2066](https://github.com/bbatsov/rubocop/issues/2066): `Style/TrivialAccessors` doesn't flag what appear to be trivial accessor method definitions, if they are nested inside a call to `instance_eval`. ([@alexdowad][]) * `Style/SymbolArray` doesn't flag arrays of symbols if a symbol contains a space character. ([@alexdowad][]) * `Style/SymbolArray` can auto-correct offenses. ([@alexdowad][]) * [#2546](https://github.com/bbatsov/rubocop/issues/2546): Report when two `rubocop:disable` comments (not the single line kind) for a given cop apppear in a file with no `rubocop:enable` in between. ([@jonas054][]) * [#2552](https://github.com/bbatsov/rubocop/issues/2552): `Style/Encoding` can auto-correct files with a blank first line. ([@alexdowad][]) * [#2556](https://github.com/bbatsov/rubocop/issues/2556): `Style/SpecialGlobalVariables` generates auto-config correctly. ([@alexdowad][]) * [#2565](https://github.com/bbatsov/rubocop/issues/2565): Let `Style/SpaceAroundOperators` leave spacing around `=>` to `Style/AlignHash`. ([@jonas054][]) * [#2569](https://github.com/bbatsov/rubocop/issues/2569): `Style/MethodCallParentheses` doesn't register warnings for `object.()` syntax, since it is handled by `Style/LambdaCall`. ([@alexdowad][]) * [#2570](https://github.com/bbatsov/rubocop/issues/2570): `Performance/RedundantMerge` doesn't break code with a modifier `if` when autocorrecting. ([@alexdowad][]) * `Performance/RedundantMerge` doesn't break code with a modifier `while` or `until` when autocorrecting. ([@alexdowad][]) * [#2574](https://github.com/bbatsov/rubocop/issues/2574): `variable` style for `Lint/EndAlignment` is working again. ([@alexdowad][]) * `Lint/EndAlignment` can autocorrect offenses on the RHS of an assignment to an instance variable, class variable, constant, and so on; previously, it only worked if the LHS was a local variable. ([@alexdowad][]) * [#2580](https://github.com/bbatsov/rubocop/issues/2580): `Style/StringReplacement` doesn't break code when autocorrection involves a regex with embedded escapes (like /\n/). ([@alexdowad][]) * [#2582](https://github.com/bbatsov/rubocop/issues/2582): `Style/AlignHash` doesn't move a key so far left that it goes onto the previous line (in an attempt to align). ([@alexdowad][]) * [#2588](https://github.com/bbatsov/rubocop/issues/2588): `Style/SymbolProc` doesn't break code when autocorrecting a method call with a trailing comma in the argument list. ([@alexdowad][]) * [#2448](https://github.com/bbatsov/rubocop/issues/2448): `Style/TrailingCommaInArguments` and `Style/TrailingCommaInLiteral` don't special-case single-item lists in a way which contradicts the documentation. ([@alexdowad][]) * Fix for remote config files to only load from on http and https URLs. ([@ptrippett][]) * [#2604](https://github.com/bbatsov/rubocop/issues/2604): `Style/FileName` doesn't fail on empty files when `ExpectMatchingDefinition` is true. ([@alexdowad][]) * `Style/RedundantFreeze` registers offences for frozen dynamic symbols. ([@segiddins][]) * [#2609](https://github.com/bbatsov/rubocop/issues/2609): All cops which rely on the `AutocorrectUnlessChangingAST` module can now autocorrect files which contain `__FILE__`. ([@alexdowad][]) * [#2608](https://github.com/bbatsov/rubocop/issues/2608): `Style/ConditionalAssignment` can autocorrect `=~` within a ternary expression. ([@alexdowad][]) ### Changes * [#2427](https://github.com/bbatsov/rubocop/pull/2427): Allow non-snake-case file names (e.g. `some-random-script`) for Ruby scripts that have a shebang. ([@sometimesfood][]) * [#2430](https://github.com/bbatsov/rubocop/pull/2430): `Lint/UnneededDisable` now adds "unknown cop" to messages if cop names in `rubocop:disable` comments are unrecognized, or "did you mean ..." if they are misspelled names of existing cops. ([@jonas054][]) * [#947](https://github.com/bbatsov/rubocop/issues/947): `Style/Documentation` considers classes and modules which only define constants to be "namespaces", and doesn't flag them for lack of a documentation comment. ([@alexdowad][]) * [#2467](https://github.com/bbatsov/rubocop/issues/2467): Explicitly inheriting configuration from the rubocop gem in .rubocop.yml is not allowed. ([@alexdowad][]) * [#2322](https://github.com/bbatsov/rubocop/issues/2322): Output of --auto-gen-config shows content of default config parameters which are Arrays; this is especially useful for SupportedStyles. ([@alexdowad][]) * [#1566](https://github.com/bbatsov/rubocop/issues/1566): When autocorrecting on Windows, line endings are not converted to "\r\n" in untouched portions of the source files; corrected portions may use "\n" rather than "\r\n". ([@alexdowad][]) * New `rake repl` task can be used for experimentation when working on RuboCop. ([@alexdowad][]) * `Lint/SpaceBeforeFirstArg` cop has been removed, since it just duplicates `Style/SingleSpaceBeforeFirstArg`. ([@alexdowad][]) * `Style/SingleSpaceBeforeFirstArg` cop has been renamed to `Style/SpaceBeforeFirstArg`, which more accurately reflects what it now does. ([@alexdowad][]) * `Style/UnneededPercentQ` reports `%q()` strings with what only appears to be an escape, but is not really (there are no escapes in `%q()` strings). ([@alexdowad][]) * `Performance/StringReplacement`, `Performance\StartWith`, and `Performance\EndWith` more accurately identify code which can be improved. ([@alexdowad][]) * The `MultiSpaceAllowedForOperators` config parameter for `Style/SpaceAroundOperators` has been removed, as it is made redundant by `AllowForAlignment`. If someone attempts to use it, config validation will fail with a helpful message. ([@alexdowad][]) * The `RunRailsCops` config parameter in .rubocop.yml is now obsolete. If someone attempts to use it, config validation will fail with a helpful message. ([@alexdowad][]) * If .rubocop.yml contains configuration for a custom cop, no warning regarding "unknown cop" will be printed. The custom cop must inherit from RuboCop::Cop::Cop, and must be loaded into memory for this to work. ([@alexdowad][]) * [#2102](https://github.com/bbatsov/rubocop/issues/2102): If .rubocop.yml exists in the working directory when running --auto-gen-config, any `Exclude` config parameters in .rubocop.yml will be merged into the generated .rubocop_todo.yml. ([@alexdowad][]) * [#1895](https://github.com/bbatsov/rubocop/issues/1895): Remove `Rails/DefaultScope` cop. ([@alexdowad][]) * [#2550](https://github.com/bbatsov/rubocop/issues/2550): New `TargetRubyVersion` configuration parameter can be used to specify which version of the Ruby interpreter the inspected code is intended to run on. ([@alexdowad][]) * [#2557](https://github.com/bbatsov/rubocop/issues/2557): `Style/GuardClause` does not warn about `if` nodes whose condition spans multiple lines. ([@alexdowad][]) * `Style/EmptyLinesAroundClassBody`, `Style/EmptyLinesAroundModuleBody`, and `Style/EmptyLinesAroundBlockBody` accept an empty body with no blank line, even if configured to `empty_lines` style. This is because the empty lines only serve to provide a break between the header, body, and footer, and are redundant if there is no body. ([@alexdowad][]) * [#2554](https://github.com/bbatsov/rubocop/issues/2554): `Style/FirstMethodArgumentLineBreak` handles implicit hash arguments without braces; `Style/FirstHashElementLineBreak` still handles those with braces. ([@alexdowad][]) * `Style/TrailingComma` has been split into `Style/TrailingCommaInArguments` and `Style/TrailingCommaInLiteral`. ([@alexdowad][]) * RuboCop returns process exit code 2 if it fails due to bad configuration, bad CLI options, or an internal error. If it runs successfully but finds one or more offenses, it still exits with code 1, as was previously the case. This is helpful when invoking RuboCop programmatically, perhaps from a script. ([@alexdowad][]) ## 0.35.1 (2015-11-10) ### Bug Fixes * [#2407](https://github.com/bbatsov/rubocop/issues/2407): Use `Process.uid` rather than `Etc.getlogin` for simplicity and compatibility. ([@jujugrrr][]) ## 0.35.0 (2015-11-07) ### New features * [#2028](https://github.com/bbatsov/rubocop/issues/2028): New config `ExtraDetails` supports addition of `Details` param to all cops to allow extra details on offense to be displayed. ([@tansaku][]) * [#2036](https://github.com/bbatsov/rubocop/issues/2036): New cop `Style/StabbyLambdaParentheses` will find and correct cases where a stabby lambda's parameters are not wrapped in parentheses. ([@hmadison][]) * [#2246](https://github.com/bbatsov/rubocop/pull/2246): `Style/TrailingUnderscoreVariable` will now register an offense for `*_`. ([@rrosenblum][]) * [#2246](https://github.com/bbatsov/rubocop/pull/2246): `Style/TrailingUnderscoreVariable` now has a configuration to remove named underscore variables (Defaulted to false). ([@rrosenblum][]) * [#2276](https://github.com/bbatsov/rubocop/pull/2276): New cop `Performance/FixedSize` will register an offense when calling `length`, `size`, or `count` on statically sized objected (strings, symbols, arrays, and hashes). ([@rrosenblum][]) * New cop `Style/NestedModifier` checks for nested `if`, `unless`, `while` and `until` modifier statements. ([@lumeet][]) * [#2270](https://github.com/bbatsov/rubocop/pull/2270): Add a new `inherit_gem` configuration to inherit a config file from an installed gem [(originally requested in #290)](https://github.com/bbatsov/rubocop/issues/290). ([@jhansche][]) * Allow `StyleGuide` parameters in local configuration for all cops, so users can add references to custom style guide documents. ([@cornelius][]) * `UnusedMethodArgument` cop allows configuration to skip keyword arguments. ([@apiology][]) * [#2318](https://github.com/bbatsov/rubocop/pull/2318): `Lint/Debugger` cop now checks for `Pry.rescue`. ([@rrosenblum][]) * [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstArrayElementLineBreak` checks for a line break before the first element in a multi-line array. ([@panthomakos][]) * [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstHashElementLineBreak` checks for a line break before the first element in a multi-line hash. ([@panthomakos][]) * [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstMethodArgumentLineBreak` checks for a line break before the first argument in a multi-line method call. ([@panthomakos][]) * [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstMethodParameterLineBreak` checks for a line break before the first parameter in a multi-line method parameter definition. ([@panthomakos][]) * Add `Rails/PluralizationGrammar` cop, checks for incorrect grammar when using methods like `3.day.ago`, when you should write `3.days.ago`. ([@maxjacobson][]) * [#2347](https://github.com/bbatsov/rubocop/pull/2347): `Lint/Eval` cop does not warn about "security risk" when eval argument is a string literal without interpolations. ([@alexdowad][]) * [#2335](https://github.com/bbatsov/rubocop/issues/2335): `Style/VariableName` cop checks naming style of method parameters. ([@alexdowad][]) * [#2329](https://github.com/bbatsov/rubocop/pull/2329): New style `braces_for_chaining` for `Style/BlockDelimiters` cop enforces braces on a multi-line block if its return value is being chained with another method. ([@panthomakos][]) * `Lint/LiteralInCondition` warns if a symbol or dynamic symbol is used as a condition. ([@alexdowad][]) * [#2369](https://github.com/bbatsov/rubocop/issues/2369): `Style/TrailingComma` doesn't add a trailing comma to a multiline method chain which is the only arg to a method call. ([@alexdowad][]) * `CircularArgumentReference` cop updated to lint for ordinal circular argument references on top of optional keyword arguments. ([@maxjacobson][]) * Added ability to download shared rubocop config files from remote urls. ([@ptrippett][]) * [#1601](https://github.com/bbatsov/rubocop/issues/1601): Add `IgnoreEmptyMethods` config parameter for `Lint/UnusedMethodArgument` and `IgnoreEmptyBlocks` config parameter for `Lint/UnusedBlockArgument` cops. ([@alexdowad][]) * [#1729](https://github.com/bbatsov/rubocop/issues/1729): `Style/MethodDefParentheses` supports new 'require_no_parentheses_except_multiline' style. ([@alexdowad][]) * [#2173](https://github.com/bbatsov/rubocop/issues/2173): `Style/AlignParameters` also checks parameter alignment for method definitions. ([@alexdowad][]) * [#1825](https://github.com/bbatsov/rubocop/issues/1825): New `NameWhitelist` configuration parameter for `Style/PredicateName` can be used to suppress errors on known-good predicate names. ([@alexdowad][]) * `Style/Documentation` recognizes 'Constant = Class.new' as a class definition. ([@alexdowad][]) * [#1608](https://github.com/bbatsov/rubocop/issues/1608): Add new 'align_braces' style for `Style/IndentHash`. ([@alexdowad][]) * `Style/Next` can autocorrect. ([@alexdowad][]) ### Bug Fixes * [#2265](https://github.com/bbatsov/rubocop/issues/2265): Handle unary `+` in `ExtraSpacing` cop. ([@jonas054][]) * [#2275](https://github.com/bbatsov/rubocop/pull/2275): Copy default `Exclude` into `Exclude` lists in `.rubocop_todo.yml`. ([@jonas054][]) * `Style/IfUnlessModifier` accepts blocks followed by a chained call. ([@lumeet][]) * [#2261](https://github.com/bbatsov/rubocop/issues/2261): Make relative `Exclude` paths in `$HOME/.rubocop_todo.yml` be relative to current directory. ([@jonas054][]) * [#2286](https://github.com/bbatsov/rubocop/issues/2286): Handle auto-correction of empty method when `AllowIfMethodIsEmpty` is `false` in `Style/SingleLineMethods`. ([@jonas054][]) * [#2246](https://github.com/bbatsov/rubocop/pull/2246): Do not register an offense for `Style/TrailingUnderscoreVariable` when the underscore variable is preceded by a splat variable. ([@rrosenblum][]) * [#2292](https://github.com/bbatsov/rubocop/pull/2292): Results should not be stored in the cache if affected by errors (crashes). ([@jonas054][]) * [#2280](https://github.com/bbatsov/rubocop/issues/2280): Avoid reporting space between hash literal keys and values in `Style/ExtraSpacing`. ([@jonas054][]) * [#2284](https://github.com/bbatsov/rubocop/issues/2284): Fix result cache being shared between ruby versions. ([@miquella][]) * [#2285](https://github.com/bbatsov/rubocop/issues/2285): Fix `ConfigurableNaming#class_emitter_method?` error when handling singleton class methods. ([@palkan][]) * [#2295](https://github.com/bbatsov/rubocop/issues/2295): Fix Performance/Detect autocorrect to handle rogue newlines. ([@palkan][]) * [#2294](https://github.com/bbatsov/rubocop/issues/2294): Do not register an offense in `Performance/StringReplacement` for regex with options. ([@rrosenblum][]) * Fix `Style/UnneededPercentQ` condition for single-quoted literal containing interpolation-like string. ([@eagletmt][]) * [#2324](https://github.com/bbatsov/rubocop/issues/2324): Handle `--only Lint/Syntax` and `--except Lint/Syntax` correctly. ([@jonas054][]) * [#2317](https://github.com/bbatsov/rubocop/issues/2317): Handle `case` as an argument correctly in `Lint/EndAlignment`. ([@lumeet][]) * [#2287](https://github.com/bbatsov/rubocop/issues/2287): Fix auto-correct of lines with only whitespace in `Style/IndentationWidth`. ([@lumeet][]) * [#2331](https://github.com/bbatsov/rubocop/issues/2331): Do not register an offense in `Performance/Size` for `count` with an argument. ([@rrosenblum][]) * Handle a backslash at the end of a line in `Style/SpaceAroundOperators`. ([@lumeet][]) * Don't warn about lack of "leading space" in a =begin/=end comment. ([@alexdowad][]) * [#2307](https://github.com/bbatsov/rubocop/issues/2307): In `Lint/FormatParameterMismatch`, don't register an offense if either argument to % is not a literal. ([@alexdowad][]) * [#2356](https://github.com/bbatsov/rubocop/pull/2356): `Style/Encoding` will now place the encoding comment on the second line if the first line is a shebang. ([@rrosenblum][]) * `Style/InitialIndentation` cop doesn't error out when a line begins with an integer literal. ([@alexdowad][]) * [#2296](https://github.com/bbatsov/rubocop/issues/2296): In `Style/DotPosition`, don't "correct" (and break) a method call which has a line comment (or blank line) between the dot and the selector. ([@alexdowad][]) * [#2272](https://github.com/bbatsov/rubocop/issues/2272): `Lint/NonLocalExitFromIterator` does not warn about `return` in a block which is passed to `Module#define_method`. ([@alexdowad][]) * [#2262](https://github.com/bbatsov/rubocop/issues/2262): Replace `Rainbow` reference with `Colorizable#yellow`. ([@minustehbare][]) * [#2068](https://github.com/bbatsov/rubocop/issues/2068): Display warning if `Style/Copyright` is misconfigured. ([@alexdowad][]) * [#2321](https://github.com/bbatsov/rubocop/issues/2321): In `Style/EachWithObject`, don't replace reduce with each_with_object if the accumulator parameter is assigned to in the block. ([@alexdowad][]) * [#1981](https://github.com/bbatsov/rubocop/issues/1981): `Lint/UselessAssignment` doesn't erroneously identify assignments in identical if branches as useless. ([@alexdowad][]) * [#2323](https://github.com/bbatsov/rubocop/issues/2323): `Style/IfUnlessModifier` cop parenthesizes autocorrected code when necessary due to operator precedence, to avoid changing its meaning. ([@alexdowad][]) * [#2003](https://github.com/bbatsov/rubocop/issues/2003): Make `Lint/UnneededDisable` work with `--auto-correct`. ([@jonas054][]) * Default RuboCop cache dir moved to per-user folders. ([@br3nda][]) * [#2393](https://github.com/bbatsov/rubocop/pull/2393): `Style/MethodCallParentheses` doesn't fail on `obj.method ||= func()`. ([@alexdowad][]) * [#2344](https://github.com/bbatsov/rubocop/pull/2344): When autocorrecting, `Style/ParallelAssignment` reorders assignment statements, if necessary, to avoid breaking code. ([@alexdowad][]) * `Style/MultilineOperationAlignment` does not try to align the receiver and selector of a method call if both are on the LHS of an assignment. ([@alexdowad][]) ### Changes * [#2194](https://github.com/bbatsov/rubocop/issues/2194): Allow any options with `--auto-gen-config`. ([@agrimm][]) ## 0.34.2 (2015-09-21) ### Bug Fixes * [#2232](https://github.com/bbatsov/rubocop/issues/2232): Fix false positive in `Lint/FormatParameterMismatch` for argument with splat operator. ([@dreyks][]) * [#2237](https://github.com/bbatsov/rubocop/pull/2237): Allow `Lint/FormatParameterMismatch` to be called using `Kernel.format` and `Kernel.sprintf`. ([@rrosenblum][]) * [#2234](https://github.com/bbatsov/rubocop/issues/2234): Do not register an offense for `Lint/FormatParameterMismatch` when the format string is a variable. ([@rrosenblum][]) * [#2240](https://github.com/bbatsov/rubocop/pull/2240): `Lint/UnneededDisable` should not report non-`Lint` `rubocop:disable` comments when running `rubocop --lint`. ([@jonas054][]) * [#2121](https://github.com/bbatsov/rubocop/issues/2121): Allow space before values in hash literals in `Style/ExtraSpacing` to avoid correction conflict. ([@jonas054][]) * [#2241](https://github.com/bbatsov/rubocop/issues/2241): Read cache in binary format. ([@jonas054][]) * [#2247](https://github.com/bbatsov/rubocop/issues/2247): Fix auto-correct of `Performance/CaseWhenSplat` for percent arrays (`%w`, `%W`, `%i`, and `%I`). ([@rrosenblum][]) * [#2244](https://github.com/bbatsov/rubocop/issues/2244): Disregard annotation keywords in `Style/CommentAnnotation` if they don't start a comment. ([@jonas054][]) * [#2257](https://github.com/bbatsov/rubocop/pull/2257): Fix bug where `Style/RescueEnsureAlignment` will register an offense for `rescue` and `ensure` on the same line. ([@rrosenblum][]) * [#2255](https://github.com/bbatsov/rubocop/issues/2255): Refine the offense highlighting for `Style/SymbolProc`. ([@bbatsov][]) * [#2260](https://github.com/bbatsov/rubocop/pull/2260): Make `Exclude` in `.rubocop_todo.yml` work when running from a subdirectory. ([@jonas054][]) ### Changes * [#2248](https://github.com/bbatsov/rubocop/issues/2248): Allow block-pass in `Style/AutoResourceCleanup`. ([@lumeet][]) * [#2258](https://github.com/bbatsov/rubocop/pull/2258): `Style/Documentation` will exclude test directories by default. ([@rrosenblum][]) * [#2260](https://github.com/bbatsov/rubocop/issues/2260): Disable `Style/StringMethods` by default. ([@bbatsov][]) ## 0.34.1 (2015-09-09) ### Bug Fixes * [#2212](https://github.com/bbatsov/rubocop/issues/2212): Handle methods without parentheses in auto-correct. ([@karreiro][]) * [#2214](https://github.com/bbatsov/rubocop/pull/2214): Fix `File name too long error` when `STDIN` option is provided. ([@mrfoto][]) * [#2217](https://github.com/bbatsov/rubocop/issues/2217): Allow block arguments in `Style/SymbolProc`. ([@lumeet][]) * [#2213](https://github.com/bbatsov/rubocop/issues/2213): Write to cache with binary encoding to avoid transcoding exceptions in some locales. ([@jonas054][]) * [#2218](https://github.com/bbatsov/rubocop/issues/2218): Fix loading config error when safe yaml is only partially loaded. ([@maxjacobson][]) * [#2161](https://github.com/bbatsov/rubocop/issues/2161): Allow an explicit receiver (except `Kernel`) in `Style/SignalException`. ([@lumeet][]) ## 0.34.0 (2015-09-05) ### New features * [#2143](https://github.com/bbatsov/rubocop/pull/2143): New cop `Performance/CaseWhenSplat` will identify and rearange `case` `when` statements that contain a `when` condition with a splat. ([@rrosenblum][]) * New cop `Lint/DuplicatedKey` checks for duplicated keys in hashes, which Ruby 2.2 warns against. ([@sliuu][]) * [#2106](https://github.com/bbatsov/rubocop/issues/2106): Add `SuspiciousParamNames` option to `Style/OptionHash`. ([@wli][]) * [#2193](https://github.com/bbatsov/rubocop/pull/2193): `Style/Next` supports more `Enumerable` methods. ([@rrosenblum][]) * [#2179](https://github.com/bbatsov/rubocop/issues/2179): Add `--list-target-files` option to CLI, which prints the files which will be inspected. ([@maxjacobson][]) * New cop `Style/MutableConstant` checks for assignment of mutable objects to constants. ([@bbatsov][]) * New cop `Style/RedudantFreeze` checks for usages of `Object#freeze` on immutable objects. ([@bbatsov][]) * [#1924](https://github.com/bbatsov/rubocop/issues/1924): New option `--cache` and configuration parameter `AllCops: UseCache` turn result caching on (default) or off. ([@jonas054][]) * [#2204](https://github.com/bbatsov/rubocop/pull/2204): New cop `Style/StringMethods` will check for preferred method `to_sym` over `intern`. ([@imtayadeway][]) ### Changes * [#1351](https://github.com/bbatsov/rubocop/issues/1351): Allow class emitter methods in `Style/MethodName`. ([@jonas054][]) * [#2126](https://github.com/bbatsov/rubocop/pull/2126): `Style/RescueModifier` can now auto-correct. ([@rrosenblum][]) * [#2109](https://github.com/bbatsov/rubocop/issues/2109): Allow alignment with a token on the nearest line with same indentation in `Style/ExtraSpacing`. ([@jonas054][]) * `Lint/EndAlignment` handles the `case` keyword. ([@lumeet][]) * [#2146](https://github.com/bbatsov/rubocop/pull/2146): Add STDIN support. ([@caseywebdev][]) * [#2175](https://github.com/bbatsov/rubocop/pull/2175): Files that are excluded from a cop (e.g. using the `Exclude:` config option) are no longer being processed by that cop. ([@bquorning][]) * `Rails/ActionFilter` now handles complete list of methods found in the Rails 4.2 [release notes](https://github.com/rails/rails/blob/4115a12da1409c753c747fd4bab6e612c0c6e51a/guides/source/4_2_release_notes.md#notable-changes-1). ([@MGerrior][]) * [*2138](https://github.com/bbatsov/rubocop/issues/2138): Change the offense in `Style/Next` to highlight the condition instead of the iteration. ([@rrosenblum][]) * `Style/EmptyLineBetweenDefs` now handles class methods as well. ([@unmanbearpig][]) * Improve handling of `super` in `Style/SymbolProc`. ([@lumeet][]) * `Style/SymbolProc` is applied to methods receiving arguments. ([@lumeet][]) * [#1839](https://github.com/bbatsov/rubocop/issues/1839): Remove Rainbow monkey patching of String which conflicts with other gems like colorize. ([@daviddavis][]) * `Style/HashSyntax` is now a bit faster when checking Ruby 1.9 syntax hash keys. ([@bquorning][]) * `Lint/DeprecatedClassMethods` is now a whole lot faster. ([@bquorning][]) * `Lint/BlockAlignment`, `Style/IndentationWidth`, and `Style/MultilineOperationIndentation` are now quite a bit faster. ([@bquorning][]) ### Bug Fixes * [#2123](https://github.com/bbatsov/rubocop/pull/2123): Fix handing of dynamic widths `Lint/FormatParameterMismatch`. ([@edmz][]) * [#2116](https://github.com/bbatsov/rubocop/pull/2116): Fix named params (using hash) `Lint/FormatParameterMismatch`. ([@edmz][]) * [#2135](https://github.com/bbatsov/rubocop/issues/2135): Ignore `super` and `zsuper` nodes in `Style/SymbolProc`. ([@bbatsov][]) * [#2165](https://github.com/bbatsov/rubocop/issues/2165): Fix a NPE in `Style/Alias`. ([@bbatsov][]) * [#2168](https://github.com/bbatsov/rubocop/issues/2168): Fix a NPE in `Rails/TimeZone`. ([@bbatsov][]) * [#2169](https://github.com/bbatsov/rubocop/issues/2169): Fix a NPE in `Rails/Date`. ([@bbatsov][]) * [#2105](https://github.com/bbatsov/rubocop/pull/2105): Fix a warning that was thrown when enabling `Style/OptionHash`. ([@wli][]) * [#2107](https://github.com/bbatsov/rubocop/pull/2107): Fix auto-correct of `Style/ParallelAssignment` for nested expressions. ([@rrosenblum][]) * [#2111](https://github.com/bbatsov/rubocop/issues/2111): Deal with byte order mark in `Style/InitialIndentation`. ([@jonas054][]) * [#2113](https://github.com/bbatsov/rubocop/issues/2113): Handle non-string tokens in `Style/ExtraSpacing`. ([@jonas054][]) * [#2129](https://github.com/bbatsov/rubocop/issues/2129): Handle empty interpolations in `Style/SpaceInsideStringInterpolation`. ([@lumeet][]) * [#2119](https://github.com/bbatsov/rubocop/issues/2119): Do not raise an error in `Style/RescueEnsureAlignment` and `Style/RescueModifier` when processing an excluded file. ([@rrosenblum][]) * [#2149](https://github.com/bbatsov/rubocop/issues/2149): Do not register an offense in `Rails/Date` when `Date#to_time` is called with a time zone argument. ([@maxjacobson][]) * Do not register a `Rails/TimeZone` offense when using Time.new safely. ([@maxjacobson][]) * [#2124](https://github.com/bbatsov/rubocop/issues/2124): Fix bug in `Style/EmptyLineBetweenDefs` when there are only comments between method definitions. ([@lumeet][]) * [#2154](https://github.com/bbatsov/rubocop/issues/2154): `Performance/StringReplacement` can auto-correct replacements with backslash in them. ([@rrosenblum][]) * [#2009](https://github.com/bbatsov/rubocop/issues/2009): Fix bug in `RuboCop::ConfigLoader.load_file` when `safe_yaml` is required. ([@eitoball][]) * [#2155](https://github.com/bbatsov/rubocop/issues/2155): Configuration `EndAlignment: AlignWith: variable` only applies when the operands of `=` are on the same line. ([@jonas054][]) * Fix bug in `Style/IndentationWidth` when `rescue` or `ensure` is preceded by an empty body. ([@lumeet][]) * [#2183](https://github.com/bbatsov/rubocop/issues/2183): Fix bug in `Style/BlockDelimiters` when auto-correcting adjacent braces. ([@lumeet][]) * [#2199](https://github.com/bbatsov/rubocop/issues/2199): Make `rubocop` exit with error when there are only `Lint/UnneededDisable` offenses. ([@jonas054][]) * Fix handling of empty parentheses when auto-correcting in `Style/SymbolProc`. ([@lumeet][]) ## 0.33.0 (2015-08-05) ### New features * [#2081](https://github.com/bbatsov/rubocop/pull/2081): New cop `Style/Send` checks for the use of `send` and instead encourages changing it to `BasicObject#__send__` or `Object#public_send` (disabled by default). ([@syndbg][]) * [#2057](https://github.com/bbatsov/rubocop/pull/2057): New cop `Lint/FormatParameterMismatch` checks for a mismatch between the number of fields expected in format/sprintf/% and what was passed to it. ([@edmz][]) * [#2010](https://github.com/bbatsov/rubocop/pull/2010): Add `space` style for SpaceInsideStringInterpolation. ([@gotrevor][]) * [#2007](https://github.com/bbatsov/rubocop/pull/2007): Allow any modifier before `def`, not only visibility modifiers. ([@fphilipe][]) * [#1980](https://github.com/bbatsov/rubocop/pull/1980): `--auto-gen-config` now outputs an excluded files list for failed cops (up to a maxiumum of 15 files). ([@bmorrall][]) * [#2004](https://github.com/bbatsov/rubocop/pull/2004): Introduced `--exclude-limit COUNT` to configure how many files `--auto-gen-config` will exclude. ([@awwaiid][], [@jonas054][]) * [#1918](https://github.com/bbatsov/rubocop/issues/1918): New configuration parameter `AllCops:DisabledByDefault` when set to `true` makes only cops found in user configuration enabled, which makes cop selection *opt-in*. ([@jonas054][]) * New cop `Performance/StringReplacement` checks for usages of `gsub` that can be replaced with `tr` or `delete`. ([@rrosenblum][]) * [#2001](https://github.com/bbatsov/rubocop/issues/2001): New cop `Style/InitialIndentation` checks for indentation of the first non-blank non-comment line in a file. ([@jonas054][]) * [#2060](https://github.com/bbatsov/rubocop/issues/2060): New cop `Style/RescueEnsureAlignment` checks for bad alignment of `rescue` and `ensure` keywords. ([@lumeet][]) * New cop `Style/OptionalArguments` checks for optional arguments that do not appear at the end of an argument list. ([@rrosenblum][]) * New cop `Lint/CircularArgumentReference` checks for "circular argument references" in keyword arguments, which Ruby 2.2 warns against. ([@maxjacobson][], [@sliuu][]) * [#2030](https://github.com/bbatsov/rubocop/issues/2030): New cop `Style/OptionHash` checks for option hashes and encourages changing them to keyword arguments (disabled by default). ([@maxjacobson][]) ### Changes * [#2052](https://github.com/bbatsov/rubocop/pull/2052): `Style/RescueModifier` uses token stream to identify offenses. ([@urbanautomaton][]) * Rename `Rails/Date` and `Rails/TimeZone` style names to "strict" and "flexible" and make "flexible" to be default. ([@palkan][]) * [#2035](https://github.com/bbatsov/rubocop/issues/2035): `Style/ExtraSpacing` is now enabled by default and has a configuration parameter `AllowForAlignment` that is `true` by default, making it allow extra spacing if it's used for alignment purposes. ([@jonas054][]) ### Bugs fixed * [#2014](https://github.com/bbatsov/rubocop/pull/2014): Fix `Style/TrivialAccessors` to support AllowPredicates: false. ([@gotrevor][]) * [#1988](https://github.com/bbatsov/rubocop/issues/1988): Fix bug in `Style/ParallelAssignment` when assigning from `Module::CONSTANT`. ([@rrosenblum][]) * [#1995](https://github.com/bbatsov/rubocop/pull/1995): Improve message for `Rails/TimeZone`. ([@palkan][]) * [#1977](https://github.com/bbatsov/rubocop/issues/1977): Fix bugs in `Rails/Date` and `Rails/TimeZone` when using namespaced Time/Date. ([@palkan][]) * [#1973](https://github.com/bbatsov/rubocop/issues/1973): Do not register an offense in `Performance/Detect` when `select` is called on `Enumerable::Lazy`. ([@palkan][]) * [#2015](https://github.com/bbatsov/rubocop/issues/2015): Fix bug occurring for auto-correction of a misaligned `end` in a file with only one method. ([@jonas054][]) * Allow string interpolation segments inside single quoted string literals when double quotes are preferred. ([@segiddins][]) * [#2026](https://github.com/bbatsov/rubocop/issues/2026): Allow `Time.current` when style is "acceptable".([@palkan][]) * [#2029](https://github.com/bbatsov/rubocop/issues/2029): Fix bug where `Style/RedundantReturn` auto-corrects returning implicit hashes to invalid syntax. ([@rrosenblum][]) * [#2021](https://github.com/bbatsov/rubocop/issues/2021): Fix bug in `Style/BlockDelimiters` when a `semantic` expression is used in an array or a range. ([@lumeet][]) * [#1992](https://github.com/bbatsov/rubocop/issues/1992): Allow parentheses in assignment to a variable with the same name as the method's in `Style/MethodCallParentheses`. ([@lumeet][]) * [#2045](https://github.com/bbatsov/rubocop/issues/2045): Fix crash in `Style/IndentationWidth` when using `private_class_method def self.foo` syntax. ([@unmanbearpig][]) * [#2006](https://github.com/bbatsov/rubocop/issues/2006): Fix crash in `Style/FirstParameterIndentation` in case of nested offenses. ([@unmanbearpig][]) * [#2059](https://github.com/bbatsov/rubocop/issues/2059): Don't check for trivial accessors in modules. ([@bbatsov][]) * Add proper punctuation to the end of offense messages, where it is missing. ([@lumeet][]) * [#2071](https://github.com/bbatsov/rubocop/pull/2071): Keep line breaks in place on WordArray autocorrect.([@unmanbearpig][]) * [#2075](https://github.com/bbatsov/rubocop/pull/2075): Properly correct `Style/PercentLiteralDelimiters` with escape characters in them. ([@rrosenblum][]) * [#2023](https://github.com/bbatsov/rubocop/issues/2023): Avoid auto-correction corruption in `IndentationWidth`. ([@jonas054][]) * [#2080](https://github.com/bbatsov/rubocop/issues/2080): Properly parse code in `Performance/Count` when calling `select..count` in a class that extends an enumerable. ([@rrosenblum][]) * [#2093](https://github.com/bbatsov/rubocop/issues/2093): Fix bug in `Style/OneLineConditional` which should not raise an offense with an 'if/then/end' statement. ([@sliuu][]) ## 0.32.1 (2015-06-24) ### New features * `Debugger` cop now checks catches methods called with arguments. ([@crazydog115][]) ### Bugs fixed * Make it possible to disable `Lint/UnneededDisable`. ([@jonas054][]) * [#1958](https://github.com/bbatsov/rubocop/issues/1958): Show name of `Lint/UnneededDisable` when `-D/--display-cop-names` is given. ([@jonas054][]) * Do not show `Style/NonNilCheck` offenses as corrected when the source code is not modified. ([@rrosenblum][]) * Fix auto-correct in `Style/RedundantReturn` when `return` has no arguments. ([@lumeet][]) * [#1955](https://github.com/bbatsov/rubocop/issues/1955): Fix false positive for `Style/TrailingComma` cop. ([@mattjmcnaughton][]) * [#1928](https://github.com/bbatsov/rubocop/issues/1928): Avoid auto-correcting two alignment offenses in the same area at the same time. ([@jonas054][]) * [#1964](https://github.com/bbatsov/rubocop/issues/1964): Fix `RedundantBegin` auto-correct issue with comments by doing a smaller correction. ([@jonas054][]) * [#1978](https://github.com/bbatsov/rubocop/pull/1978): Don't count disabled offences if fail-level is autocorrect. ([@sch1zo][]) * [#1986](https://github.com/bbatsov/rubocop/pull/1986): Fix Date false positives on variables. ([@palkan][]) ### Changes * [#1708](https://github.com/bbatsov/rubocop/issues/1708): Improve message for `FirstParameterIndentation`. ([@tejasbubane][]) * [#1959](https://github.com/bbatsov/rubocop/issues/1959): Allow `Lint/UnneededDisable` to be inline disabled. ([@rrosenblum][]) ## 0.32.0 (2015-06-06) ### New features * Adjust behavior of `TrailingComma` cop to account for multi-line hashes nested within method calls. ([@panthomakos][]) * [#1719](https://github.com/bbatsov/rubocop/pull/1719): Display an error and abort the program if input file can't be found. ([@matugm][]) * New cop `SpaceInsideStringInterpolation` checks for spaces within string interpolations. ([@glasnt][]) * New cop `NestedMethodDefinition` checks for method definitions inside other methods. ([@ojab][]) * `LiteralInInterpolation` cop does auto-correction. ([@tmr08c][]) * [#1865](https://github.com/bbatsov/rubocop/issues/1865): New cop `Lint/UnneededDisable` checks for `rubocop:disable` comments that can be removed. ([@jonas054][]) * `EmptyElse` cop does auto-correction. ([@lumeet][]) * Show reference links when displaying style guide links. ([@rrosenblum][]) * `Debugger` cop now checks for the Capybara debug method `save_screenshot`. ([@crazydog115][]) * [#1282](https://github.com/bbatsov/rubocop/issues/1282): `CaseIndentation` cop does auto-correction. ([@lumeet][]) * [#1928](https://github.com/bbatsov/rubocop/issues/1928): Do auto-correction one offense at a time (rather than one cop at a time) if there are tabs in the code. ([@jonas054][]) ### Changes * Prefer `SpaceInsideBlockBraces` to `SpaceBeforeSemicolon` and `SpaceAfterSemicolon` to avoid an infinite loop when auto-correcting. ([@lumeet][]) * [#1873](https://github.com/bbatsov/rubocop/issues/1873): Move `ParallelAssignment` cop from Performance to Style. ([@rrosenblum][]) * Add `getlocal` to acceptable methods of `Rails/TimeZone`. ([@ojab][]) * [#1851](https://github.com/bbatsov/rubocop/issues/1851), [#1948](https://github.com/bbatsov/rubocop/issues/1948): Change offense message for `ClassLength` and `ModuleLength` to match that of `MethodLength`. ([@bquorning][]) ### Bugs fixed * Don't count required keyword args when specifying `CountKeywordArgs: false` for `ParameterLists`. ([@sumeet][]) * [#1879](https://github.com/bbatsov/rubocop/issues/1879): Avoid auto-correcting hash with trailing comma into invalid code in `BracesAroundHashParameters`. ([@jonas054][]) * [#1868](https://github.com/bbatsov/rubocop/issues/1868): Do not register an offense in `Performance/Count` when `select` is called with symbols or strings as the parameters. ([@rrosenblum][]) * `Sample` rewritten to properly handle shuffle randomness source, first/last params and non-literal ranges. ([@chastell][]) * [#1873](https://github.com/bbatsov/rubocop/issues/1873): Modify `ParallelAssignment` to properly autocorrect when the assignment is protected by a modifier statement. ([@rrosenblum][]) * Configure `ParallelAssignment` to work with non-standard `IndentationWidths`. ([@rrosenblum][]) * [#1899](https://github.com/bbatsov/rubocop/issues/1899): Be careful about comments when auto-correcting in `BracesAroundHashParameters`. ([@jonas054][]) * [#1897](https://github.com/bbatsov/rubocop/issues/1897): Don't report that semicolon separated statements can be converted to modifier form in `IfUnlessModifier` (and don't auto-correct them). ([@jonas054][]) * [#1644](https://github.com/bbatsov/rubocop/issues/1644): Don't search the entire file system when a folder is named `,` (fix for jruby and rbx). ([@rrosenblum][]) * [#1803](https://github.com/bbatsov/rubocop/issues/1803): Don't warn for `return` from `lambda` block in `NonLocalExitFromIterator`. ([@ypresto][]) * [#1905](https://github.com/bbatsov/rubocop/issues/1905): Ignore sparse and trailing comments in `Style/Documentation`. ([@RGBD][]) * [#1923](https://github.com/bbatsov/rubocop/issues/1923): Handle properly `for` without body in `Style/Next`. ([@bbatsov][]) * [#1901](https://github.com/bbatsov/rubocop/issues/1901): Do not auto correct comments that are missing a note. ([@rrosenblum][]) * [#1926](https://github.com/bbatsov/rubocop/issues/1926): Fix crash in `Style/AlignHash` when correcting a hash with a splat in it. ([@rrosenblum][]) * [#1935](https://github.com/bbatsov/rubocop/issues/1935): Allow `Symbol#to_proc` blocks in Performance/Size. ([@m1foley][]) ## 0.31.0 (2015-05-05) ### New features * `Rails/TimeZone` emits acceptable methods on a violation when `EnforcedStyle` is `:acceptable`. ([@l8nite][]) * Recognize rackup file (config.ru) out of the box. ([@carhartl][]) * [#1788](https://github.com/bbatsov/rubocop/pull/1788): New cop `ModuleLength` checks for overly long module definitions. ([@sdeframond][]) * New cop `Performance/Count` to convert `Enumerable#select...size`, `Enumerable#reject...size`, `Enumerable#select...count`, `Enumerable#reject...count` `Enumerable#select...length`, and `Enumerable#reject...length` to `Enumerable#count`. ([@rrosenblum][]) * `CommentAnnotation` cop does auto-correction. ([@dylandavidson][]) * New cop `Style/TrailingUnderscoreVariable` to remove trailing underscore variables from mass assignment. ([@rrosenblum][]) * [#1136](https://github.com/bbatsov/rubocop/issues/1136): New cop `Performance/ParallelAssignment` to avoid usages of unnessary parallel assignment. ([@rrosenblum][]) * [#1278](https://github.com/bbatsov/rubocop/issues/1278): `DefEndAlignment` and `EndAlignment` cops do auto-correction. ([@lumeet][]) * `IndentationWidth` cop follows the `AlignWith` option of the `DefEndAlignment` cop. ([@lumeet][]) * [#1837](https://github.com/bbatsov/rubocop/issues/1837): New cop `EachWithObjectArgument` checks that `each_with_object` isn't called with an immutable object as argument. ([@jonas054][]) * `ArrayJoin` cop does auto-correction. ([@tmr08c][]) ### Bugs fixed * [#1816](https://github.com/bbatsov/rubocop/issues/1816): Fix bug in `Sample` when calling `#shuffle` with something other than an element selector. ([@rrosenblum][]) * [#1768](https://github.com/bbatsov/rubocop/pull/1768): `DefEndAlignment` recognizes preceding `private_class_method` or `public_class_method` before `def`. ([@til][]) * [#1820](https://github.com/bbatsov/rubocop/issues/1820): Correct the logic in `AlignHash` for when to ignore a key because it's not on its own line. ([@jonas054][]) * [#1829](https://github.com/bbatsov/rubocop/pull/1829): Fix bug in `Sample` and `FlatMap` that would cause them to report having been auto-corrected when they were not. ([@rrosenblum][]) * [#1832](https://github.com/bbatsov/rubocop/pull/1832): Fix bug in `UnusedMethodArgument` that would cause them to report having been auto-corrected when they were not. ([@jonas054][]) * [#1834](https://github.com/bbatsov/rubocop/issues/1834): Support only boolean values for `AutoCorrect` configuration parameter, and remove warning for unknown parameter. ([@jonas054][]) * [#1843](https://github.com/bbatsov/rubocop/issues/1843): Fix crash in `TrailingBlankLines` when a file ends with a block comment without final newline. ([@jonas054][]) * [#1849](https://github.com/bbatsov/rubocop/issues/1849): Fix bug where you can not have nested arrays in the Rake task configuration. ([@rrosenblum][]) * Fix bug in `MultilineTernaryOperator` where it will not register an offense when only the false branch is on a separate line. ([@rrosenblum][]) * Fix crash in `MultilineBlockLayout` when using new lambda literal syntax without parentheses. ([@hbd225][]) * [#1859](https://github.com/bbatsov/rubocop/pull/1859): Fix bugs in `IfUnlessModifier` concerning comments and empty lines. ([@jonas054][]) * Fix handling of trailing comma in `SpaceAroundBlockParameters` and `SpaceAfterComma`. ([@lumeet][]) ## 0.30.1 (2015-04-21) ### Bugs fixed * [#1691](https://github.com/bbatsov/rubocop/issues/1691): For assignments with line break after `=`, use `keyword` alignment in `EndAlignment` regardless of configured style. ([@jonas054][]) * [#1769](https://github.com/bbatsov/rubocop/issues/1769): Fix bug where `LiteralInInterpolation` registers an offense for interpolation of `__LINE__`. ([@rrosenblum][]) * [#1773](https://github.com/bbatsov/rubocop/pull/1773): Fix typo ('strptime' -> 'strftime') in `Rails/TimeZone`. ([@palkan][]) * [#1777](https://github.com/bbatsov/rubocop/pull/1777): Fix offense message from Rails/TimeZone. ([@mzp][]) * [#1784](https://github.com/bbatsov/rubocop/pull/1784): Add an explicit error message when config contains an empty section. ([@bankair][]) * [#1791](https://github.com/bbatsov/rubocop/pull/1791): Fix autocorrection of `PercentLiteralDelimiters` with no content. ([@cshaffer][]) * Fix handling of `while` and `until` with assignment in `IndentationWidth`. ([@lumeet][]) * [#1793](https://github.com/bbatsov/rubocop/pull/1793): Fix bug in `TrailingComma` that caused `,` in comment to count as a trailing comma. ([@jonas054][]) * [#1765](https://github.com/bbatsov/rubocop/pull/1765): Update 1.9 hash to stop triggering when the symbol is not valid in the 1.9 hash syntax. ([@crimsonknave][]) * [#1806](https://github.com/bbatsov/rubocop/issues/1806): Require a newer version of `parser` and use its corrected solution for comment association in `Style/Documentation`. ([@jonas054][]) * [#1792](https://github.com/bbatsov/rubocop/issues/1792): Fix bugs in `Sample` that did not account for array selectors with a range and passing random to shuffle. ([@rrosenblum][]) * [#1770](https://github.com/bbatsov/rubocop/pull/1770): Add more acceptable methods to `Rails/TimeZone` (`utc`, `localtime`, `to_i`, `iso8601` etc). ([@palkan][]) * [#1767](https://github.com/bbatsov/rubocop/pull/1767): Do not register offenses on non-enumerable select/find_all by `Performance/Detect`. ([@palkan][]) * [#1795](https://github.com/bbatsov/rubocop/pull/1795): Fix bug in `TrailingBlankLines` that caused a crash for files containing only newlines. ([@renuo][]) ## 0.30.0 (2015-04-06) ### New features * [#1600](https://github.com/bbatsov/rubocop/issues/1600): Add `line_count_based` and `semantic` styles to the `BlockDelimiters` (formerly `Blocks`) cop. ([@clowder][], [@mudge][]) * [#1712](https://github.com/bbatsov/rubocop/pull/1712): Set `Offense#corrected?` to `true`, `false`, or `nil` when it was, wasn't, or can't be auto-corrected, respectively. ([@vassilevsky][]) * [#1669](https://github.com/bbatsov/rubocop/pull/1669): Add command-line switch `--display-style-guide`. ([@marxarelli][]) * [#1405](https://github.com/bbatsov/rubocop/issues/1405): Add Rails TimeZone and Date cops. ([@palkan][]) * [#1641](https://github.com/bbatsov/rubocop/pull/1641): Add ruby19_no_mixed_keys style to `HashStyle` cop. ([@iainbeeston][]) * [#1604](https://github.com/bbatsov/rubocop/issues/1604): Add `IgnoreClassMethods` option to `TrivialAccessors` cop. ([@bbatsov][]) * [#1651](https://github.com/bbatsov/rubocop/issues/1651): The `Style/SpaceAroundOperators` cop now also detects extra spaces around operators. A list of operators that *may* be surrounded by multiple spaces is configurable. ([@bquorning][]) * Add auto-correct to `Encoding` cop. ([@rrosenblum][]) * [#1621](https://github.com/bbatsov/rubocop/issues/1621): `TrailingComma` has a new style `consistent_comma`. ([@tamird][]) * [#1611](https://github.com/bbatsov/rubocop/issues/1611): Add `empty`, `nil`, and `both` `SupportedStyles` to `EmptyElse` cop. Default is `both`. ([@rrosenblum][]) * [#1611](https://github.com/bbatsov/rubocop/issues/1611): Add new `MissingElse` cop. Default is to have this cop be disabled. ([@rrosenblum][]) * [#1602](https://github.com/bbatsov/rubocop/issues/1602): Add support for `# :nodoc` in `Documentation`. ([@lumeet][]) * [#1437](https://github.com/bbatsov/rubocop/issues/1437): Modify `HashSyntax` cop to allow the use of hash rockets for hashes that have symbol values when using ruby19 syntax. ([@rrosenblum][]) * New cop `Style/SymbolLiteral` makes sure you're not using the string within symbol syntax unless it's needed. ([@bbatsov][]) * [#1657](https://github.com/bbatsov/rubocop/issues/1657): Autocorrect can be turned off on a specific cop via the configuration. ([@jdoconnor][]) * New cop `Style/AutoResourceCleanup` suggests the use of block taking versions of methods that do resource cleanup. ([@bbatsov][]) * [#1275](https://github.com/bbatsov/rubocop/issues/1275): `WhileUntilModifier` cop does auto-correction. ([@lumeet][]) * New cop `Performance/ReverseEach` to convert `reverse.each` to `reverse_each`. ([@rrosenblum][]) * [#1281](https://github.com/bbatsov/rubocop/issues/1281): `IfUnlessModifier` cop does auto-correction. ([@lumeet][]) * New cop `Performance/Detect` to detect usage of `select.first`, `select.last`, `find_all.first`, and `find_all.last` and convert them to use `detect` instead. ([@palkan][], [@rrosenblum][]) * [#1728](https://github.com/bbatsov/rubocop/pull/1728): New cop `NonLocalExitFromIterator` checks for misused `return` in block. ([@ypresto][]) * New cop `Performance/Size` to convert calls to `count` on `Array` and `Hash` to `size`. ([@rrosenblum][]) * New cop `Performance/Sample` to convert usages of `shuffle.first`, `shuffle.last`, and `shuffle[Fixnum]` to `sample`. ([@rrosenblum][]) * New cop `Performance/FlatMap` to convert `Enumerable#map...Array#flatten` and `Enumerable#collect...Array#flatten` to `Enumerable#flat_map`. ([@rrosenblum][]) * [#1144](https://github.com/bbatsov/rubocop/issues/1144): New cop `ClosingParenthesisIndentation` checks the indentation of hanging closing parentheses. ([@jonas054][]) * New Rails cop `FindBy` identifies usages of `where.first` and `where.take`. ([@bbatsov][]) * New Rails cop `FindEach` identifies usages of `all.each`. ([@bbatsov][]) * [#1342](https://github.com/bbatsov/rubocop/issues/1342): `IndentationConsistency` is now configurable with the styles `normal` and `rails`. ([@jonas054][]) ### Bugs fixed * [#1705](https://github.com/bbatsov/rubocop/issues/1705): Fix crash when reporting offenses of `MissingElse` cop. ([@gerry3][]) * [#1659](https://github.com/bbatsov/rubocop/pull/1659): Fix stack overflow with JRuby and Windows 8, during initial config validation. ([@pimterry][]) * [#1694](https://github.com/bbatsov/rubocop/issues/1694): Ignore methods with a `blockarg` in `TrivialAccessors`. ([@bbatsov][]) * [#1617](https://github.com/bbatsov/rubocop/issues/1617): Always read the html output template using utf-8. ([@bbatsov][]) * [#1684](https://github.com/bbatsov/rubocop/issues/1684): Ignore symbol keys like `:"string"` in `HashSyntax`. ([@bbatsov][]) * Handle explicit `begin` blocks in `Lint/Void`. ([@bbatsov][]) * Handle symbols in `Lint/Void`. ([@bbatsov][]) * [#1695](https://github.com/bbatsov/rubocop/pull/1695): Fix bug with `--auto-gen-config` and `SpaceInsideBlockBraces`. ([@meganemura][]) * Correct issues with whitespace around multi-line lambda arguments. ([@zvkemp][]) * [#1579](https://github.com/bbatsov/rubocop/issues/1579): Fix handling of similar-looking blocks in `BlockAlignment`. ([@lumeet][]) * [#1676](https://github.com/bbatsov/rubocop/pull/1676): Fix auto-correct in `Lambda` when a new multi-line lambda is used as an argument. ([@lumeet][]) * [#1656](https://github.com/bbatsov/rubocop/issues/1656): Fix bug that would include hidden directories implicitly. ([@jonas054][]) * [#1728](https://github.com/bbatsov/rubocop/pull/1728): Fix bug in `LiteralInInterpolation` and `AssignmentInCondition`. ([@ypresto][]) * [#1735](https://github.com/bbatsov/rubocop/issues/1735): Handle trailing space in `LineEndConcatenation` autocorrect. ([@jonas054][]) * [#1750](https://github.com/bbatsov/rubocop/issues/1750): Escape offending code lines output by the HTML formatter in case they contain markup. ([@jonas054][]) * [#1541](https://github.com/bbatsov/rubocop/issues/1541): No inspection of text that follows `__END__`. ([@jonas054][]) * Fix comment detection in `Style/Documentation`. ([@lumeet][]) * [#1637](https://github.com/bbatsov/rubocop/issues/1637): Fix handling of `binding` calls in `UnusedBlockArgument` and `UnusedMethodArgument`. ([@lumeet][]) ### Changes * [#1397](https://github.com/bbatsov/rubocop/issues/1397): `UnneededPercentX` renamed to `CommandLiteral`. The cop can be configured to enforce using either `%x` or backticks around command literals, or using `%x` around multi-line commands and backticks around single-line commands. The cop ignores heredoc commands. ([@bquorning][]) * [#1020](https://github.com/bbatsov/rubocop/issues/1020): Removed the `MaxSlashes` configuration option for `RegexpLiteral`. Instead, the cop can be configured to enforce using either `%r` or slashes around regular expressions, or using `%r` around multi-line regexes and slashes around single-line regexes. ([@bquorning][]) * [#1734](https://github.com/bbatsov/rubocop/issues/1734): The default exclusion of hidden directories has been optimized for speed. ([@jonas054][]) * [#1673](https://github.com/bbatsov/rubocop/issues/1673): `Style/TrivialAccessors` now requires matching names by default. ([@bbatsov][]) ## 0.29.1 (2015-02-13) ### Bugs fixed * [#1638](https://github.com/bbatsov/rubocop/issues/1638): Use Parser functionality rather than regular expressions for matching comments in `FirstParameterIndentation`. ([@jonas054][]) * [#1642](https://github.com/bbatsov/rubocop/issues/1642): Raise the correct exception if the configuration file is malformed. ([@bquorning][]) * [#1647](https://github.com/bbatsov/rubocop/issues/1647): Skip `SpaceAroundBlockParameters` when lambda has no argument. ([@eitoball][]) * [#1649](https://github.com/bbatsov/rubocop/issues/1649): Handle exception assignments in `UselessSetterCall`. ([@bbatsov][]) * [#1644](https://github.com/bbatsov/rubocop/issues/1644): Don't search the entire file system when a folder is named `,`. ([@bquorning][]) ## 0.29.0 (2015-02-05) ### New features * [#1430](https://github.com/bbatsov/rubocop/issues/1430): Add `--except` option for disabling cops on the command line. ([@jonas054][]) * [#1506](https://github.com/bbatsov/rubocop/pull/1506): Add auto-correct from `EvenOdd` cop. ([@blainesch][]) * [#1507](https://github.com/bbatsov/rubocop/issues/1507): `Debugger` cop now checks for the Capybara debug methods `save_and_open_page` and `save_and_open_screenshot`. ([@rrosenblum][]) * [#1539](https://github.com/bbatsov/rubocop/pull/1539): Implement autocorrection for Rails/ReadWriteAttribute cop. ([@huerlisi][]) * [#1324](https://github.com/bbatsov/rubocop/issues/1324): Add `AllCops/DisplayCopNames` configuration option for showing cop names in reports, like `--display-cop-names`. ([@jonas054][]) * [#1271](https://github.com/bbatsov/rubocop/issues/1271): `Lambda` cop does auto-correction. ([@lumeet][]) * [#1284](https://github.com/bbatsov/rubocop/issues/1284): Support namespaces, e.g. `Lint`, in the arguments to `--only` and `--except`. ([@jonas054][]) * [#1276](https://github.com/bbatsov/rubocop/issues/1276): `SelfAssignment` cop does auto-correction. ([@lumeet][]) * Add autocorrect to `RedundantException`. ([@mattjmcnaughton][]) * [#1571](https://github.com/bbatsov/rubocop/pull/1571): New cop `StructInheritance` checks for inheritance from Struct.new. ([@mmozuras][]) * [#1575](https://github.com/bbatsov/rubocop/issues/1575): New cop `DuplicateMethods` points out duplicate method name in class and module. ([@d4rk5eed][]) * [#1144](https://github.com/bbatsov/rubocop/issues/1144): New cop `FirstParameterIndentation` checks the indentation of the first parameter in a method call. ([@jonas054][]) * [#1627](https://github.com/bbatsov/rubocop/issues/1627): New cop `SpaceAroundBlockParameters` checks the spacing inside and after block parameters pipes. ([@jonas054][]) ### Changes * [#1492](https://github.com/bbatsov/rubocop/pull/1492): Abort when auto-correct causes an infinite loop. ([@dblock][]) * Options `-e`/`--emacs` and `-s`/`--silent` are no longer recognized. Using them will now raise an error. ([@bquorning][]) * [#1565](https://github.com/bbatsov/rubocop/issues/1565): Let `--fail-level A` cause exit with error if all offenses are auto-corrected. ([@jonas054][]) * [#1309](https://github.com/bbatsov/rubocop/issues/1309): Add argument handling to `MultilineBlockLayout`. ([@lumeet][]) ### Bugs fixed * [#1634](https://github.com/bbatsov/rubocop/pull/1634): Fix `PerlBackrefs` Cop Autocorrections to Not Raise. ([@cshaffer][]) * [#1553](https://github.com/bbatsov/rubocop/pull/1553): Fix bug where `Style/EmptyLinesAroundAccessModifier` interfered with `Style/EmptyLinesAroundBlockBody` when there is and access modifier at the beginning of a block. ([@volkert][]) * Handle element assignment in `Lint/AssignmentInCondition`. ([@jonas054][]) * [#1484](https://github.com/bbatsov/rubocop/issues/1484): Fix `EmptyLinesAroundAccessModifier` incorrectly finding a violation inside method calls with names identical to an access modifier. ([@dblock][]) * Fix bug concerning `Exclude` properties inherited from a higher directory level. ([@jonas054][]) * [#1500](https://github.com/bbatsov/rubocop/issues/1500): Fix crashing `--auto-correct --only IndentationWidth`. ([@jonas054][]) * [#1512](https://github.com/bbatsov/rubocop/issues/1512): Fix false negative for typical string formatting examples. ([@kakutani][], [@jonas054][]) * [#1504](https://github.com/bbatsov/rubocop/issues/1504): Fail with a meaningful error if the configuration file is malformed. ([@bquorning][]) * Fix bug where `auto_correct` Rake tasks does not take in the options specified in its parent task. ([@rrosenblum][]) * [#1054](https://github.com/bbatsov/rubocop/issues/1054): Handle comments within concatenated strings in `LineEndConcatenation`. ([@yujinakayama][], [@jonas054][]) * [#1527](https://github.com/bbatsov/rubocop/issues/1527): Make autocorrect `BracesAroundHashParameter` leave the correct number of spaces. ([@mattjmcnaughton][]) * [#1547](https://github.com/bbatsov/rubocop/issues/1547): Don't print `[Corrected]` when auto-correction was avoided in `Style/Semicolon`. ([@jonas054][]) * [#1573](https://github.com/bbatsov/rubocop/issues/1573): Fix assignment-related auto-correction for `BlockAlignment`. ([@lumeet][]) * [#1587](https://github.com/bbatsov/rubocop/pull/1587): Exit with exit code 1 if there were errors ("crashing" cops). ([@jonas054][]) * [#1574](https://github.com/bbatsov/rubocop/issues/1574): Avoid auto-correcting `Hash.new` to `{}` when braces would be interpreted as a block. ([@jonas054][]) * [#1591](https://github.com/bbatsov/rubocop/issues/1591): Don't check parameters inside `[]` in `MultilineOperationIndentation`. ([@jonas054][]) * [#1509](https://github.com/bbatsov/rubocop/issues/1509): Ignore class methods in `Rails/Delegate`. ([@bbatsov][]) * [#1594](https://github.com/bbatsov/rubocop/issues/1594): Fix `@example` warnings in Yard Doc documentation generation. ([@mattjmcnaughton][]) * [#1598](https://github.com/bbatsov/rubocop/issues/1598): Fix bug in file inclusion when running from another directory. ([@jonas054][]) * [#1580](https://github.com/bbatsov/rubocop/issues/1580): Don't print `[Corrected]` when auto-correction was avoided in `TrivialAccessors`. ([@lumeet][]) * [#1612](https://github.com/bbatsov/rubocop/issues/1612): Allow `expand_path` on `inherit_from` in `.rubocop.yml`. ([@mattjmcnaughton][]) * [#1610](https://github.com/bbatsov/rubocop/issues/1610): Check that class method names actually match the name of the containing class/module in `Style/ClassMethods`. ([@bbatsov][]) ## 0.28.0 (2014-12-10) ### New features * [#1450](https://github.com/bbatsov/rubocop/issues/1450): New cop `ExtraSpacing` points out unnecessary spacing in files. ([@blainesch][]) * New cop `EmptyLinesAroundBlockBody` provides same functionality as the EmptyLinesAround(Class|Method|Module)Body but for blocks. ([@jcarbo][]) * New cop `Style/EmptyElse` checks for empty `else`-clauses. ([@Koronen][]) * [#1454](https://github.com/bbatsov/rubocop/issues/1454): New `--only-guide-cops` and `AllCops/StyleGuideCopsOnly` options that will only enforce cops that link to a style guide. ([@marxarelli][]) ### Changes * [#801](https://github.com/bbatsov/rubocop/issues/801): New style `context_dependent` for `Style/BracesAroundHashParameters` looks at preceding parameter to determine if braces should be used for final parameter. ([@jonas054][]) * [#1427](https://github.com/bbatsov/rubocop/issues/1427): Excluding directories on the top level is now done earlier, so that these file trees are not searched, thus saving time when inspecting projects with many excluded files. ([@jonas054][]) * [#1325](https://github.com/bbatsov/rubocop/issues/1325): When running with `--auto-correct`, only offenses *that can not be corrected* will result in a non-zero exit code. ([@jonas054][]) * [#1445](https://github.com/bbatsov/rubocop/issues/1445): Allow sprockets directive comments (starting with `#=`) in `Style/LeadingCommentSpace`. ([@bbatsov][]) ### Bugs fixed * Fix `%W[]` auto corrected to `%w(]`. ([@toy][]) * Fix Style/ElseAlignment Cop to find the right parent on def/rescue/else/ensure/end. ([@oneamtu][]) * [#1181](https://github.com/bbatsov/rubocop/issues/1181): *(fix again)* `Style/StringLiterals` cop stays away from strings inside interpolated expressions. ([@jonas054][]) * [#1441](https://github.com/bbatsov/rubocop/issues/1441): Correct the logic used by `Style/Blocks` and other cops to determine if an auto-correction would alter the meaning of the code. ([@jonas054][]) * [#1449](https://github.com/bbatsov/rubocop/issues/1449): Handle the case in `MultilineOperationIndentation` where instances of both correct style and unrecognized (plain wrong) style are detected during an `--auto-gen-config` run. ([@jonas054][]) * [#1456](https://github.com/bbatsov/rubocop/pull/1456): Fix autocorrect in `SymbolProc` when there are multiple offenses on the same line. ([@jcarbo][]) * [#1459](https://github.com/bbatsov/rubocop/issues/1459): Handle parenthesis around the condition in `--auto-correct` for `NegatedWhile`. ([@jonas054][]) * [#1465](https://github.com/bbatsov/rubocop/issues/1465): Fix autocorrect of code like `#$1` in `PerlBackrefs`. ([@bbatsov][]) * Fix autocorrect of code like `#$:` in `SpecialGlobalVars`. ([@bbatsov][]) * [#1466](https://github.com/bbatsov/rubocop/issues/1466): Allow leading underscore for unused parameters in `SingleLineBlockParams`. ([@jonas054][]) * [#1470](https://github.com/bbatsov/rubocop/issues/1470): Handle `elsif` + `else` in `ElseAlignment`. ([@jonas054][]) * [#1474](https://github.com/bbatsov/rubocop/issues/1474): Multiline string with both `<<` and `\` caught by `Style/LineEndConcatenation` cop. ([@katieschilling][]) * [#1485](https://github.com/bbatsov/rubocop/issues/1485): Ignore procs in `SymbolProc`. ([@bbatsov][]) * [#1473](https://github.com/bbatsov/rubocop/issues/1473): `Style/MultilineOperationIndentation` doesn't recognize assignment to array/hash element. ([@jonas054][]) ## 0.27.1 (2014-11-08) ### Changes * [#1343](https://github.com/bbatsov/rubocop/issues/1343): Remove auto-correct from `RescueException` cop. ([@bbatsov][]) * [#1425](https://github.com/bbatsov/rubocop/issues/1425): `AllCops/Include` configuration parameters are only taken from the project `.rubocop.yml` and files it inherits from, not from `.rubocop.yml` files in subdirectories. ([@jonas054][]) ### Bugs fixed * [#1411](https://github.com/bbatsov/rubocop/issues/1411): Handle lambda calls without a selector in `MultilineOperationIndentation`. ([@bbatsov][]) * [#1401](https://github.com/bbatsov/rubocop/issues/1401): Files in hidden directories, i.e. ones beginning with dot, can now be selected through configuration, but are still not included by default. ([@jonas054][]) * [#1415](https://github.com/bbatsov/rubocop/issues/1415): String literals concatenated with backslashes are now handled correctly by `StringLiteralsInInterpolation`. ([@jonas054][]) * [#1416](https://github.com/bbatsov/rubocop/issues/1416): Fix handling of `begin/rescue/else/end` in `ElseAlignment`. ([@jonas054][]) * [#1413](https://github.com/bbatsov/rubocop/issues/1413): Support empty elsif branches in `MultilineIfThen`. ([@janraasch][], [@jonas054][]) * [#1406](https://github.com/bbatsov/rubocop/issues/1406): Allow a newline in `SpaceInsideRangeLiteral`. ([@bbatsov][]) ## 0.27.0 (2014-10-30) ### New features * [#1348](https://github.com/bbatsov/rubocop/issues/1348): New cop `ElseAlignment` checks alignment of `else` and `elsif` keywords. ([@jonas054][]) * [#1321](https://github.com/bbatsov/rubocop/issues/1321): New cop `MultilineOperationIndentation` checks indentation/alignment of binary operations if they span more than one line. ([@jonas054][]) * [#1077](https://github.com/bbatsov/rubocop/issues/1077): New cop `Metrics/AbcSize` checks the ABC metric, based on assignments, branches, and conditions. ([@jonas054][], [@jfelchner][]) * [#1352](https://github.com/bbatsov/rubocop/issues/1352): `WordArray` is now configurable with the `WordRegex` option. ([@bquorning][]) * [#1181](https://github.com/bbatsov/rubocop/issues/1181): New cop `Style/StringLiteralsInInterpolation` checks quotes inside interpolated expressions in strings. ([@jonas054][]) * [#872](https://github.com/bbatsov/rubocop/issues/872): `Style/IndentationWidth` is now configurable with the `Width` option. ([@jonas054][]) * [#1396](https://github.com/bbatsov/rubocop/issues/1396): Include `.opal` files by default. ([@bbatsov][]) * [#771](https://github.com/bbatsov/rubocop/issues/771): Three new `Style` cops, `EmptyLinesAroundMethodBody` , `EmptyLinesAroundClassBody` , and `EmptyLinesAroundModuleBody` replace the `EmptyLinesAroundBody` cop. ([@jonas054][]) ### Changes * [#1084](https://github.com/bbatsov/rubocop/issues/1084): Disabled `Style/CollectionMethods` by default. ([@bbatsov][]) ### Bugs fixed * `AlignHash` no longer skips multiline hashes that contain some elements on the same line. ([@mvz][]) * [#1349](https://github.com/bbatsov/rubocop/issues/1349): `BracesAroundHashParameters` no longer cleans up whitespace in autocorrect, as these extra corrections are likely to interfere with other cops' corrections. ([@jonas054][]) * [#1350](https://github.com/bbatsov/rubocop/issues/1350): Guard against `Blocks` cop introducing syntax errors in auto-correct. ([@jonas054][]) * [#1374](https://github.com/bbatsov/rubocop/issues/1374): To eliminate interference, auto-correction is now done by one cop at a time, with saving and re-parsing in between. ([@jonas054][]) * [#1388](https://github.com/bbatsov/rubocop/issues/1388): Fix a false positive in `FormatString`. ([@bbatsov][]) * [#1389](https://github.com/bbatsov/rubocop/issues/1389): Make `--out` to create parent directories. ([@yous][]) * Refine HTML formatter. ([@yujinakayama][]) * [#1410](https://github.com/bbatsov/rubocop/issues/1410): Handle specially Java primitive type references in `ColonMethodCall`. ([@bbatsov][]) ## 0.26.1 (2014-09-18) ### Bugs fixed * [#1326](https://github.com/bbatsov/rubocop/issues/1326): Fix problem in `SpaceInsideParens` with detecting space inside parentheses used for grouping expressions. ([@jonas054][]) * [#1335](https://github.com/bbatsov/rubocop/issues/1335): Restrict URI schemes permitted by `LineLength` when `AllowURI` is enabled. ([@smangelsdorf][]) * [#1339](https://github.com/bbatsov/rubocop/issues/1339): Handle `eql?` and `equal?` in `OpMethod`. ([@bbatsov][]) * [#1340](https://github.com/bbatsov/rubocop/issues/1340): Fix crash in `Style/SymbolProc` cop when the block calls a method with no explicit receiver. ([@smangelsdorf][]) ## 0.26.0 (2014-09-03) ### New features * New formatter `HTMLFormatter` generates a html file with a list of files with offences in them. ([@SkuliOskarsson][]) * New cop `SpaceInsideRangeLiteral` checks for spaces around `..` and `...` in range literals. ([@bbatsov][]) * New cop `InfiniteLoop` checks for places where `Kernel#loop` should have been used. ([@bbatsov][]) * New cop `SymbolProc` checks for places where a symbol can be used as proc instead of a block. ([@bbatsov][]) * `UselessAssignment` cop now suggests a variable name for possible typos if there's a variable-ish identifier similar to the unused variable name in the same scope. ([@yujinakayama][]) * `PredicateName` cop now has separate configurations for prefices that denote predicate method names and predicate prefices that should be removed. ([@bbatsov][]) * [#1272](https://github.com/bbatsov/rubocop/issues/1272): `Tab` cop does auto-correction. ([@yous][]) * [#1274](https://github.com/bbatsov/rubocop/issues/1274): `MultilineIfThen` cop does auto-correction. ([@bbatsov][]) * [#1279](https://github.com/bbatsov/rubocop/issues/1279): `DotPosition` cop does auto-correction. ([@yous][]) * [#1277](https://github.com/bbatsov/rubocop/issues/1277): `SpaceBeforeFirstArg` cop does auto-correction. ([@yous][]) * [#1310](https://github.com/bbatsov/rubocop/issues/1310): Handle `module_function` in `Style/AccessModifierIndentation` and `Style/EmptyLinesAroundAccessModifier`. ([@bbatsov][]) ### Changes * [#1289](https://github.com/bbatsov/rubocop/issues/1289): Use utf-8 as default encoding for inspected files. ([@jonas054][]) * [#1304](https://github.com/bbatsov/rubocop/issues/1304): `Style/Encoding` is no longer a no-op on Ruby 2.x. It's also disabled by default, as projects not supporting 1.9 don't need to run it. ([@bbatsov][]) ### Bugs fixed * [#1263](https://github.com/bbatsov/rubocop/issues/1263): Do not report `%W` literals with special escaped characters in `UnneededCapitalW`. ([@jonas054][]) * [#1286](https://github.com/bbatsov/rubocop/issues/1286): Fix a false positive in `VariableName`. ([@bbatsov][]) * [#1211](https://github.com/bbatsov/rubocop/issues/1211): Fix false negative in `UselessAssignment` when there's a reference for the variable in an exclusive branch. ([@yujinakayama][]) * [#1307](https://github.com/bbatsov/rubocop/issues/1307): Fix auto-correction of `RedundantBegin` cop deletes new line. ([@yous][]) * [#1283](https://github.com/bbatsov/rubocop/issues/1283): Fix auto-correction of indented expressions in `PercentLiteralDelimiters`. ([@jonas054][]) * [#1315](https://github.com/bbatsov/rubocop/pull/1315): `BracesAroundHashParameters` auto-correction removes whitespace around content inside braces. ([@jspanjers][]) * [#1313](https://github.com/bbatsov/rubocop/issues/1313): Fix a false positive in `AndOr` when enforced style is `conditionals`. ([@bbatsov][]) * Handle post-conditional `while` and `until` in `AndOr` when enforced style is `conditionals`. ([@yujinakayama][]) * [#1319](https://github.com/bbatsov/rubocop/issues/1319): Fix a false positive in `FormatString`. ([@bbatsov][]) * [#1287](https://github.com/bbatsov/rubocop/issues/1287): Allow missing blank line for EmptyLinesAroundAccessModifier if next line closes a block. ([@sch1zo][]) ## 0.25.0 (2014-08-15) ### New features * [#1259](https://github.com/bbatsov/rubocop/issues/1259): Allow AndOr cop to autocorrect by adding method call parenthesis. ([@vrthra][]) * [#1232](https://github.com/bbatsov/rubocop/issues/1232): Add EnforcedStyle option to cop `AndOr` to restrict it to conditionals. ([@vrthra][]) * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `PercentQLiterals` checks if use of `%Q` and `%q` matches configuration. ([@jonas054][]) * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `BarePercentLiterals` checks if usage of `%()` or `%Q()` matches configuration. ([@jonas054][]) * [#1079](https://github.com/bbatsov/rubocop/pull/1079): New cop `MultilineBlockLayout` checks if a multiline block has an expression on the same line as the start of the block. ([@barunio][]) * [#1217](https://github.com/bbatsov/rubocop/pull/1217): `Style::EmptyLinesAroundAccessModifier` cop does auto-correction. ([@tamird][]) * [#1220](https://github.com/bbatsov/rubocop/issues/1220): New cop `PerceivedComplexity` is similar to `CyclomaticComplexity`, but reports when methods have a high complexity for a human reader. ([@jonas054][]) * `Debugger` cop now checks for `binding.pry_remote`. ([@yous][]) * [#1238](https://github.com/bbatsov/rubocop/issues/1238): Add `MinBodyLength` option to `Next` cop. ([@bbatsov][]) * [#1241](https://github.com/bbatsov/rubocop/issues/1241): `TrailingComma` cop does auto-correction. ([@yous][]) * [#1078](https://github.com/bbatsov/rubocop/pull/1078): New cop `BlockEndNewline` checks if the end statement of a multiline block is on its own line. ([@barunio][]) * [#1078](https://github.com/bbatsov/rubocop/pull/1078): `BlockAlignment` cop does auto-correction. ([@barunio][]) ### Changes * [#1220](https://github.com/bbatsov/rubocop/issues/1220): New namespace `Metrics` created and some `Style` cops moved there. ([@jonas054][]) * Drop support for Ruby 1.9.2 in accordance with [the end of the security maintenance extension](https://www.ruby-lang.org/en/news/01-07-2014/eol-for-1-8-7-and-1-9-2/). ([@yujinakayama][]) ### Bugs fixed * [#1251](https://github.com/bbatsov/rubocop/issues/1251): Fix `PercentLiteralDelimiters` auto-correct indentation error. ([@hannestyden][]) * [#1197](https://github.com/bbatsov/rubocop/issues/1197): Fix false positive for new lambda syntax in `SpaceInsideBlockBraces`. ([@jonas054][]) * [#1201](https://github.com/bbatsov/rubocop/issues/1201): Fix error at anonymous keyword splat arguments in some variable cops. ([@yujinakayama][]) * Fix false positive in `UnneededPercentQ` for `/%Q(something)/`. ([@jonas054][]) * Fix `SpacesInsideBrackets` for `Hash#[]` calls with spaces after left bracket. ([@mcls][]) * [#1210](https://github.com/bbatsov/rubocop/issues/1210): Fix false positive in `UnneededPercentQ` for `%Q(\t")`. ([@jonas054][]) * Fix false positive in `UnneededPercentQ` for heredoc strings with `%q`/`%Q`. ([@jonas054][]) * [#1214](https://github.com/bbatsov/rubocop/issues/1214): Don't destroy code in `AlignHash` autocorrect. ([@jonas054][]) * [#1219](https://github.com/bbatsov/rubocop/issues/1219): Don't report bad alignment for `end` or `}` in `BlockAlignment` if it doesn't begin its line. ([@jonas054][]) * [#1227](https://github.com/bbatsov/rubocop/issues/1227): Don't permanently change yamler as it can affect other apps. ([@jonas054][]) * [#1184](https://github.com/bbatsov/rubocop/issues/1184): Fix a false positive in `Output` cop. ([@bbatsov][]) * [#1256](https://github.com/bbatsov/rubocop/issues/1256): Ignore block-pass in `TrailingComma`. ([@tamird][]) * [#1255](https://github.com/bbatsov/rubocop/issues/1255): Compare without context in `AutocorrectUnlessChangingAST`. ([@jonas054][]) * [#1262](https://github.com/bbatsov/rubocop/issues/1262): Handle regexp and backtick literals in `VariableInterpolation`. ([@bbatsov][]) ## 0.24.1 (2014-07-03) ### Bugs fixed * [#1174](https://github.com/bbatsov/rubocop/issues/1174): Fix `--auto-correct` crash in `AlignParameters`. ([@jonas054][]) * [#1176](https://github.com/bbatsov/rubocop/issues/1176): Fix `--auto-correct` crash in `IndentationWidth`. ([@jonas054][]) * [#1177](https://github.com/bbatsov/rubocop/issues/1177): Avoid suggesting underscore-prefixed name for unused keyword arguments and auto-correcting in that way. ([@yujinakayama][]) * [#1157](https://github.com/bbatsov/rubocop/issues/1157): Validate `--only` arguments later when all cop names are known. ([@jonas054][]) * [#1188](https://github.com/bbatsov/rubocop/issues/1188), [#1190](https://github.com/bbatsov/rubocop/issues/1190): Fix crash in `LineLength` cop when `AllowURI` option is enabled. ([@yujinakayama][]) * [#1191](https://github.com/bbatsov/rubocop/issues/1191): Fix crash on empty body branches in a loop in `Next` cop. ([@yujinakayama][]) ## 0.24.0 (2014-06-25) ### New features * [#639](https://github.com/bbatsov/rubocop/issues/639): Support square bracket setters in `UselessSetterCall`. ([@yujinakayama][]) * [#835](https://github.com/bbatsov/rubocop/issues/835): `UnneededCapitalW` cop does auto-correction. ([@sfeldon][]) * [#1092](https://github.com/bbatsov/rubocop/issues/1092): New cop `DefEndAlignment` takes over responsibility for checking alignment of method definition `end`s from `EndAlignment`, and is configurable. ([@jonas054][]) * [#1145](https://github.com/bbatsov/rubocop/issues/1145): New cop `ClassCheck` enforces consistent use of `is_a?` or `kind_of?`. ([@bbatsov][]) * [#1161](https://github.com/bbatsov/rubocop/pull/1161): New cop `SpaceBeforeComma` detects spaces before a comma. ([@agrimm][]) * [#1161](https://github.com/bbatsov/rubocop/pull/1161): New cop `SpaceBeforeSemicolon` detects spaces before a semicolon. ([@agrimm][]) * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `UnneededPercentQ` checks for usage of the `%q`/`%Q` syntax when `''` or `""` would do. ([@jonas054][]) * [#977](https://github.com/bbatsov/rubocop/issues/977): Add `AllowURI` option (enabled by default) to `LineLength` cop. ([@yujinakayama][]) ### Changes * Unused block local variables (`obj.each { |arg; this| }`) are now handled by `UnusedBlockArgument` cop instead of `UselessAssignment` cop. ([@yujinakayama][]) * [#1141](https://github.com/bbatsov/rubocop/issues/1141): Clarify in the message from `TrailingComma` that a trailing comma is never allowed for lists where some items share a line. ([@jonas054][]) ### Bugs fixed * [#1133](https://github.com/bbatsov/rubocop/issues/1133): Handle `reduce/inject` with no arguments in `EachWithObject`. ([@bbatsov][]) * [#1152](https://github.com/bbatsov/rubocop/issues/1152): Handle `while/until` with no body in `Next`. ([@tamird][]) * Fix a false positive in `UselessSetterCall` for setter call on a local variable that contains a non-local object. ([@yujinakayama][]) * [#1158](https://github.com/bbatsov/rubocop/issues/1158): Fix auto-correction of floating-point numbers. ([@bbatsov][]) * [#1159](https://github.com/bbatsov/rubocop/issues/1159): Fix checking of `begin`..`end` structures, blocks, and parenthesized expressions in `IndentationWidth`. ([@jonas054][]) * [#1159](https://github.com/bbatsov/rubocop/issues/1159): More rigid conditions for when `attr` is considered an offense. ([@jonas054][]) * [#1167](https://github.com/bbatsov/rubocop/issues/1167): Fix handling of parameters spanning multiple lines in `TrailingComma`. ([@jonas054][]) * [#1169](https://github.com/bbatsov/rubocop/issues/1169): Fix handling of ternary op conditions in `ParenthesesAroundCondition`. ([@bbatsov][]) * [#1147](https://github.com/bbatsov/rubocop/issues/1147): WordArray checks arrays with special characters. ([@camilleldn][]) * Fix a false positive against `return` in a loop in `Next` cop. ([@yujinakayama][]) * [#1165](https://github.com/bbatsov/rubocop/issues/1165): Support `rescue`/`else`/`ensure` bodies in `IndentationWidth`. ([@jonas054][]) * Fix false positive for aligned list of values after `when` in `IndentationWidth`. ([@jonas054][]) ## 0.23.0 (2014-06-02) ### New features * [#1117](https://github.com/bbatsov/rubocop/issues/1117): `BlockComments` cop does auto-correction. ([@jonas054][]) * [#1124](https://github.com/bbatsov/rubocop/pull/1124): `TrivialAccessors` cop auto-corrects class-level accessors. ([@ggilder][]) * [#1062](https://github.com/bbatsov/rubocop/pull/1062): New cop `InlineComment` checks for inline comments. ([@salbertson][]) * [#1118](https://github.com/bbatsov/rubocop/issues/1118): Add checking and auto-correction of right brackets in `IndentArray` and `IndentHash`. ([@jonas054][]) ### Changes * [#1097](https://github.com/bbatsov/rubocop/issues/1097): Add optional namespace prefix to cop names: `Style/LineLength` instead of `LineLength` in config files, `--only` argument, `--show-cops` output, and `# rubocop:disable`. ([@jonas054][]) * [#1075](https://github.com/bbatsov/rubocop/issues/1075): More strict limits on when to require trailing comma. ([@jonas054][]) * Renamed `Rubocop` module to `RuboCop`. ([@bbatsov][]) ### Bugs fixed * [#1126](https://github.com/bbatsov/rubocop/pull/1126): Fix `--auto-gen-config` bug with `RegexpLiteral` where only the last file's results would be used. ([@ggilder][]) * [#1104](https://github.com/bbatsov/rubocop/issues/1104): Fix `EachWithObject` with modifier if as body. ([@geniou][]) * [#1106](https://github.com/bbatsov/rubocop/issues/1106): Fix `EachWithObject` with single method call as body. ([@geniou][]) * Avoid the warning about ignoring syck YAML engine from JRuby. ([@jonas054][]) * [#1111](https://github.com/bbatsov/rubocop/issues/1111): Fix problem in `EndOfLine` with reading non-UTF-8 encoded files. ([@jonas054][]) * [#1115](https://github.com/bbatsov/rubocop/issues/1115): Fix `Next` to ignore super nodes. ([@geniou][]) * [#1117](https://github.com/bbatsov/rubocop/issues/1117): Don't auto-correct indentation in scopes that contain block comments (`=begin`..`=end`). ([@jonas054][]) * [#1123](https://github.com/bbatsov/rubocop/pull/1123): Support setter calls in safe assignment in `ParenthesesAroundCondition`. ([@jonas054][]) * [#1090](https://github.com/bbatsov/rubocop/issues/1090): Correct handling of documentation vs annotation comment. ([@jonas054][]) * [#1118](https://github.com/bbatsov/rubocop/issues/1118): Never write invalid ruby to a file in auto-correct. ([@jonas054][]) * [#1120](https://github.com/bbatsov/rubocop/issues/1120): Don't change indentation of heredoc strings in auto-correct. ([@jonas054][]) * [#1109](https://github.com/bbatsov/rubocop/issues/1109): Handle conditions with modifier ops in them in `ParenthesesAroundCondition`. ([@bbatsov][]) ## 0.22.0 (2014-05-20) ### New features * [#974](https://github.com/bbatsov/rubocop/pull/974): New cop `CommentIndentation` checks indentation of comments. ([@jonas054][]) * Add new cop `EachWithObject` to prefer `each_with_object` over `inject` or `reduce`. ([@geniou][]) * [#1010](https://github.com/bbatsov/rubocop/issues/1010): New Cop `Next` check for conditions at the end of an iteration and propose to use `next` instead. ([@geniou][]) * The `GuardClause` cop now also looks for unless and it is configurable how many lines the body of an if / unless needs to have to not be ignored. ([@geniou][]) * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `UnneededPercentX` checks for `%x` when backquotes would do. ([@jonas054][]) * Add auto-correct to `UnusedBlockArgument` and `UnusedMethodArgument` cops. ([@hannestyden][]) * [#1074](https://github.com/bbatsov/rubocop/issues/1074): New cop `SpaceBeforeComment` checks for missing space between code and a comment on the same line. ([@jonas054][]) * [#1089](https://github.com/bbatsov/rubocop/pull/1089): New option `-F`/`--fail-fast` inspects files in modification time order and stop after the first file with offenses. ([@jonas054][]) * Add optional `require` directive to `.rubocop.yml` to load custom ruby files. ([@geniou][]) ### Changes * `NonNilCheck` offense reporting and autocorrect are configurable to include semantic changes. ([@hannestyden][]) * The parameters `AllCops/Excludes` and `AllCops/Includes` with final `s` only give a warning and don't halt `rubocop` execution. ([@jonas054][]) * The `GuardClause` cop is no longer ignoring a one-line body by default - see configuration. ([@geniou][]) * [#1050](https://github.com/bbatsov/rubocop/issues/1050): Rename `rubocop-todo.yml` file to `.rubocop_todo.yml`. ([@geniou][]) * [#1064](https://github.com/bbatsov/rubocop/issues/1064): Adjust default max line length to 80. ([@bbatsov][]) ### Bugs fixed * Allow assignment in `AlignParameters` cop. ([@tommeier][]) * Fix `Void` and `SpaceAroundOperators` for short call syntax `lambda.()`. ([@biinari][]) * Fix `Delegate` for delegation with assignment or constant. ([@geniou][]) * [#1032](https://github.com/bbatsov/rubocop/issues/1032): Avoid duplicate reporting when code moves around due to `--auto-correct`. ([@jonas054][]) * [#1036](https://github.com/bbatsov/rubocop/issues/1036): Handle strings like `__FILE__` in `LineEndConcatenation`. ([@bbatsov][]) * [#1006](https://github.com/bbatsov/rubocop/issues/1006): Fix LineEndConcatenation to handle chained concatenations. ([@barunio][]) * [#1066](https://github.com/bbatsov/rubocop/issues/1066): Fix auto-correct for `NegatedIf` when the condition has parentheses around it. ([@jonas054][]) * Fix `AlignParameters` `with_fixed_indentation` for multi-line method calls. ([@molawson][]) * Fix problem that appears in some installations when reading empty YAML files. ([@jonas054][]) * [#1022](https://github.com/bbatsov/rubocop/issues/1022): A Cop will no longer auto-correct a file that's excluded through an `Exclude` setting in the cop's configuration. ([@jonas054][]) * Fix paths in `Exclude` config section not being recognized on Windows. ([@wndhydrnt][]) * [#1094](https://github.com/bbatsov/rubocop/issues/1094): Fix ClassAndModuleChildren for classes with a single method. ([@geniou][]) ## 0.21.0 (2014-04-24) ### New features * [#835](https://github.com/bbatsov/rubocop/issues/835): New cop `UnneededCapitalW` checks for `%W` when interpolation not necessary and `%w` would do. ([@sfeldon][]) * [#934](https://github.com/bbatsov/rubocop/issues/934): New cop `UnderscorePrefixedVariableName` checks for `_`-prefixed variables that are actually used. ([@yujinakayama][]) * [#934](https://github.com/bbatsov/rubocop/issues/934): New cop `UnusedMethodArgument` checks for unused method arguments. ([@yujinakayama][]) * [#934](https://github.com/bbatsov/rubocop/issues/934): New cop `UnusedBlockArgument` checks for unused block arguments. ([@yujinakayama][]) * [#964](https://github.com/bbatsov/rubocop/issues/964): `RedundantBegin` cop does auto-correction. ([@tamird][]) * [#966](https://github.com/bbatsov/rubocop/issues/966): `RescueException` cop does auto-correction. ([@tamird][]) * [#967](https://github.com/bbatsov/rubocop/issues/967): `TrivialAccessors` cop does auto-correction. ([@tamird][]) * [#963](https://github.com/bbatsov/rubocop/issues/963): Add `AllowDSLWriters` options to `TrivialAccessors`. ([@tamird][]) * [#969](https://github.com/bbatsov/rubocop/issues/969): Let the `Debugger` cop check for forgotten calls to byebug. ([@bquorning][]) * [#971](https://github.com/bbatsov/rubocop/issues/971): Configuration format deprecation warnings include the path to the problematic config file. ([@bcobb][]) * [#490](https://github.com/bbatsov/rubocop/issues/490): Add EnforcedStyle config option to TrailingBlankLines. ([@jonas054][]) * Add `auto_correct` task to Rake integration. ([@irrationalfab][]) * [#986](https://github.com/bbatsov/rubocop/issues/986): The `--only` option can take a comma-separated list of cops. ([@jonas054][]) * New Rails cop `Delegate` that checks for delegations that could be replaced by the `delegate` method. ([@geniou][]) * Add configuration to `Encoding` cop to only enforce encoding comment if there are non ASCII characters. ([@geniou][]) ### Changes * Removed `FinalNewline` cop as its check is now performed by `TrailingBlankLines`. ([@jonas054][]) * [#1011](https://github.com/bbatsov/rubocop/issues/1011): Pattern matching with `Dir#[]` for config parameters added. ([@jonas054][]) ### Bugs fixed * Update description on `LineEndConcatenation` cop. ([@mockdeep][]) * [#978](https://github.com/bbatsov/rubocop/issues/978): Fix regression in `IndentationWidth` handling method calls. ([@tamird][]) * [#976](https://github.com/bbatsov/rubocop/issues/976): Fix `EndAlignment` not handling element assignment correctly. ([@tamird][]) * [#976](https://github.com/bbatsov/rubocop/issues/976): Fix `IndentationWidth` not handling element assignment correctly. ([@tamird][]) * [#800](https://github.com/bbatsov/rubocop/issues/800): Do not report `[Corrected]` in `--auto-correct` mode if correction wasn't done. ([@jonas054][]) * [#968](https://github.com/bbatsov/rubocop/issues/968): Fix bug when running RuboCop with `-c .rubocop.yml`. ([@bquorning][]) * [#975](https://github.com/bbatsov/rubocop/pull/975): Fix infinite correction in `IndentationWidth`. ([@jonas054][]) * [#986](https://github.com/bbatsov/rubocop/issues/986): When `--lint` is used together with `--only`, all lint cops are run in addition to the given cops. ([@jonas054][]) * [#997](https://github.com/bbatsov/rubocop/issues/997): Fix handling of file paths for matching against `Exclude` property when `rubocop .` is called. ([@jonas054][]) * [#1000](https://github.com/bbatsov/rubocop/issues/1000): Support modifier (e.g., `private`) and `def` on the same line (Ruby >= 2.1) in `IndentationWidth`. ([@jonas054][]) * [#1001](https://github.com/bbatsov/rubocop/issues/1001): Fix `--auto-gen-config` logic for `RegexpLiteral`. ([@jonas054][]) * [#993](https://github.com/bbatsov/rubocop/issues/993): Do not report any offenses for the contents of an empty file. ([@jonas054][]) * [#1016](https://github.com/bbatsov/rubocop/issues/1016): Fix a false positive in `ConditionPosition` regarding statement modifiers. ([@bbatsov][]) * [#1014](https://github.com/bbatsov/rubocop/issues/1014): Fix handling of strings nested in `dstr` nodes. ([@bbatsov][]) ## 0.20.1 (2014-04-05) ### Bugs fixed * [#940](https://github.com/bbatsov/rubocop/issues/940): Fixed `UselessAccessModifier` not handling `attr_*` correctly. ([@fshowalter][]) * `NegatedIf` properly handles negated `unless` condition. ([@bbatsov][]) * `NegatedWhile` properly handles negated `until` condition. ([@bbatsov][]) * [#925](https://github.com/bbatsov/rubocop/issues/925): Do not disable the `Syntax` cop in output from `--auto-gen-config`. ([@jonas054][]) * [#943](https://github.com/bbatsov/rubocop/issues/943): Fix auto-correction interference problem between `SpaceAfterComma` and other cops. ([@jonas054][]) * [#954](https://github.com/bbatsov/rubocop/pull/954): Fix auto-correction bug in `NilComparison`. ([@bbatsov][]) * [#953](https://github.com/bbatsov/rubocop/pull/953): Fix auto-correction bug in `NonNilCheck`. ([@bbatsov][]) * [#952](https://github.com/bbatsov/rubocop/pull/952): Handle implicit receiver in `StringConversionInInterpolation`. ([@bbatsov][]) * [#956](https://github.com/bbatsov/rubocop/pull/956): Apply `ClassMethods` check only on `class`/`module` bodies. ([@bbatsov][]) * [#945](https://github.com/bbatsov/rubocop/issues/945): Fix SpaceBeforeFirstArg cop for multiline argument and exclude assignments. ([@cschramm][]) * [#948](https://github.com/bbatsov/rubocop/issues/948): `Blocks` cop avoids auto-correction if it would introduce a semantic change. ([@jonas054][]) * [#946](https://github.com/bbatsov/rubocop/issues/946): Allow non-nil checks that are the final expressions of predicate method definitions in `NonNilCheck`. ([@bbatsov][]) * [#957](https://github.com/bbatsov/rubocop/issues/957): Allow space + comment inside parentheses, braces, and square brackets. ([@jonas054][]) ## 0.20.0 (2014-04-02) ### New features * New cop `GuardClause` checks for conditionals that can be replaced by guard clauses. ([@bbatsov][]) * New cop `EmptyInterpolation` checks for empty interpolation in double-quoted strings. ([@bbatsov][]) * [#899](https://github.com/bbatsov/rubocop/issues/899): Make `LineEndConcatenation` cop `<<` aware. ([@mockdeep][]) * [#896](https://github.com/bbatsov/rubocop/issues/896): New option `--fail-level` changes minimum severity for exit with error code. ([@hiroponz][]) * [#893](https://github.com/bbatsov/rubocop/issues/893): New option `--force-exclusion` forces excluding files specified in the configuration `Exclude` even if they are explicitly passed as arguments. ([@yujinakayama][]) * `VariableInterpolation` cop does auto-correction. ([@bbatsov][]) * `Not` cop does auto-correction. ([@bbatsov][]) * `ClassMethods` cop does auto-correction. ([@bbatsov][]) * `StringConversionInInterpolation` cop does auto-correction. ([@bbatsov][]) * `NilComparison` cop does auto-correction. ([@bbatsov][]) * `NonNilComparison` cop does auto-correction. ([@bbatsov][]) * `NegatedIf` cop does auto-correction. ([@bbatsov][]) * `NegatedWhile` cop does auto-correction. ([@bbatsov][]) * New lint cop `SpaceBeforeFirstArg` checks for space between the method name and the first argument in method calls without parentheses. ([@jonas054][]) * New style cop `SingleSpaceBeforeFirstArg` checks that no more than one space is used between the method name and the first argument in method calls without parentheses. ([@jonas054][]) * New formatter `disabled_lines` displays cops and line ranges disabled by inline comments. ([@fshowalter][]) * New cop `UselessAccessModifiers` checks for access modifiers that have no effect. ([@fshowalter][]) ### Changes * [#913](https://github.com/bbatsov/rubocop/issues/913): `FileName` accepts multiple extensions. ([@tamird][]) * `AllCops/Excludes` and `AllCops/Includes` were renamed to `AllCops/Exclude` and `AllCops/Include` for consistency with standard cop params. ([@bbatsov][]) * Extract `NonNilCheck` cop from `NilComparison`. ([@bbatsov][]) * Renamed `FavorJoin` to `ArrayJoin`. ([@bbatsov][]) * Renamed `FavorUnlessOverNegatedIf` to `NegatedIf`. ([@bbatsov][]) * Renamed `FavorUntilOverNegatedWhile`to `NegatedWhile`. ([@bbatsov][]) * Renamed `HashMethods` to `DeprecatedHashMethods`. ([@bbatsov][]) * Renamed `ReadAttribute` to `ReadWriteAttribute` and extended it to check for uses of `write_attribute`. ([@bbatsov][]) * Add experimental support for Ruby 2.2 (development version) by falling back to Ruby 2.1 parser. ([@yujinakayama][]) ### Bugs fixed * [#926](https://github.com/bbatsov/rubocop/issues/926): Fixed `BlockNesting` not auto-generating correctly. ([@tmorris-fiksu][]) * [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `LiteralInInterpolation`. ([@bbatsov][]) * [#904](https://github.com/bbatsov/rubocop/issues/904): Fixed a NPE in `StringConversionInInterpolation`. ([@bbatsov][]) * [#892](https://github.com/bbatsov/rubocop/issues/892): Make sure `Include` and `Exclude` paths in a `.rubocop.yml` are interpreted as relative to the directory of that file. ([@jonas054][]) * [#906](https://github.com/bbatsov/rubocop/issues/906): Fixed a false positive in `LiteralInInterpolation`. ([@bbatsov][]) * [#909](https://github.com/bbatsov/rubocop/issues/909): Handle properly multiple `rescue` clauses in `SignalException`. ([@bbatsov][]) * [#876](https://github.com/bbatsov/rubocop/issues/876): Do a deep merge of hashes when overriding default configuration in a `.rubocop.yml` file. ([@jonas054][]) * [#912](https://github.com/bbatsov/rubocop/issues/912): Fix a false positive in `LineEndConcatenation` for `%` string literals. ([@bbatsov][]) * [#912](https://github.com/bbatsov/rubocop/issues/912): Handle top-level constant resolution in `DeprecatedClassMethods` (e.g. `::File.exists?`). ([@bbatsov][]) * [#914](https://github.com/bbatsov/rubocop/issues/914): Fixed rdoc error during gem installation. ([@bbatsov][]) * The `--only` option now enables the given cop in case it is disabled in configuration. ([@jonas054][]) * Fix path resolution so that the default exclusion of `vendor` directories works. ([@jonas054][]) * [#908](https://github.com/bbatsov/rubocop/issues/908): Fixed hanging while auto correct for `SpaceAfterComma` and `SpaceInsideBrackets`. ([@hiroponz][]) * [#919](https://github.com/bbatsov/rubocop/issues/919): Don't avoid auto-correction in `HashSyntax` when there is missing space around operator. ([@jonas054][]) * Fixed handling of floats in `NumericLiterals`. ([@bbatsov][]) * [#927](https://github.com/bbatsov/rubocop/issues/927): Let `--auto-gen-config` overwrite an existing `rubocop-todo.yml` file instead of asking the user to remove it. ([@jonas054][]) * [#936](https://github.com/bbatsov/rubocop/issues/936): Allow `_other` as well as `other` in `OpMethod`. ([@bbatsov][]) ## 0.19.1 (2014-03-17) ### Bugs fixed * [#884](https://github.com/bbatsov/rubocop/issues/884): Fix --auto-gen-config for `NumericLiterals` so MinDigits is correct. ([@tmorris-fiksu][]) * [#879](https://github.com/bbatsov/rubocop/issues/879): Fix --auto-gen-config for `RegexpLiteral` so we don't generate illegal values for `MaxSlashes`. ([@jonas054][]) * Fix the name of the `Include` param in the default config of the Rails cops. ([@bbatsov][]) * [#878](https://github.com/bbatsov/rubocop/pull/878): Blacklist `Rakefile`, `Gemfile` and `Capfile` by default in the `FileName` cop. ([@bbatsov][]) * [#875](https://github.com/bbatsov/rubocop/issues/875): Handle `separator` style hashes in `IndentHash`. ([@jonas054][]) * Fix a bug where multiple cli options that result in exit can be specified at once (e.g. `-vV`, `-v --show-cops`). ([@jkogara][]) * [#889](https://github.com/bbatsov/rubocop/issues/889): Fix a false positive for `LiteralInCondition` when the condition is non-primitive array. ([@bbatsov][]) ## 0.19.0 (2014-03-13) ### New features * New cop `FileName` makes sure that source files have snake_case names. ([@bbatsov][]) * New cop `DeprecatedClassMethods` checks for deprecated class methods. ([@bbatsov][]) * New cop `StringConversionInInterpolation` checks for redundant `Object#to_s` in string interpolation. ([@bbatsov][]) * New cop `LiteralInInterpolation` checks for interpolated string literals. ([@bbatsov][]) * New cop `SelfAssignment` checks for places where the self-assignment shorthand should have been used. ([@bbatsov][]) * New cop `DoubleNegation` checks for uses of `!!`. ([@bbatsov][]) * New cop `PercentLiteralDelimiters` enforces consistent usage of `%`-literal delimiters. ([@hannestyden][]) * New Rails cop `ActionFilter` enforces the use of `_filter` or `_action` action filter methods. ([@bbatsov][]) * New Rails cop `ScopeArgs` makes sure you invoke the `scope` method properly. ([@bbatsov][]) * Add `with_fixed_indentation` style to `AlignParameters` cop. ([@hannestyden][]) * Add `IgnoreLastArgumentHash` option to `AlignHash` cop. ([@hannestyden][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `SingleLineMethods` cop does auto-correction. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `Semicolon` cop does auto-correction. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `EmptyLineBetweenDefs` cop does auto-correction. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationWidth` cop does auto-correction. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `IndentationConsistency` cop does auto-correction. ([@jonas054][]) * [#809](https://github.com/bbatsov/rubocop/issues/809): New formatter `fuubar` displays a progress bar and shows details of offenses as soon as they are detected. ([@yujinakayama][]) * [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentHash` checks the indentation of the first key in multi-line hash literals. ([@jonas054][]) * [#797](https://github.com/bbatsov/rubocop/issues/797): New cop `IndentArray` checks the indentation of the first element in multi-line array literals. ([@jonas054][]) * [#806](https://github.com/bbatsov/rubocop/issues/806): Now excludes files in `vendor/**` by default. ([@jeremyolliver][]) * [#795](https://github.com/bbatsov/rubocop/issues/795): `IfUnlessModifier` and `WhileUntilModifier` supports `MaxLineLength`, which is independent of `LineLength` parameter `Max`. ([@agrimm][]) * [#868](https://github.com/bbatsov/rubocop/issues/868): New cop `ClassAndModuleChildren` checks the style of children definitions at classes and modules: nested / compact. ([@geniou][]) ### Changes * [#793](https://github.com/bbatsov/rubocop/issues/793): Add printing total count when `rubocop --format offences`. ([@ma2gedev][]) * Remove `Ignore` param from the Rails `Output` cop. The standard `Exclude/Include` should be used instead. ([@bbatsov][]) * Renamed `FavorSprintf` to `FormatString` and made it configurable. ([@bbatsov][]) * Renamed `Offence` to `Offense`. ([@bbatsov][]) * Use `offense` in all messages instead of `offence`. ([@bbatsov][]) * For indentation of `if`/`unless`/`while`/`until` bodies when the result is assigned to a variable, instead of supporting two styles simultaneously, `IndentationWidth` now supports one style of indentation at a time, specified by `EndAlignment`/`AlignWith`. ([@jonas054][]) * Renamed `Style` param of `DotPosition` cop to `EnforcedStyle`. ([@bbatsov][]) * Add `length` value to locations of offense in JSON formatter. ([@yujinakayama][]) * `SpaceAroundBlockBraces` cop replaced by `SpaceBeforeBlockBraces` and `SpaceInsideBlockBraces`. ([@jonas054][]) * `SpaceAroundEqualsInParameterDefault` cop is now configurable with the `EnforcedStyle` option. ([@jonas054][]) ### Bugs fixed * [#790](https://github.com/bbatsov/rubocop/issues/790): Fix auto-correction interference problem between `MethodDefParentheses` and other cops. ([@jonas054][]) * [#794](https://github.com/bbatsov/rubocop/issues/794): Fix handling of modifier keywords with required parentheses in `ParenthesesAroundCondition`. ([@bbatsov][]) * [#804](https://github.com/bbatsov/rubocop/issues/804): Fix a false positive with operator assignments in a loop (including `begin..rescue..end` with `retry`) in `UselessAssignment`. ([@yujinakayama][]) * [#815](https://github.com/bbatsov/rubocop/issues/815): Fix a false positive for heredocs with blank lines in them in `EmptyLines`. ([@bbatsov][]) * Auto-correction is now more robust and less likely to die because of `RangeError` or "clobbering". ([@jonas054][]) * Offenses always reported in order of position in file, also during `--auto-correct` runs. ([@jonas054][]) * Fix problem with `[Corrected]` tag sometimes missing in output from `--auto-correct` runs. ([@jonas054][]) * Fix message from `EndAlignment` cop when `AlignWith` is `keyword`. ([@jonas054][]) * Handle `case` conditions in `LiteralInCondition`. ([@bbatsov][]) * [#822](https://github.com/bbatsov/rubocop/issues/822): Fix a false positive in `DotPosition` when enforced style is set to `trailing`. ([@bbatsov][]) * Handle properly dynamic strings in `LineEndConcatenation`. ([@bbatsov][]) * [#832](https://github.com/bbatsov/rubocop/issues/832): Fix auto-correction interference problem between `BracesAroundHashParameters` and `SpaceInsideHashLiteralBraces`. ([@jonas054][]) * Fix bug in auto-correction of alignment so that only space can be removed. ([@jonas054][]) * Fix bug in `IndentationWidth` auto-correction so it doesn't correct things that `IndentationConsistency` should correct. ([@jonas054][]) * [#847](https://github.com/bbatsov/rubocop/issues/847): Fix bug in `RegexpLiteral` concerning `--auto-gen-config`. ([@jonas054][]) * [#848](https://github.com/bbatsov/rubocop/issues/848): Fix bug in `--show-cops` that made it print the default configuration rather than the current configuration. ([@jonas054][]) * [#862](https://github.com/bbatsov/rubocop/issues/862): Fix a bug where single line `rubocop:disable` comments with indentations were treated as multiline cop disabling comments. ([@yujinakayama][]) * Fix a bug where `rubocop:disable` comments with a cop name including `all` (e.g. `MethodCallParentheses`) were disabling all cops. ([@yujinakayama][]) * Fix a bug where string and regexp literals including `# rubocop:disable` were confused with real comments. ([@yujinakayama][]) * [#877](https://github.com/bbatsov/rubocop/issues/877): Fix bug in `PercentLiteralDelimiters` concerning auto-correct of regular expressions with interpolation. ([@hannestyden][]) ## 0.18.1 (2014-02-02) ### Bugs fixed * Remove double reporting in `EmptyLinesAroundBody` of empty line inside otherwise empty class/module/method that caused crash in autocorrect. ([@jonas054][]) * [#779](https://github.com/bbatsov/rubocop/issues/779): Fix a false positive in `LineEndConcatenation`. ([@bbatsov][]) * [#751](https://github.com/bbatsov/rubocop/issues/751): Fix `Documentation` cop so that a comment followed by an empty line and then a class definition is not considered to be class documentation. ([@jonas054][]) * [#783](https://github.com/bbatsov/rubocop/issues/783): Fix a false positive in `ParenthesesAroundCondition` when the parentheses are actually required. ([@bbatsov][]) * [#781](https://github.com/bbatsov/rubocop/issues/781): Fix problem with back-and-forth auto-correction in `AccessModifierIndentation`. ([@jonas054][]) * [#785](https://github.com/bbatsov/rubocop/issues/785): Fix false positive on `%w` arrays in `TrailingComma`. ([@jonas054][]) * [#782](https://github.com/bbatsov/rubocop/issues/782): Fix false positive in `AlignHash` for single line hashes. ([@jonas054][]) ## 0.18.0 (2014-01-30) ### New features * [#714](https://github.com/bbatsov/rubocop/issues/714): New cop `RequireParentheses` checks for method calls without parentheses together with a boolean operator indicating that a mistake about precedence may have been made. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `WordArray` cop does auto-correction. ([@jonas054][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `Proc` cop does auto-correction. ([@bbatsov][]) * [#743](https://github.com/bbatsov/rubocop/issues/743): `AccessModifierIndentation` cop does auto-correction. ([@jonas054][]) * [#768](https://github.com/bbatsov/rubocop/issues/768): Rake task now supports `requires` and `options`. ([@nevir][]) * [#759](https://github.com/bbatsov/rubocop/issues/759): New cop `EndLineConcatenation` checks for string literal concatenation with `+` at line end. ([@bbatsov][]) ### Changes * [#762](https://github.com/bbatsov/rubocop/issues/762): Support Rainbow gem both 1.99.x and 2.x. ([@yujinakayama][]) * [#761](https://github.com/bbatsov/rubocop/issues/761): Relax `json` requirement to `>= 1.7.7`. ([@bbatsov][]) * [#757](https://github.com/bbatsov/rubocop/issues/757): `Include/Exclude` supports relative globbing to some extent. ([@nevir][]) ### Bugs fixed * [#764](https://github.com/bbatsov/rubocop/issues/764): Handle heredocs in `TrailingComma`. ([@jonas054][]) * Guide for contributors now points to correct issues page. ([@scottmatthewman][]) ## 0.17.0 (2014-01-25) ### New features * New cop `ConditionPosition` checks for misplaced conditions in expressions like `if/unless/when/until`. ([@bbatsov][]) * New cop `ElseLayout` checks for odd arrangement of code in the `else` branch of a conditional expression. ([@bbatsov][]) * [#694](https://github.com/bbatsov/rubocop/issues/694): Support Ruby 1.9.2 until June 2014. ([@yujinakayama][]) * [#702](https://github.com/bbatsov/rubocop/issues/702): Improve `rubocop-todo.yml` with comments about offence count, configuration parameters, and auto-correction support. ([@jonas054][]) * Add new command-line flag `-D/--display-cop-names` to trigger the display of cop names in offence messages. ([@bbatsov][]) * [#733](https://github.com/bbatsov/rubocop/pull/733): `NumericLiterals` cop does auto-correction. ([@dblock][]) * [#713](https://github.com/bbatsov/rubocop/issues/713): New cop `TrailingComma` checks for comma after the last item in a hash, array, or method call parameter list. ([@jonas054][]) ### Changes * [#581](https://github.com/bbatsov/rubocop/pull/581): Extracted a new cop `AmbiguousOperator` from `Syntax` cop. It checks for ambiguous operators in the first argument of a method invocation without parentheses. ([@yujinakayama][]) * Extracted a new cop `AmbiguousRegexpLiteral` from `Syntax` cop. It checks for ambiguous regexp literals in the first argument of a method invocation without parentheses. ([@yujinakayama][]) * Extracted a new cop `UselessElseWithoutRescue` from `Syntax` cop. It checks for useless `else` in `begin..end` without `rescue`. ([@yujinakayama][]) * Extracted a new cop `InvalidCharacterLiteral` from `Syntax` cop. It checks for invalid character literals with a non-escaped whitespace character (e.g. `? `). ([@yujinakayama][]) * Removed `Syntax` cop from the configuration. It no longer can be disabled and it reports only invalid syntax offences. ([@yujinakayama][]) * [#688](https://github.com/bbatsov/rubocop/issues/688): Output from `rubocop --show-cops` now looks like a YAML configuration file. The `--show-cops` option takes a comma separated list of cops as optional argument. ([@jonas054][]) * New cop `IndentationConsistency` extracted from `IndentationWidth`, which has checked two kinds of offences until now. ([@jonas054][]) ### Bugs fixed * [#698](https://github.com/bbatsov/rubocop/pull/698): Support Windows paths on command-line. ([@rifraf][]) * [#498](https://github.com/bbatsov/rubocop/issues/498): Disable terminal ANSI escape sequences when a formatter's output is not a TTY. ([@yujinakayama][]) * [#703](https://github.com/bbatsov/rubocop/issues/703): BracesAroundHashParameters auto-correction broken with trailing comma. ([@jonas054][]) * [#709](https://github.com/bbatsov/rubocop/issues/709): When `EndAlignment` has configuration `AlignWith: variable`, it now handles `@@a = if ...` and `a, b = if ...`. ([@jonas054][]) * `SpaceAroundOperators` now reports an offence for `@@a=0`. ([@jonas054][]) * [#707](https://github.com/bbatsov/rubocop/issues/707): Fix error on operator assignments in top level scope in `UselessAssignment`. ([@yujinakayama][]) * Fix a bug where some offences were discarded when any cop that has specific target file path (by `Include` or `Exclude` under each cop configuration) had run. ([@yujinakayama][]) * [#724](https://github.com/bbatsov/rubocop/issues/724): Accept colons denoting required keyword argument (a new feature in Ruby 2.1) without trailing space in `SpaceAfterColon`. ([@jonas054][]) * The `--no-color` option works again. ([@jonas054][]) * [#716](https://github.com/bbatsov/rubocop/issues/716): Fixed a regression in the auto-correction logic of `MethodDefParentheses`. ([@bbatsov][]) * Inspected projects that lack a `.rubocop.yml` file, and therefore get their configuration from RuboCop's `config/default.yml`, no longer get configuration from RuboCop's `.rubocop.yml` and `rubocop-todo.yml`. ([@jonas054][]) * [#730](https://github.com/bbatsov/rubocop/issues/730): `EndAlignment` now handles for example `private def some_method`, which is allowed in Ruby 2.1. It requires `end` to be aligned with `private`, not `def`, in such cases. ([@jonas054][]) * [#744](https://github.com/bbatsov/rubocop/issues/744): Any new offences created by `--auto-correct` are now handled immediately and corrected when possible, so running `--auto-correct` once is enough. ([@jonas054][]) * [#748](https://github.com/bbatsov/rubocop/pull/748): Auto-correction conflict between `EmptyLinesAroundBody` and `TrailingWhitespace` resolved. ([@jonas054][]) * `ParenthesesAroundCondition` no longer crashes on parentheses around the condition in a ternary if. ([@jonas054][]) * [#738](https://github.com/bbatsov/rubocop/issues/738): Fix a false positive in `StringLiterals`. ([@bbatsov][]) ## 0.16.0 (2013-12-25) ### New features * [#612](https://github.com/bbatsov/rubocop/pull/612): `BracesAroundHashParameters` cop does auto-correction. ([@dblock][]) * [#614](https://github.com/bbatsov/rubocop/pull/614): `ParenthesesAroundCondition` cop does auto-correction. ([@dblock][]) * [#624](https://github.com/bbatsov/rubocop/pull/624): `EmptyLines` cop does auto-correction. ([@dblock][]) * New Rails cop `DefaultScope` ensures `default_scope` is called properly with a block argument. ([@bbatsov][]) * All cops now support the `Include` param, which specifies the files on which they should operate. ([@bbatsov][]) * All cops now support the `Exclude` param, which specifies the files on which they should not operate. ([@bbatsov][]) * [#631](https://github.com/bbatsov/rubocop/issues/631): `IndentationWidth` cop now detects inconsistent indentation between lines that should have the same indentation. ([@jonas054][]) * [#649](https://github.com/bbatsov/rubocop/pull/649): `EmptyLinesAroundBody` cop does auto-correction. ([@dblock][]) * [#657](https://github.com/bbatsov/rubocop/pull/657): `Alias` cop does auto-correction. ([@dblock][]) * Rake task now support setting formatters. ([@pmenglund][]) * [#653](https://github.com/bbatsov/rubocop/issues/653): `CaseIndentation` cop is now configurable with parameters `IndentWhenRelativeTo` and `IndentOneStep`. ([@jonas054][]) * [#654](https://github.com/bbatsov/rubocop/pull/654): `For` cop is now configurable to enforce either `each` (default) or `for`. ([@jonas054][]) * [#661](https://github.com/bbatsov/rubocop/issues/661): `EndAlignment` cop is now configurable for alignment with `keyword` (default) or `variable`. ([@jonas054][]) * Allow to overwrite the severity of a cop with the new `Severity` param. ([@codez][]) * New cop `FlipFlop` checks for flip flops. ([@agrimm][]) * [#577](https://github.com/bbatsov/rubocop/issues/577): Introduced `MethodDefParentheses` to allow for for requiring either parentheses or no parentheses in method definitions. Replaces `DefWithoutParentheses`. ([@skanev][]) * [#693](https://github.com/bbatsov/rubocop/pull/693): Generation of parameter values (i.e., not only `Enabled: false`) in `rubocop-todo.yml` by the `--auto-gen-config` option is now supported for some cops. ([@jonas054][]) * New cop `AccessorMethodName` checks accessor method names for non-idiomatic names like `get_attribute` and `set_attribute`. ([@bbatsov][]) * New cop `PredicateName` checks the names of predicate methods for non-idiomatic names like `is_something`, `has_something`, etc. ([@bbatsov][]) * Support Ruby 2.1 with Parser 2.1. ([@yujinakayama][]) ### Changes * Removed `SymbolNames` as it was generating way too many false positives. ([@bbatsov][]) * Renamed `ReduceArguments` to `SingleLineBlockParams` and made it configurable. ([@bbatsov][]) ### Bugs fixed * Handle properly heredocs in `StringLiterals` cop. ([@bbatsov][]) * Fix `SpaceAroundOperators` to not report missing space around operator for `def self.method *args`. ([@jonas054][]) * Properly handle `['AllCops']['Includes']` and `['AllCops']['Excludes']` when passing config via `-c`. ([@fancyremarker][], [@codez][]) * [#611](https://github.com/bbatsov/rubocop/pull/611): Fix crash when loading an empty config file. ([@sinisterchipmunk][]) * Fix `DotPosition` cop with `trailing` style for method calls on same line. ([@vonTronje][]) * [#627](https://github.com/bbatsov/rubocop/pull/627): Fix counting of slashes in complicated regexps in `RegexpLiteral` cop. ([@jonas054][]) * [#638](https://github.com/bbatsov/rubocop/issues/638): Fix bug in auto-correct that changes `each{ |x|` to `each d o |x|`. ([@jonas054][]) * [#418](https://github.com/bbatsov/rubocop/issues/418): Stop searching for configuration files above the work directory of the isolated environment when running specs. ([@jonas054][]) * Fix error on implicit match conditionals (e.g. `if /pattern/; end`) in `MultilineIfThen`. ([@agrimm][]) * [#651](https://github.com/bbatsov/rubocop/issues/651): Handle properly method arguments in `RedundantSelf`. ([@bbatsov][]) * [#628](https://github.com/bbatsov/rubocop/issues/628): Allow `self.Foo` in `RedundantSelf` cop. ([@chulkilee][]) * [#668](https://github.com/bbatsov/rubocop/issues/668): Fix crash in `EndOfLine` that occurs when default encoding is `US_ASCII` and an inspected file has non-ascii characters. ([@jonas054][]) * [#664](https://github.com/bbatsov/rubocop/issues/664): Accept oneline while when condition has local variable assignment. ([@emou][]) * Fix auto-correct for `MethodDefParentheses` when parentheses are required. ([@skanev][]) ## 0.15.0 (2013-11-06) ### New features * New cop `Output` checks for calls to print, puts, etc. in Rails. ([@daviddavis][]) * New cop `EmptyLinesAroundBody` checks for empty lines around the bodies of class, method and module definitions. ([@bbatsov][]) * `LeadingCommentSpace` cop does auto-correction. ([@jonas054][]) * `SpaceAfterControlKeyword` cop does auto-correction. ([@jonas054][]) * `SpaceAfterColon` cop does auto-correction. ([@jonas054][]) * `SpaceAfterComma` cop does auto-correction. ([@jonas054][]) * `SpaceAfterSemicolon` cop does auto-correction. ([@jonas054][]) * `SpaceAfterMethodName` cop does auto-correction. ([@jonas054][]) * `SpaceAroundBlockBraces` cop does auto-correction. ([@jonas054][]) * `SpaceAroundEqualsInParameterDefault` cop does auto-correction. ([@jonas054][]) * `SpaceAroundOperators` cop does auto-correction. ([@jonas054][]) * `SpaceBeforeModifierKeyword` cop does auto-correction. ([@jonas054][]) * `SpaceInsideHashLiteralBraces` cop does auto-correction. ([@jonas054][]) * `SpaceInsideBrackets` cop does auto-correction. ([@jonas054][]) * `SpaceInsideParens` cop does auto-correction. ([@jonas054][]) * `TrailingWhitespace` cop does auto-correction. ([@jonas054][]) * `TrailingBlankLines` cop does auto-correction. ([@jonas054][]) * `FinalNewline` cop does auto-correction. ([@jonas054][]) * New cop `CyclomaticComplexity` checks the cyclomatic complexity of methods against a configurable max value. ([@jonas054][]) * [#594](https://github.com/bbatsov/rubocop/pull/594): New parameter `EnforcedStyleForEmptyBraces` with values `space` and `no_space` (default) added to `SpaceAroundBlockBraces`. ([@jonas054][]) * [#603](https://github.com/bbatsov/rubocop/pull/603): New parameter `MinSize` added to `WordArray` to allow small string arrays, retaining the default (0). ([@claco][]) ### Changes * [#557](https://github.com/bbatsov/rubocop/pull/557): Configuration files for excluded files are no longer loaded. ([@jonas054][]) * [#571](https://github.com/bbatsov/rubocop/pull/571): The default rake task now runs RuboCop over itself! ([@nevir][]) * Encoding errors are reported as fatal offences rather than printed with red text. ([@jonas054][]) * `AccessControl` cop is now configurable with the `EnforcedStyle` option. ([@sds][]) * Split `AccessControl` cop to `AccessModifierIndentation` and `EmptyLinesAroundAccessModifier`. ([@bbatsov][]) * [#594](https://github.com/bbatsov/rubocop/pull/594): Add configuration parameter `EnforcedStyleForEmptyBraces` to `SpaceInsideHashLiteralBraces` cop, and change `EnforcedStyleIsWithSpaces` (values `true`, `false`) to `EnforcedStyle` (values `space`, `no_space`). ([@jonas054][]) * Coverage builds linked from the README page are enabled again. ([@jonas054][]) ### Bugs fixed * [#561](https://github.com/bbatsov/rubocop/pull/561): Handle properly negative literals in `NumericLiterals` cop. ([@bbatsov][]) * [#567](https://github.com/bbatsov/rubocop/pull/567): Register an offence when the last hash parameter has braces in `BracesAroundHashParameters` cop. ([@dblock][]) * `StringLiterals` cop no longer reports errors for character literals such as ?/. That should be done only by the `CharacterLiterals` cop. ([@jonas054][]) * Made auto-correct much less likely to crash due to conflicting corrections ("clobbering"). ([@jonas054][]) * [#565](https://github.com/bbatsov/rubocop/pull/565): `$GLOBAL_VAR from English library` should no longer be inserted when autocorrecting short-form global variables like `$!`. ([@nevir][]) * [#566](https://github.com/bbatsov/rubocop/pull/566): Methods that just assign a splat to an ivar are no longer considered trivial writers. ([@nevir][]) * [#585](https://github.com/bbatsov/rubocop/pull/585): `MethodCallParentheses` should allow methods starting with uppercase letter. ([@bbatsov][]) * [#574](https://github.com/bbatsov/rubocop/issues/574): Fix error on multiple-assignment with non-array right hand side in `UselessSetterCall`. ([@yujinakayama][]) * [#576](https://github.com/bbatsov/rubocop/issues/576): Output config validation warning to STDERR so that it won't be mixed up with formatter's output. ([@yujinakayama][]) * [#599](https://github.com/bbatsov/rubocop/pull/599): `EndOfLine` cop is operational again. ([@jonas054][]) * [#604](https://github.com/bbatsov/rubocop/issues/604): Fix error on implicit match conditionals (e.g. `if /pattern/; end`) in `FavorModifier`. ([@yujinakayama][]) * [#600](https://github.com/bbatsov/rubocop/pull/600): Don't require an empty line for access modifiers at the beginning of class/module body. ([@bbatsov][]) * [#608](https://github.com/bbatsov/rubocop/pull/608): `RescueException` no longer crashes when the namespace of a rescued class is in a local variable. ([@jonas054][]) * [#173](https://github.com/bbatsov/rubocop/issues/173): Allow the use of `alias` in the body of an `instance_exec`. ([@bbatsov][]) * [#554](https://github.com/bbatsov/rubocop/issues/554): Handle properly multi-line arrays with comments in them in `WordArray`. ([@bbatsov][]) ## 0.14.1 (2013-10-10) ### New features * [#551](https://github.com/bbatsov/rubocop/pull/551): New cop `BracesAroundHashParameters` checks for braces in function calls with hash parameters. ([@dblock][]) * New cop `SpaceAfterNot` tracks redundant space after the `!` operator. ([@bbatsov][]) ### Bugs fixed * Fix bug concerning table and separator alignment of multi-line hash with multiple keys on the same line. ([@jonas054][]) * [#550](https://github.com/bbatsov/rubocop/pull/550): Fix a bug where `ClassLength` counted lines of inner classes/modules. ([@yujinakayama][]) * [#550](https://github.com/bbatsov/rubocop/pull/550): Fix a false positive for namespace class in `Documentation`. ([@yujinakayama][]) * [#556](https://github.com/bbatsov/rubocop/pull/556): Fix "Parser::Source::Range spans more than one line" bug in clang formatter. ([@yujinakayama][]) * [#552](https://github.com/bbatsov/rubocop/pull/552): `RaiseArgs` allows exception constructor calls with more than one 1 argument. ([@bbatsov][]) ## 0.14.0 (2013-10-07) ### New features * [#491](https://github.com/bbatsov/rubocop/issues/491): New cop `MethodCalledOnDoEndBlock` keeps track of methods called on `do`...`end` blocks. * [#456](https://github.com/bbatsov/rubocop/issues/456): New configuration parameter `AllCops`/`RunRailsCops` can be set to `true` for a project, removing the need to give the `-R`/`--rails` option with every invocation of `rubocop`. * [#501](https://github.com/bbatsov/rubocop/issues/501): `simple`/`clang`/`progress`/`emacs` formatters now print `[Corrected]` along with offence message when the offence is automatically corrected. * [#501](https://github.com/bbatsov/rubocop/issues/501): `simple`/`clang`/`progress` formatters now print count of auto-corrected offences in the final summary. * [#501](https://github.com/bbatsov/rubocop/issues/501): `json` formatter now outputs `corrected` key with boolean value in offence objects whether the offence is automatically corrected. * New cop `ClassLength` checks for overly long class definitions. * New cop `Debugger` checks for forgotten calls to debugger or pry. * New cop `RedundantException` checks for code like `raise RuntimeError, message`. * [#526](https://github.com/bbatsov/rubocop/issues/526): New cop `RaiseArgs` checks the args passed to `raise/fail`. ### Changes * Cop `MethodAndVariableSnakeCase` replaced by `MethodName` and `VariableName`, both having the configuration parameter `EnforcedStyle` with values `snake_case` (default) and `camelCase`. * [#519](https://github.com/bbatsov/rubocop/issues/519): `HashSyntax` cop is now configurable and can enforce the use of the classic hash rockets syntax. * [#520](https://github.com/bbatsov/rubocop/issues/520): `StringLiterals` cop is now configurable and can enforce either single-quoted or double-quoted strings. * [#528](https://github.com/bbatsov/rubocop/issues/528): Added a config option to `RedundantReturn` to allow a `return` with multiple values. * [#524](https://github.com/bbatsov/rubocop/issues/524): Added a config option to `Semicolon` to allow the use of `;` as an expression separator. * [#525](https://github.com/bbatsov/rubocop/issues/525): `SignalException` cop is now configurable and can enforce the semantic rule or an exclusive use of `raise` or `fail`. * `LambdaCall` is now configurable and enforce either `Proc#call` or `Proc#()`. * [#529](https://github.com/bbatsov/rubocop/issues/529): Added config option `EnforcedStyle` to `SpaceAroundBraces`. * [#529](https://github.com/bbatsov/rubocop/issues/529): Changed config option `NoSpaceBeforeBlockParameters` to `SpaceBeforeBlockParameters`. * Support Parser 2.0.0 (non-beta). ### Bugs fixed * [#514](https://github.com/bbatsov/rubocop/issues/514): Fix alignment of the hash containing different key lengths in one line. * [#496](https://github.com/bbatsov/rubocop/issues/496): Fix corner case crash in `AlignHash` cop: single key/value pair when configuration is `table` for '=>' and `separator` for `:`. * [#502](https://github.com/bbatsov/rubocop/issues/502): Don't check non-decimal literals with `NumericLiterals`. * [#448](https://github.com/bbatsov/rubocop/issues/448): Fix auto-correction of parameters spanning more than one line in `AlignParameters` cop. * [#493](https://github.com/bbatsov/rubocop/issues/493): Support disabling `Syntax` offences with `warning` severity. * Fix bug appearing when there were different values for the `AllCops`/`RunRailsCops` configuration parameter in different directories. * [#512](https://github.com/bbatsov/rubocop/issues/512): Fix bug causing crash in `AndOr` auto-correction. * [#515](https://github.com/bbatsov/rubocop/issues/515): Fix bug causing `AlignParameters` and `AlignArray` auto-correction to destroy code. * [#516](https://github.com/bbatsov/rubocop/issues/516): Fix bug causing `RedundantReturn` auto-correction to produce invalid code. * [#527](https://github.com/bbatsov/rubocop/issues/527): Handle `!=` expressions in `EvenOdd` cop. * `SignalException` cop now finds `raise` calls anywhere, not only in `begin` sections. * [#538](https://github.com/bbatsov/rubocop/issues/538): Fix bug causing `Blocks` auto-correction to produce invalid code. ## 0.13.1 (2013-09-19) ### New features * `HashSyntax` cop does auto-correction. * [#484](https://github.com/bbatsov/rubocop/pull/484): Allow calls to self to fix name clash with argument. * Renamed `SpaceAroundBraces` to `SpaceAroundBlockBraces`. * `SpaceAroundBlockBraces` now has a `NoSpaceBeforeBlockParameters` config option to enforce a style for blocks with parameters like `{|foo| puts }`. * New cop `LambdaCall` tracks uses of the obscure `lambda.(...)` syntax. ### Bugs fixed * Fix crash on empty input file in `FinalNewline`. * [#485](https://github.com/bbatsov/rubocop/issues/485): Fix crash on multiple-assignment and op-assignment in `UselessSetterCall`. * [#497](https://github.com/bbatsov/rubocop/issues/497): Fix crash in `UselessComparison` and `NilComparison`. ## 0.13.0 (2013-09-13) ### New features * New configuration parameter `AllowAdjacentOneLineDefs` for `EmptyLineBetweenDefs`. * New cop `MultilineBlockChain` keeps track of chained blocks spanning multiple lines. * `RedundantSelf` cop does auto-correction. * `AvoidPerlBackrefs` cop does auto-correction. * `AvoidPerlisms` cop does auto-correction. * `RedundantReturn` cop does auto-correction. * `Blocks` cop does auto-correction. * New cop `TrailingBlankLines` keeps track of extra blanks lines at the end of source file. * New cop `AlignHash` keeps track of bad alignment in multi-line hash literals. * New cop `AlignArray` keeps track of bad alignment in multi-line array literals. * New cop `SpaceBeforeModifierKeyword` keeps track of missing space before a modifier keyword (`if`, `unless`, `while`, `until`). * New cop `FinalNewline` keeps tracks of the required final newline in a source file. * Highlightling corrected in `SpaceInsideHashLiteralBraces` and `SpaceAroundBraces` cops. ### Changes * [#447](https://github.com/bbatsov/rubocop/issues/447): `BlockAlignment` cop now allows `end` to be aligned with the start of the line containing `do`. * `SymbolName` now has an `AllowDots` config option to allow symbols like `:'whatever.submit_button'`. * [#469](https://github.com/bbatsov/rubocop/issues/469): Extracted useless setter call tracking part of `UselessAssignment` cop to `UselessSetterCall`. * [#469](https://github.com/bbatsov/rubocop/issues/469): Merged `UnusedLocalVariable` cop into `UselessAssignment`. * [#458](https://github.com/bbatsov/rubocop/issues/458): The merged `UselessAssignment` cop now has advanced logic that tracks not only assignment at the end of the method but also every assignment in every scope. * [#466](https://github.com/bbatsov/rubocop/issues/466): Allow built-in JRuby global vars in `AvoidGlobalVars`. * Added a config option `AllowedVariables` to `AvoidGlobalVars` to allow users to whitelist certain global variables. * Renamed `AvoidGlobalVars` to `GlobalVars`. * Renamed `AvoidPerlisms` to `SpecialGlobalVars`. * Renamed `AvoidFor` to `For`. * Renamed `AvoidClassVars` to `ClassVars`. * Renamed `AvoidPerlBackrefs` to `PerlBackrefs`. * `NumericLiterals` now accepts a config param `MinDigits` - the minimal number of digits in the integer portion of number for the cop to check it. ### Bugs fixed * [#449](https://github.com/bbatsov/rubocop/issues/449): Remove whitespaces between condition and `do` with `WhileUntilDo` auto-correction. * Continue with file inspection after parser warnings. Give up only on syntax errors. * Don't trigger the HashSyntax cop on digit-starting keys. * Fix crashes while inspecting class definition subclassing another class stored in a local variable in `UselessAssignment` (formerly of `UnusedLocalVariable`) and `ShadowingOuterLocalVariable` (like `clazz = Array; class SomeClass < clazz; end`). * [#463](https://github.com/bbatsov/rubocop/issues/463): Do not warn if using destructuring in second `reduce` argument (`ReduceArguments`). ## 0.12.0 (2013-08-23) ### New features * [#439](https://github.com/bbatsov/rubocop/issues/439): Added formatter 'OffenceCount' which outputs a summary list of cops and their offence count. * [#395](https://github.com/bbatsov/rubocop/issues/395): Added `--show-cops` option to show available cops. * New cop `NilComparison` keeps track of comparisons like `== nil`. * New cop `EvenOdd` keeps track of occasions where `Fixnum#even?` or `Fixnum#odd?` should have been used (like `x % 2 == 0`). * New cop `IndentationWidth` checks for files using indentation that is not two spaces. * New cop `SpaceAfterMethodName` keeps track of method definitions with a space between the method name and the opening parenthesis. * New cop `ParenthesesAsGroupedExpression` keeps track of method calls with a space before the opening parenthesis. * New cop `HashMethods` keeps track of uses of deprecated `Hash` methods. * New Rails cop `HasAndBelongsToMany` checks for uses of `has_and_belongs_to_many`. * New Rails cop `ReadAttribute` tracks uses of `read_attribute`. * `Attr` cop does auto-correction. * `CollectionMethods` cop does auto-correction. * `SignalException` cop does auto-correction. * `EmptyLiteral` cop does auto-correction. * `MethodCallParentheses` cop does auto-correction. * `DefWithParentheses` cop does auto-correction. * `DefWithoutParentheses` cop does auto-correction. ### Changes * Dropped `-s`/`--silent` option. Now `progress`/`simple`/`clang` formatters always report summary and `emacs`/`files` formatters no longer report. * Dropped the `LineContinuation` cop. ### Bugs fixed * [#432](https://github.com/bbatsov/rubocop/issues/432): Fix false positive for constant assignments when rhs is a method call with block in `ConstantName`. * [#434](https://github.com/bbatsov/rubocop/issues/434): Support classes and modules defined with `Class.new`/`Module.new` in `AccessControl`. * Fix which ranges are highlighted in reports from IfUnlessModifier, WhileUntilModifier, and MethodAndVariableSnakeCase cop. * [#438](https://github.com/bbatsov/rubocop/issues/438): Accept setting attribute on method argument in `UselessAssignment`. ## 0.11.1 (2013-08-12) ### Changes * [#425](https://github.com/bbatsov/rubocop/issues/425): `ColonMethodCalls` now allows constructor methods (like `Nokogiri::HTML()` to be called with double colon. ### Bugs fixed * [#427](https://github.com/bbatsov/rubocop/issues/427): FavorUnlessOverNegatedIf triggered when using elsifs. * [#429](https://github.com/bbatsov/rubocop/issues/429): Fix `LeadingCommentSpace` offence reporting. * Fixed `AsciiComments` offence reporting. * Fixed `BlockComments` offence reporting. ## 0.11.0 (2013-08-09) ### New features * [#421](https://github.com/bbatsov/rubocop/issues/421): `TrivialAccessors` now ignores methods on user-configurable whitelist (such as `to_s` and `to_hash`). * [#369](https://github.com/bbatsov/rubocop/issues/369): New option `--auto-gen-config` outputs RuboCop configuration that disables all cops that detect any offences. * The list of annotation keywords recognized by the `CommentAnnotation` cop is now configurable. * Configuration file names are printed as they are loaded in `--debug` mode. * Auto-correct support added in `AlignParameters` cop. * New cop `UselessComparison` checks for comparisons of the same arguments. * New cop `UselessAssignment` checks for useless assignments to local variables. * New cop `SignalException` checks for proper usage of `fail` and `raise`. * New cop `ModuleFunction` checks for usage of `extend self` in modules. ### Bugs fixed * [#374](https://github.com/bbatsov/rubocop/issues/374): Fixed error at post condition loop (`begin-end-while`, `begin-end-until`) in `UnusedLocalVariable` and `ShadowingOuterLocalVariable`. * [#373](https://github.com/bbatsov/rubocop/issues/373) and [#376](https://github.com/bbatsov/rubocop/issues/376): Allow braces around multi-line blocks if `do`-`end` would change the meaning of the code. * `RedundantSelf` now allows `self.` followed by any ruby keyword. * [#391](https://github.com/bbatsov/rubocop/issues/391): Fix bug in counting slashes in a regexp. * [#394](https://github.com/bbatsov/rubocop/issues/394): `DotPosition` cop handles correctly code like `l.(1)`. * [#390](https://github.com/bbatsov/rubocop/issues/390): `CommentAnnotation` cop allows keywords (e.g. Review, Optimize) if they just begin a sentence. * [#400](https://github.com/bbatsov/rubocop/issues/400): Fix bug concerning nested defs in `EmptyLineBetweenDefs` cop. * [#399](https://github.com/bbatsov/rubocop/issues/399): Allow assignment inside blocks in `AssignmentInCondition` cop. * Fix bug in favor_modifier.rb regarding missed offences after else etc. * [#393](https://github.com/bbatsov/rubocop/issues/393): Retract support for multiline chaining of blocks (which fixed [#346](https://github.com/bbatsov/rubocop/issues/346)), thus rejecting issue 346. * [#389](https://github.com/bbatsov/rubocop/issues/389): Ignore symbols that are arguments to Module#private_constant in `SymbolName` cop. * [#387](https://github.com/bbatsov/rubocop/issues/387): Do autocorrect in `AndOr` cop only if it does not change the meaning of the code. * [#398](https://github.com/bbatsov/rubocop/issues/398): Don't display blank lines in the output of the clang formatter. * [#283](https://github.com/bbatsov/rubocop/issues/283): Refine `StringLiterals` string content check. ## 0.10.0 (2013-07-17) ### New features * New cop `RedundantReturn` tracks redundant `return`s in method bodies. * New cop `RedundantBegin` tracks redundant `begin` blocks in method definitions. * New cop `RedundantSelf` tracks redundant uses of `self`. * New cop `EmptyEnsure` tracks empty `ensure` blocks. * New cop `CommentAnnotation` tracks formatting of annotation comments such as TODO. * Added custom rake task. * New formatter `FileListFormatter` outputs just a list of files with offences in them (related to [#357](https://github.com/bbatsov/rubocop/issues/357)). ### Changes * `TrivialAccessors` now has an `ExactNameMatch` config option (related to [#308](https://github.com/bbatsov/rubocop/issues/308)). * `TrivialAccessors` now has an `ExcludePredicates` config option (related to [#326](https://github.com/bbatsov/rubocop/issues/326)). * Cops don't inherit from `Parser::AST::Rewriter` anymore. All 3rd party Cops should remove the call to `super` in their callbacks. If you implement your own processing you need to define the `#investigate` method instead of `#inspect`. Refer to the documentation of `Cop::Commissioner` and `Cop::Cop` classes for more information. * `EndAlignment` cop split into `EndAlignment` and `BlockAlignment` cops. ### Bugs fixed * [#288](https://github.com/bbatsov/rubocop/issues/288): Work with absolute Excludes paths internally (2nd fix for this issue). * `TrivialAccessors` now detects class attributes as well as instance attributes. * [#338](https://github.com/bbatsov/rubocop/issues/338): Fix end alignment of blocks in chained assignments. * [#345](https://github.com/bbatsov/rubocop/issues/345): Add `$SAFE` to the list of built-in global variables. * [#340](https://github.com/bbatsov/rubocop/issues/340): Override config parameters rather than merging them. * [#349](https://github.com/bbatsov/rubocop/issues/349): Fix false positive for `CharacterLiteral` (`%w(?)`). * [#346](https://github.com/bbatsov/rubocop/issues/346): Support method chains for block end alignment checks. * [#350](https://github.com/bbatsov/rubocop/issues/350): Support line breaks between variables on left hand side for block end alignment checks. * [#356](https://github.com/bbatsov/rubocop/issues/356): Allow safe assignment in `ParenthesesAroundCondition`. ### Misc * Improved performance on Ruby 1.9 by about 20%. * Improved overall performance by about 35%. ## 0.9.1 (2013-07-05) ### New features * Added `-l/--lint` option to allow doing only linting with no style checks (similar to running `ruby -wc`). ### Changes * Removed the `BlockAlignSchema` configuration option from `EndAlignment`. We now support only the default alignment schema - `StartOfAssignment`. * Made the preferred collection methods in `CollectionMethods` configurable. * Made the `DotPosition` cop configurable - now both `leading` and `trailing` styles are supported. ### Bugs fixed * [#318](https://github.com/bbatsov/rubocop/issues/318): Correct some special cases of block end alignment. * [#317](https://github.com/bbatsov/rubocop/issues/317): Fix a false positive in `LiteralInCondition`. * [#321](https://github.com/bbatsov/rubocop/issues/321): Ignore variables whose name start with `_` in `ShadowingOuterLocalVariable`. * [#322](https://github.com/bbatsov/rubocop/issues/322): Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting keyword splat argument. * [#316](https://github.com/bbatsov/rubocop/issues/316): Correct nested postfix unless in `MultilineIfThen`. * [#327](https://github.com/bbatsov/rubocop/issues/327): Fix false offences for block expression that span on two lines in `EndAlignment`. * [#332](https://github.com/bbatsov/rubocop/issues/332): Fix exception of `UnusedLocalVariable` and `ShadowingOuterLocalVariable` when inspecting named captures. * [#333](https://github.com/bbatsov/rubocop/issues/333): Fix a case that `EnsureReturn` throws an exception when ensure has no body. ## 0.9.0 (2013-07-01) ### New features * Introduced formatter feature, enables custom formatted output and multiple outputs. * Added progress formatter and now it's the default. (`--format progress`). * Added JSON formatter. (`--format json`). * Added clang style formatter showing the offending source. code. (`--format clang`). The `clang` formatter marks a whole range rather than just the starting position, to indicate more clearly where the problem is. * Added `-f`/`--format` option to specify formatter. * Added `-o`/`--out` option to specify output file for each formatter. * Added `-r/--require` option to inject external Ruby code into RuboCop. * Added `-V/--verbose-version` option that displays Parser version and Ruby version as well. * Added `-R/--rails` option that enables extra Rails-specific cops. * Added support for auto-correction of some offences with `-a`/`--auto-correct`. * New cop `CaseEquality` checks for explicit use of `===`. * New cop `AssignmentInCondition` checks for assignment in conditions. * New cop `EndAlignment` tracks misaligned `end` keywords. * New cop `Void` tracks uses of literals/variables/operators in possibly void context. * New cop `Documentation` checks for top level class/module doc comments. * New cop `UnreachableCode` tracks unreachable code segments. * New cop `MethodCallParentheses` tracks unwanted braces in method calls. * New cop `UnusedLocalVariable` tracks unused local variables for each scope. * New cop `ShadowingOuterLocalVariable` tracks use of the same name as outer local variables for block arguments or block local variables. * New cop `WhileUntilDo` tracks uses of `do` with multi-line `while/until`. * New cop `CharacterLiteral` tracks uses of character literals (`?x`). * New cop `EndInMethod` tracks uses of `END` in method definitions. * New cop `LiteralInCondition` tracks uses of literals in the conditions of `if/while/until`. * New cop `BeginBlock` tracks uses of `BEGIN` blocks. * New cop `EndBlock` tracks uses of `END` blocks. * New cop `DotPosition` tracks the dot position in multi-line method calls. * New cop `Attr` tracks uses of `Module#attr`. * Add support for auto-correction of some offences with `-a`/`--auto-correct`. ### Changes * Deprecated `-e`/`--emacs` option. (Use `--format emacs` instead). * Made `progress` formatter the default. * Most formatters (`progress`, `simple` and `clang`) now print relative file paths if the paths are under the current working directory. * Migrate all cops to new namespaces. `Rubocop::Cop::Lint` is for cops that emit warnings. `Rubocop::Cop::Style` is for cops that do not belong in other namespaces. * Merge `FavorPercentR` and `PercentR` into one cop called `RegexpLiteral`, and add configuration parameter `MaxSlashes`. * Add `CountKeywordArgs` configuration option to `ParameterLists` cop. ### Bugs fixed * [#239](https://github.com/bbatsov/rubocop/issues/239): Fixed double quotes false positives. * [#233](https://github.com/bbatsov/rubocop/issues/233): Report syntax cop offences. * Fix off-by-one error in favor_modifier. * [#229](https://github.com/bbatsov/rubocop/issues/229): Recognize a line with CR+LF as a blank line in AccessControl cop. * [#235](https://github.com/bbatsov/rubocop/issues/235): Handle multiple constant assignment in ConstantName cop. * [#246](https://github.com/bbatsov/rubocop/issues/246): Correct handling of unicode escapes within double quotes. * Fix crashes in Blocks, CaseEquality, CaseIndentation, ClassAndModuleCamelCase, ClassMethods, CollectionMethods, and ColonMethodCall. * [#263](https://github.com/bbatsov/rubocop/issues/263): Do not check for space around operators called with method syntax. * [#271](https://github.com/bbatsov/rubocop/issues/271): Always allow line breaks inside hash literal braces. * [#270](https://github.com/bbatsov/rubocop/issues/270): Fixed a false positive in ParenthesesAroundCondition. * [#288](https://github.com/bbatsov/rubocop/issues/288): Get config parameter AllCops/Excludes from highest config file in path. * [#276](https://github.com/bbatsov/rubocop/issues/276): Let columns start at 1 instead of 0 in all output of column numbers. * [#292](https://github.com/bbatsov/rubocop/issues/292): Don't check non-regular files (like sockets, etc). * Fix crashes in WordArray on arrays of character literals such as `[?\r, ?\n]`. * Fix crashes in Documentation on empty modules. ## 0.8.3 (2013-06-18) ### Bug fixes * Lock Parser dependency to version 2.0.0.beta5. ## 0.8.2 (2013-06-05) ### New features * New cop `BlockNesting` checks for excessive block nesting. ### Bug fixes * Correct calculation of whether a modifier version of a conditional statement will fit. * Fix an error in `MultilineIfThen` cop that occurred in some special cases. * [#231](https://github.com/bbatsov/rubocop/issues/231): Fix a false positive for modifier if. ## 0.8.1 (2013-05-30) ### New features * New cop `Proc` tracks uses of `Proc.new`. ### Changes * Renamed `NewLambdaLiteral` to `Lambda`. * Aligned the `Lambda` cop more closely to the style guide - it now allows the use of `lambda` for multi-line blocks. ### Bugs fixed * [#210](https://github.com/bbatsov/rubocop/issues/210): Fix a false positive for double quotes in regexp literals. * [#211](https://github.com/bbatsov/rubocop/issues/211): Fix a false positive for `initialize` method looking like a trivial writer. * [#215](https://github.com/bbatsov/rubocop/issues/215): Fixed a lot of modifier `if/unless/while/until` issues. * [#213](https://github.com/bbatsov/rubocop/issues/213): Make sure even disabled cops get their configuration set. * [#214](https://github.com/bbatsov/rubocop/issues/214): Fix SpaceInsideHashLiteralBraces to handle string interpolation right. ## 0.8.0 (2013-05-28) ### Changes * Folded `ArrayLiteral` and `HashLiteral` into `EmptyLiteral` cop. * The maximum number of params `ParameterLists` accepts in now configurable. * Reworked `SymbolSnakeCase` into `SymbolName`, which has an option `AllowCamelCase` enabled by default. * Migrated from `Ripper` to the portable [Parser](https://github.com/whitequark/parser). ### New features * New cop `ConstantName` checks for constant which are not using `SCREAMING_SNAKE_CASE`. * New cop `AccessControl` checks private/protected indentation and surrounding blank lines. * New cop `Loop` checks for `begin/end/while(until)` and suggests the use of `Kernel#loop`. ## 0.7.2 (2013-05-13) ### Bugs fixed * [#155](https://github.com/bbatsov/rubocop/issues/155): 'Do not use semicolons to terminate expressions.' is not implemented correctly. * `OpMethod` now handles definition of unary operators without crashing. * `SymbolSnakeCase` now handles aliasing of operators without crashing. * `RescueException` now handles the splat operator `*` in a `rescue` clause without crashing. * [#159](https://github.com/bbatsov/rubocop/issues/159): AvoidFor cop misses many violations. ## 0.7.1 (2013-05-11) ### Bugs fixed * Added missing files to the gemspec. ## 0.7.0 (2013-05-11) ### New features * Added ability to include or exclude files/directories through `.rubocop.yml`. * Added option --only for running a single cop. * Relax semicolon rule for one line methods, classes and modules. * Configuration files, such as `.rubocop.yml`, can now include configuration from other files through the `inherit_from` directive. All configuration files implicitly inherit from `config/default.yml`. * New cop `ClassMethods` checks for uses for class/module names in definitions of class/module methods. * New cop `SingleLineMethods` checks for methods implemented on a single line. * New cop `FavorJoin` checks for usages of `Array#*` with a string argument. * New cop `BlockComments` tracks uses of block comments(`=begin/=end` comments). * New cop `EmptyLines` tracks consecutive blank lines. * New cop `WordArray` tracks arrays of words. * [#108](https://github.com/bbatsov/rubocop/issues/108): New cop `SpaceInsideHashLiteralBraces` checks for spaces inside hash literal braces - style is configurable. * New cop `LineContinuation` tracks uses of the line continuation character (`\`). * New cop `SymbolArray` tracks arrays of symbols. * Print warnings for unrecognized names in configuration files. * New cop `TrivialAccessors` tracks method definitions that could be automatically generated with `attr_*` methods. * New cop `LeadingCommentSpace` checks for missing space after `#` in comments. * New cop `ColonMethodCall` tracks uses of `::` for method calls. * New cop `AvoidGlobalVars` tracks uses of non built-in global variables. * New cop `SpaceAfterControlKeyword` tracks missing spaces after `if/elsif/case/when/until/unless/while`. * New cop `Not` tracks uses of the `not` keyword. * New cop `Eval` tracks uses of the `eval` function. ### Bugs fixed * [#101](https://github.com/bbatsov/rubocop/issues/101): `SpaceAroundEqualsInParameterDefault` doesn't work properly with empty string. * Fix `BraceAfterPercent` for `%W`, `%i` and `%I` and added more tests. * Fix a false positive in the `Alias` cop. `:alias` is no longer treated as keyword. * `ArrayLiteral` now properly detects `Array.new`. * `HashLiteral` now properly detects `Hash.new`. * `VariableInterpolation` now detects regexp back references and doesn't crash. * Don't generate pathnames like some/project//some.rb. * [#151](https://github.com/bbatsov/rubocop/issues/151): Don't print the unrecognized cop warning several times for the same `.rubocop.yml`. ### Misc * Renamed `Indentation` cop to `CaseIndentation` to avoid confusion. * Renamed `EmptyLines` cop to `EmptyLineBetweenDefs` to avoid confusion. ## 0.6.1 (2013-04-28) ### New features * Split `AsciiIdentifiersAndComments` cop in two separate cops. ### Bugs fixed * [#90](https://github.com/bbatsov/rubocop/issues/90): Two cops crash when scanning code using `super`. * [#93](https://github.com/bbatsov/rubocop/issues/93): Issue with `whitespace?': undefined method`. * [#97](https://github.com/bbatsov/rubocop/issues/97): Build fails. * [#100](https://github.com/bbatsov/rubocop/issues/100): `OpMethod` cop doesn't work if method arg is not in braces. * `SymbolSnakeCase` now tracks Ruby 1.9 hash labels as well as regular symbols. ### Misc * [#88](https://github.com/bbatsov/rubocop/issues/88): Abort gracefully when interrupted with Ctrl-C. * No longer crashes on bugs within cops. Now problematic checks are skipped and a message is displayed. * Replaced `Term::ANSIColor` with `Rainbow`. * Add an option to disable colors in the output. * Cop names are now displayed alongside messages when `-d/--debug` is passed. ## 0.6.0 (2013-04-23) ### New features * New cop `ReduceArguments` tracks argument names in reduce calls. * New cop `MethodLength` tracks number of LOC (lines of code) in methods. * New cop `RescueModifier` tracks uses of `rescue` in modifier form. * New cop `PercentLiterals` tracks uses of `%q`, `%Q`, `%s` and `%x`. * New cop `BraceAfterPercent` tracks uses of % literals with delimiters other than (). * Support for disabling cops locally in a file with rubocop:disable comments. * New cop `EnsureReturn` tracks usages of `return` in `ensure` blocks. * New cop `HandleExceptions` tracks suppressed exceptions. * New cop `AsciiIdentifiersAndComments` tracks uses of non-ascii characters in identifiers and comments. * New cop `RescueException` tracks uses of rescuing the `Exception` class. * New cop `ArrayLiteral` tracks uses of Array.new. * New cop `HashLiteral` tracks uses of Hash.new. * New cop `OpMethod` tracks the argument name in operator methods. * New cop `PercentR` tracks uses of %r literals with zero or one slash in the regexp. * New cop `FavorPercentR` tracks uses of // literals with more than one slash in the regexp. ### Bugs fixed * [#62](https://github.com/bbatsov/rubocop/issues/62): Config files in ancestor directories are ignored if another exists in home directory. * [#65](https://github.com/bbatsov/rubocop/issues/65): Suggests to convert symbols `:==`, `:<=>` and the like to snake_case. * [#66](https://github.com/bbatsov/rubocop/issues/66): Does not crash on unreadable or unparseable files. * [#70](https://github.com/bbatsov/rubocop/issues/70): Support `alias` with bareword arguments. * [#64](https://github.com/bbatsov/rubocop/issues/64): Performance issue with Bundler. * [#75](https://github.com/bbatsov/rubocop/issues/75): Make it clear that some global variables require the use of the English library. * [#79](https://github.com/bbatsov/rubocop/issues/79): Ternary operator missing whitespace detection. ### Misc * Dropped Jeweler for gem release management since it's no longer actively maintained. * Handle pluralization properly in the final summary. ## 0.5.0 (2013-04-17) ### New features * New cop `FavorSprintf` that checks for usages of `String#%`. * New cop `Semicolon` that checks for usages of `;` as expression separator. * New cop `VariableInterpolation` that checks for variable interpolation in double quoted strings. * New cop `Alias` that checks for uses of the keyword `alias`. * Automatically detect extensionless Ruby files with shebangs when search for Ruby source files in a directory. ### Bugs fixed * [#59](https://github.com/bbatsov/rubocop/issues/59): Interpolated variables not enclosed in braces are not noticed. * [#42](https://github.com/bbatsov/rubocop/issues/42): Received malformed format string ArgumentError from rubocop. [@bbatsov]: https://github.com/bbatsov [@jonas054]: https://github.com/jonas054 [@yujinakayama]: https://github.com/yujinakayama [@dblock]: https://github.com/dblock [@nevir]: https://github.com/nevir [@daviddavis]: https://github.com/daviddavis [@sds]: https://github.com/sds [@fancyremarker]: https://github.com/fancyremarker [@sinisterchipmunk]: https://github.com/sinisterchipmunk [@vonTronje]: https://github.com/vonTronje [@agrimm]: https://github.com/agrimm [@pmenglund]: https://github.com/pmenglund [@chulkilee]: https://github.com/chulkilee [@codez]: https://github.com/codez [@cyberdelia]: https://github.com/cyberdelia [@emou]: https://github.com/emou [@skanev]: http://github.com/skanev [@claco]: http://github.com/claco [@rifraf]: http://github.com/rifraf [@scottmatthewman]: https://github.com/scottmatthewman [@ma2gedev]: http://github.com/ma2gedev [@jeremyolliver]: https://github.com/jeremyolliver [@hannestyden]: https://github.com/hannestyden [@geniou]: https://github.com/geniou [@jkogara]: https://github.com/jkogara [@tmorris-fiksu]: https://github.com/tmorris-fiksu [@mockdeep]: https://github.com/mockdeep [@hiroponz]: https://github.com/hiroponz [@tamird]: https://github.com/tamird [@fshowalter]: https://github.com/fshowalter [@cschramm]: https://github.com/cschramm [@bquorning]: https://github.com/bquorning [@bcobb]: https://github.com/bcobb [@irrationalfab]: https://github.com/irrationalfab [@tommeier]: https://github.com/tommeier [@sfeldon]: https://github.com/sfeldon [@biinari]: https://github.com/biinari [@barunio]: https://github.com/barunio [@molawson]: https://github.com/molawson [@wndhydrnt]: https://github.com/wndhydrnt [@ggilder]: https://github.com/ggilder [@salbertson]: https://github.com/salbertson [@camilleldn]: https://github.com/camilleldn [@mcls]: https://github.com/mcls [@yous]: https://github.com/yous [@vrthra]: https://github.com/vrthra [@SkuliOskarsson]: https://github.com/SkuliOskarsson [@jspanjers]: https://github.com/jspanjers [@sch1zo]: https://github.com/sch1zo [@smangelsdorf]: https://github.com/smangelsdorf [@mvz]: https://github.com/mvz [@jfelchner]: https://github.com/jfelchner [@janraasch]: https://github.com/janraasch [@jcarbo]: https://github.com/jcarbo [@oneamtu]: https://github.com/oneamtu [@toy]: https://github.com/toy [@Koronen]: https://github.com/Koronen [@blainesch]: https://github.com/blainesch [@marxarelli]: https://github.com/marxarelli [@katieschilling]: https://github.com/katieschilling [@kakutani]: https://github.com/kakutani [@rrosenblum]: https://github.com/rrosenblum [@mattjmcnaughton]: https://github.com/mattjmcnaughton [@huerlisi]: https://github.com/huerlisi [@volkert]: https://github.com/volkert [@lumeet]: https://github.com/lumeet [@mmozuras]: https://github.com/mmozuras [@d4rk5eed]: https://github.com/d4rk5eed [@cshaffer]: https://github.com/cshaffer [@eitoball]: https://github.com/eitoball [@iainbeeston]: https://github.com/iainbeeston [@pimterry]: https://github.com/pimterry [@palkan]: https://github.com/palkan [@jdoconnor]: https://github.com/jdoconnor [@meganemura]: https://github.com/meganemura [@zvkemp]: https://github.com/zvkemp [@vassilevsky]: https://github.com/vassilevsky [@gerry3]: https://github.com/gerry3 [@ypresto]: https://github.com/ypresto [@clowder]: https://github.com/clowder [@mudge]: https://github.com/mudge [@mzp]: https://github.com/mzp [@bankair]: https://github.com/bankair [@crimsonknave]: https://github.com/crimsonknave [@renuo]: https://github.com/renuo [@sdeframond]: https://github.com/sdeframond [@til]: https://github.com/til [@carhartl]: https://github.com/carhartl [@dylandavidson]: https://github.com/dylandavidson [@tmr08c]: https://github.com/tmr08c [@hbd225]: https://github.com/hbd225 [@l8nite]: https://github.com/l8nite [@sumeet]: https://github.com/sumeet [@ojab]: https://github.com/ojab [@chastell]: https://github.com/chastell [@glasnt]: https://github.com/glasnt [@crazydog115]: https://github.com/crazydog115 [@RGBD]: https://github.com/RGBD [@panthomakos]: https://github.com/panthomakos [@matugm]: https://github.com/matugm [@m1foley]: https://github.com/m1foley [@tejasbubane]: https://github.com/tejasbubane [@bmorrall]: https://github.com/bmorrall [@fphilipe]: https://github.com/fphilipe [@gotrevor]: https://github.com/gotrevor [@awwaiid]: https://github.com/awwaiid [@segiddins]: https://github.com/segiddins [@urbanautomaton]: https://github.com/urbanautomaton.com [@unmanbearpig]: https://github.com/unmanbearpig [@maxjacobson]: https://github.com/maxjacobson [@sliuu]: https://github.com/sliuu [@edmz]: https://github.com/edmz [@syndbg]: https://github.com/syndbg [@wli]: https://github.com/wli [@caseywebdev]: https://github.com/caseywebdev [@MGerrior]: https://github.com/MGerrior [@imtayadeway]: https://github.com/imtayadeway [@mrfoto]: https://github.com/mrfoto [@karreiro]: https://github.com/karreiro [@dreyks]: https://github.com/dreyks [@hmadison]: https://github.com/hmadison [@miquella]: https://github.com/miquella [@jhansche]: https://github.com/jhansche [@cornelius]: https://github.com/cornelius [@eagletmt]: https://github.com/eagletmt [@apiology]: https://github.com/apiology [@alexdowad]: https://github.com/alexdowad [@minustehbare]: https://github.com/minustehbare [@tansaku]: https://github.com/tansaku [@ptrippett]: https://github.com/ptrippett [@br3nda]: https://github.com/br3nda [@jujugrrr]: https://github.com/jujugrrr [@sometimesfood]: https://github.com/sometimesfood [@cgriego]: https://github.com/cgriego [@savef]: https://github.com/savef [@volmer]: https://github.com/volmer [@domcleal]: https://github.com/domcleal [@codebeige]: https://github.com/codebeige [@weh]: https://github.com/weh [@bfontaine]: https://github.com/bfontaine [@jawshooah]: https://github.com/jawshooah [@DNNX]: https://github.com/DNNX [@mvidner]: https://github.com/mvidner [@mattparlane]: https://github.com/mattparlane [@drenmi]: https://github.com/drenmi [@georgyangelov]: https://github.com/georgyangelov [@owst]: https://github.com/owst [@seikichi]: https://github.com/seikichi [@madwort]: https://github.com/madwort [@annih]: https://github.com/annih [@mmcguinn]: https://github.com/mmcguinn [@pocke]: https://github.com/pocke [@prsimp]: https://github.com/prsimp [@ptarjan]: https://github.com/ptarjan [@jweir]: https://github.com/jweir [@Fryguy]: https://github.com/Fryguy [@mikegee]: https://github.com/mikegee [@tbrisker]: https://github.com/tbrisker [@necojackarc]: https://github.com/necojackarc [@laurelfan]: https://github.com/laurelfan [@amuino]: https://github.com/amuino [@dylanahsmith]: https://github.com/dylanahsmith [@gerrywastaken]: https://github.com/gerrywastaken [@bolshakov]: https://github.com/bolshakov [@jastkand]: https://github.com/jastkand [@graemeboy]: https://github.com/graemeboy [@akihiro17]: https://github.com/akihiro17 [@magni-]: https://github.com/magni- [@NobodysNightmare]: https://github.com/NobodysNightmare [@gylaz]: https://github.com/gylaz [@tjwp]: https://github.com/tjwp [@neodelf]: https://github.com/neodelf [@josh]: https://github.com/josh [@natalzia-paperless]: https://github.com/natalzia-paperless [@jules2689]: https://github.com/jules2689 [@giannileggio]: https://github.com/giannileggio [@deivid-rodriguez]: https://github.com/deivid-rodriguez [@pclalv]: https://github.com/pclalv [@flexoid]: https://github.com/flexoid [@sgringwe]: https://github.com/sgringwe [@Tei]: https://github.com/Tei [@haziqhafizuddin]: https://github.com/haziqhafizuddin [@dvandersluis]: https://github.com/dvandersluis [@QuinnHarris]: https://github.com/QuinnHarris [@sooyang]: https://github.com/sooyang [@metcalf]: https://github.com/metcalf [@annaswims]: https://github.com/annaswims [@soutaro]: https://github.com/soutaro [@nicklamuro]: https://github.com/nicklamuro [@mikezter]: https://github.com/mikezter [@joejuzl]: https://github.com/joejuzl [@hedgesky]: https://github.com/hedgesky [@tjwallace]: https://github.com/tjwallace [@scottohara]: https://github.com/scottohara [@koic]: https://github.com/koic [@groddeck]: https://github.com/groddeck [@b-t-g]: https://github.com/b-t-g [@coorasse]: https://github.com/coorasse [@scottmatthewman]: https://github.com/scottmatthewman [@tcdowney]: https://github.com/tcdowney [@logicminds]: https://github.com/logicminds [@abrom]: https://github.com/abrom [@thegedge]: https://github.com/thegedge [@jmks]: https://github.com/jmks/ [@connorjacobsen]: https://github.com/connorjacobsen [@legendetm]: https://github.com/legendetm [@bronson]: https://github.com/bronson [@albus522]: https://github.com/albus522 [@sihu]: https://github.com/sihu [@kamaradclimber]: https://github.com/kamaradclimber [@swcraig]: https://github.com/swcraig [@jessieay]: https://github.com/jessieay [@tiagocasanovapt]: https://github.com/tiagocasanovapt [@iGEL]: https://github.com/iGEL [@tessi]: https://github.com/tessi [@ivanovaleksey]: https://github.com/ivanovaleksey [@Ana06]: https://github.com/Ana06 [@aroben]: https://github.com/aroben [@olliebennett]: https://github.com/olliebennett [@aesthetikx]: https://github.com/aesthetikx [@tdeo]: https://github.com/tdeo [@AlexWayfer]: https://github.com/AlexWayfer [@amogil]: https://github.com/amogil [@kevindew]: https://github.com/kevindew [@lucasuyezu]: https://github.com/lucasuyezu [@breckenedge]: https://github.com/breckenedge [@enriikke]: https://github.com/enriikke [@iguchi1124]: https://github.com/iguchi1124 [@vergenzt]: https://github.com/vergenzt [@rahulcs]: https://github.com/rahulcs [@dominh]: https://github.com/dominh [@sue445]: https://github.com/sue445 [@zverok]: https://github.com/zverok [@backus]: https://github.com/backus [@pat]: https://github.com/pat [@sinsoku]: https://github.com/sinsoku [@nodo]: https://github.com/nodo [@onk]: https://github.com/onk [@dabroz]: https://github.com/dabroz [@buenaventure]: https://github.com/buenaventure [@dorian]: https://github.com/dorian [@attilahorvath]: https://github.com/attilahorvath [@droptheplot]: https://github.com/droptheplot [@wkurniawan07]: https://github.com/wkurniawan07 [@kddeisz]: https://github.com/kddeisz [@ota42y]: https://github.com/ota42y [@smakagon]: https://github.com/smakagon [@musialik]: https://github.com/musialik [@twe4ked]: https://github.com/twe4ked [@maxbeizer]: https://github.com/maxbeizer [@andriymosin]: https://github.com/andriymosin [@brandonweiss]: https://github.com/brandonweiss [@betesh]: https://github.com/betesh [@dpostorivo]: https://github.com/dpostorivo [@konto-andrzeja]: https://github.com/konto-andrzeja [@sadovnik]: https://github.com/sadovnik [@cjlarose]: https://github.com/cjlarose [@alpaca-tc]: https://github.com/alpaca-tc [@ilansh]: https://github.com/ilansh [@mclark]: https://github.com/mclark [@klesse413]: https://github.com/klesse413 [@gprado]: https://github.com/gprado [@yhirano55]: https://github.com/yhirano55 [@hoshinotsuyoshi]: https://github.com/hoshinotsuyoshi [@timrogers]: https://github.com/timrogers [@harold-s]: https://github.com/harold-s [@daniloisr]: https://github.com/daniloisr [@promisedlandt]: https://github.com/promisedlandt [@oboxodo]: https://github.com/oboxodo [@gohdaniel15]: https://github.com/gohdaniel15 [@barthez]: https://github.com/barthez [@Envek]: https://github.com/Envek [@petehamilton]: https://github.com/petehamilton [@donjar]: https://github.com/donjar [@highb]: https://github.com/highb [@JoeCohen]: https://github.com/JoeCohen [@theRealNG]: https://github.com/theRealNG [@akhramov]: https://github.com/akhramov [@jekuta]: https://github.com/jekuta [@fujimura]: https://github.com/fujimura [@kristjan]: https://github.com/kristjan [@frodsan]: https://github.com/frodsan [@erikdstock]: https://github.com/erikdstock [@GauthamGoli]: https://github.com/GauthamGoli [@nelsonjr]: https://github.com/nelsonjr [@jonatas]: https://github.com/jonatas [@jaredbeck]: https://www.jaredbeck.com [@michniewicz]: https://github.com/michniewicz [@bgeuken]: https://github.com/bgeuken [@mtsmfm]: https://github.com/mtsmfm [@bdewater]: https://github.com/bdewater [@garettarrowood]: https://github.com/garettarrowood [@sambostock]: https://github.com/sambostock [@asherkach]: https://github.com/asherkach [@tiagotex]: https://github.com/tiagotex [@wata727]: https://github.com/wata727 [@marcandre]: https://github.com/marcandre [@walf443]: https://github.com/walf443 [@reitermarkus]: https://github.com/reitermarkus [@chrishulton]: https://github.com/chrishulton [@siggymcfried]: https://github.com/siggymcfried [@melch]: https://github.com/melch [@nattfodd]: https://github.com/nattfodd [@nattfodd]: https://github.com/nattfodd [@melch]: https://github.com/melch [@flyerhzm]: https://github.com/flyerhzm [@ybiquitous]: https://github.com/ybiquitous rubocop-0.52.1/CONTRIBUTING.md000066400000000000000000000064151322072016200155020ustar00rootroot00000000000000# Contributing If you discover issues, have ideas for improvements or new features, please report them to the [issue tracker][1] of the repository or submit a pull request. Please, try to follow these guidelines when you do so. ## Issue reporting * Check that the issue has not already been reported. * Check that the issue has not already been fixed in the latest code (a.k.a. `master`). * Be clear, concise and precise in your description of the problem. * Open an issue with a descriptive title and a summary in grammatically correct, complete sentences. * Include the output of `rubocop -V`: ``` $ rubocop -V 0.50.0 (using Parser 2.4.0.0, running on ruby 2.4.2 x86_64-linux) ``` * Include any relevant code to the issue summary. ## Pull requests * Read [how to properly contribute to open source projects on GitHub][2]. * Fork the project. * Use a topic/feature branch to easily amend a pull request later, if necessary. * Write [good commit messages][3]. * Use the same coding conventions as the rest of the project. * Commit and push until you are happy with your contribution. * If your change has a corresponding open GitHub issue, prefix the commit message with `[Fix #github-issue-number]`. * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally. * Add an entry to the [Changelog](CHANGELOG.md) accordingly. See [changelog entry format](#changelog-entry-format). * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it. * Make sure the test suite is passing and the code you wrote doesn't produce RuboCop offenses (usually this is as simple as running `bundle exec rake`). * [Squash related commits together][5]. * Open a [pull request][4] that relates to *only* one subject with a clear title and description in grammatically correct, complete sentences. ### Changelog entry format Here are a few examples: ``` * [#716](https://github.com/bbatsov/rubocop/issues/716): Fixed a regression in the auto-correction logic of `MethodDefParentheses`. ([@bbatsov][]) * New cop `ElseLayout` checks for odd arrangement of code in the `else` branch of a conditional expression. ([@bbatsov][]) ``` * Mark it up in [Markdown syntax][6]. * The entry line should start with `* ` (an asterisk and a space). * If the change has a related GitHub issue (e.g. a bug fix for a reported issue), put a link to the issue as `[#123](https://github.com/bbatsov/rubocop/issues/123): `. * Describe the brief of the change. The sentence should end with a punctuation. * At the end of the entry, add an implicit link to your GitHub user page as `([@username][])`. * If this is your first contribution to RuboCop project, add a link definition for the implicit link to the bottom of the changelog as `[@username]: https://github.com/username`. [1]: https://github.com/bbatsov/rubocop/issues [2]: http://gun.io/blog/how-to-github-fork-branch-and-pull-request [3]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html [4]: https://help.github.com/articles/using-pull-requests [5]: http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html [6]: http://daringfireball.net/projects/markdown/syntax rubocop-0.52.1/Gemfile000066400000000000000000000010261322072016200145350ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec gem 'bump', require: false gem 'pry' gem 'rake', '~> 12.0' gem 'rspec', '~> 3.7' gem 'rubocop-rspec', '~> 1.20.0' gem 'simplecov', '~> 0.10' gem 'test-queue' gem 'yard', '~> 0.9' group :test do gem 'codeclimate-test-reporter', '~> 1.0', require: false gem 'public_suffix', '~> 2.0', require: false gem 'safe_yaml', require: false gem 'webmock', require: false end local_gemfile = 'Gemfile.local' eval_gemfile local_gemfile if File.exist?(local_gemfile) rubocop-0.52.1/LICENSE.txt000066400000000000000000000020461322072016200150700ustar00rootroot00000000000000Copyright (c) 2012-17 Bozhidar Batsov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rubocop-0.52.1/README.md000066400000000000000000000354251322072016200145330ustar00rootroot00000000000000[![Gem Version](https://badge.fury.io/rb/rubocop.svg)](http://badge.fury.io/rb/rubocop) [![Dependency Status](https://gemnasium.com/bbatsov/rubocop.svg)](https://gemnasium.com/bbatsov/rubocop) [![Travis Status](https://travis-ci.org/bbatsov/rubocop.svg?branch=master)](https://travis-ci.org/bbatsov/rubocop) [![Appveyor status](https://ci.appveyor.com/api/projects/status/e5jdwocv30oqm4sm?svg=true)](https://ci.appveyor.com/project/bbatsov/rubocop) [![Coverage Status](https://img.shields.io/codeclimate/coverage/github/bbatsov/rubocop.svg)](https://codeclimate.com/github/bbatsov/rubocop) [![Code Climate](https://codeclimate.com/github/bbatsov/rubocop/badges/gpa.svg)](https://codeclimate.com/github/bbatsov/rubocop) [![Inline docs](http://inch-ci.org/github/bbatsov/rubocop.svg)](http://inch-ci.org/github/bbatsov/rubocop) [![Patreon](https://img.shields.io/badge/patreon-donate-orange.svg)](https://www.patreon.com/bbatsov) [![Liberapay](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/bbatsov/donate) [![OpenCollective](https://opencollective.com/rubocop/backers/badge.svg)](#open-collective-backers) [![OpenCollective](https://opencollective.com/rubocop/sponsors/badge.svg)](#open-collective-sponsors)

RuboCop Logo

> Role models are important.
> -- Officer Alex J. Murphy / RoboCop **RuboCop** is a Ruby static code analyzer. Out of the box it will enforce many of the guidelines outlined in the community [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide). Most aspects of its behavior can be tweaked via various [configuration options](https://github.com/bbatsov/rubocop/blob/master/config/default.yml). Apart from reporting problems in your code, RuboCop can also automatically fix some of the problems for you. [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bbatsov/rubocop?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) **Please consider [supporting financially its ongoing development](#funding).** ## Installation **RuboCop**'s installation is pretty standard: ```sh $ gem install rubocop ``` If you'd rather install RuboCop using `bundler`, don't require it in your `Gemfile`: ```rb gem 'rubocop', require: false ``` RuboCop's development is moving at a very rapid pace and there are often backward-incompatible changes between minor releases (since we haven't reached version 1.0 yet). To prevent an unwanted RuboCop update you might want to use a conservative version locking in your `Gemfile`: ```rb gem 'rubocop', '~> 0.52.1', require: false ``` ## Quickstart Just type `rubocop` in a Ruby project's folder and watch the magic happen. ``` $ cd my/cool/ruby/project $ rubocop ``` ## Official manual You can read a ton more about RuboCop in its [official manual](http://rubocop.readthedocs.io). ## Compatibility RuboCop supports the following Ruby implementations: * MRI 2.1+ * JRuby 9.0+ ## Team Here's a list of RuboCop's core developers: * [Bozhidar Batsov](https://github.com/bbatsov) * [Jonas Arvidsson](https://github.com/jonas054) * [Yuji Nakayama](https://github.com/yujinakayama) * [Evgeni Dzhelyov](https://github.com/edzhelyov) (retired) * [Ted Johansson](https://github.com/drenmi) * [Masataka Kuwabara](https://github.com/pocke) ## Logo RuboCop's logo was created by [Dimiter Petrov](https://www.chadomoto.com/). You can find the logo in various formats [here](https://github.com/bbatsov/rubocop/tree/master/logo). The logo is licensed under a [Creative Commons Attribution-NonCommercial 4.0 International License](http://creativecommons.org/licenses/by-nc/4.0/deed.en_GB). ## Contributors Here's a [list](https://github.com/bbatsov/rubocop/graphs/contributors) of all the people who have contributed to the development of RuboCop. I'm extremely grateful to each and every one of them! If you'd like to contribute to RuboCop, please take the time to go through our short [contribution guidelines](CONTRIBUTING.md). Converting more of the Ruby Style Guide into RuboCop cops is our top priority right now. Writing a new cop is a great way to dive into RuboCop! Of course, bug reports and suggestions for improvements are always welcome. GitHub pull requests are even better! :-) ## Funding While RuboCop is free software and will always be, the project would benefit immensely from some funding. Raising a monthly budget of a couple of thousand dollars would make it possible to pay people to work on certain complex features, fund other development related stuff (e.g. hardware, conference trips) and so on. Raising a monthly budget of over $5000 would open the possibility of someone working full-time on the project which would speed up the pace of development significantly. We welcome both individual and corporate sponsors! We also offer a wide array of funding channels to account for your preferences (although currently [Open Collective](https://opencollective.com/rubocop) is our preferred funding platform). If you're working in a company that's making significant use of RuboCop we'd appreciate it if you suggest to your company to become a RuboCop sponsor. You can support the development of RuboCop via [Salt](https://salt.bountysource.com/teams/rubocop), [Patreon](https://www.patreon.com/bbatsov), [Liberapay](https://liberapay.com/bbatsov/donate), and [Open Collective](https://opencollective.com/rubocop). ### Open Collective Backers Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/rubocop#backer)] ### Open Collective Sponsors Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/rubocop#sponsor)] ## Changelog RuboCop's changelog is available [here](CHANGELOG.md). ## Copyright Copyright (c) 2012-2017 Bozhidar Batsov. See [LICENSE.txt](LICENSE.txt) for further details. rubocop-0.52.1/Rakefile000066400000000000000000000101261322072016200147100ustar00rootroot00000000000000# frozen_string_literal: true require 'rubygems' require 'bundler' require 'bundler/gem_tasks' begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e warn e.message warn 'Run `bundle install` to install missing gems' exit e.status_code end require 'rake' require 'rspec/core' require 'rspec/core/rake_task' require 'rubocop/rake_task' Dir['tasks/**/*.rake'].each { |t| load t } RSpec::Core::RakeTask.new(:spec) { |t| t.ruby_opts = '-E UTF-8' } RSpec::Core::RakeTask.new(:ascii_spec) { |t| t.ruby_opts = '-E ASCII' } desc 'Run test and RuboCop in parallel' task parallel: %i[ documentation_syntax_check generate_cops_documentation parallel:spec parallel:ascii_spec internal_investigation ] namespace :parallel do desc 'Run RSpec in parallel' task :spec do sh('rspec-queue spec/') end desc 'Run RSpec in parallel with ASCII encoding' task :ascii_spec do sh('RUBYOPT="$RUBYOPT -E ASCII" rspec-queue spec/') end end desc 'Run RSpec with code coverage' task :coverage do ENV['COVERAGE'] = 'true' Rake::Task['spec'].execute end desc 'Run RuboCop over itself' RuboCop::RakeTask.new(:internal_investigation).tap do |task| if RUBY_ENGINE == 'ruby' && RbConfig::CONFIG['host_os'] !~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ task.options = %w[--parallel] end end task default: %i[ documentation_syntax_check generate_cops_documentation spec ascii_spec internal_investigation ] require 'yard' YARD::Rake::YardocTask.new desc 'Open a REPL for experimentation' task :repl do require 'pry' require 'rubocop' ARGV.clear RuboCop.pry end desc 'Benchmark a cop on given source file/dir' task :bench_cop, %i[cop srcpath times] do |_task, args| require 'benchmark' require 'rubocop' include RuboCop include RuboCop::Formatter::TextUtil cop_name = args[:cop] src_path = args[:srcpath] iterations = args[:times] ? args[:times].to_i : 1 cop_class = if cop_name.include?('/') Cop::Cop.all.find { |klass| klass.cop_name == cop_name } else Cop::Cop.all.find do |klass| klass.cop_name[/[a-zA-Z]+$/] == cop_name end end raise "No such cop: #{cop_name}" if cop_class.nil? config = ConfigLoader.load_file(ConfigLoader::DEFAULT_FILE) cop = cop_class.new(config) puts "Benchmarking #{cop.cop_name} on #{src_path} (using default config)" files = if File.directory?(src_path) Dir[File.join(src_path, '**', '*.rb')] else [src_path] end puts "(#{pluralize(iterations, 'iteration')}, " \ "#{pluralize(files.size, 'file')})" ruby_version = RuboCop::Config::KNOWN_RUBIES.last srcs = files.map { |file| ProcessedSource.from_file(file, ruby_version) } puts 'Finished parsing source, testing inspection...' puts(Benchmark.measure do iterations.times do commissioner = Cop::Commissioner.new([cop], []) srcs.each { |src| commissioner.investigate(src) } end end) end desc 'Syntax check for the documentation comments' task documentation_syntax_check: :yard_for_generate_documentation do require 'parser/ruby24' ok = true YARD::Registry.load! cops = RuboCop::Cop::Cop.registry cops.each do |cop| # TODO: parser cannot parse the example, so skip it. # https://github.com/whitequark/parser/issues/407 next if cop == RuboCop::Cop::Layout::SpaceAroundKeyword next if %i[RSpec Capybara FactoryBot].include?(cop.department) examples = YARD::Registry.all(:class).find do |code_object| next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge break code_object.tags('example') end examples.each do |example| begin buffer = Parser::Source::Buffer.new('', 1) buffer.source = example.text parser = Parser::Ruby24.new(RuboCop::AST::Builder.new) parser.diagnostics.all_errors_are_fatal = true parser.parse(buffer) rescue Parser::SyntaxError => ex path = example.object.file puts "#{path}: Syntax Error in an example. #{ex}" ok = false end end end abort unless ok end rubocop-0.52.1/appveyor.yml000066400000000000000000000006001322072016200156270ustar00rootroot00000000000000--- version: "{build}" install: - set PATH=C:\Ruby%ruby_version%\bin;%PATH% - gem update --system 2.6.14 --no-document - gem install bundler --no-document --force - bundle install --jobs 3 --retry 3 build: off test_script: - bundle exec rake environment: matrix: - ruby_version: '22' - ruby_version: 22-x64 - ruby_version: '23' - ruby_version: 23-x64 rubocop-0.52.1/assets/000077500000000000000000000000001322072016200145455ustar00rootroot00000000000000rubocop-0.52.1/assets/output.html.erb000066400000000000000000000157021322072016200175470ustar00rootroot00000000000000 RuboCop Inspection Report <%# TODO: Clean up the messy markup and style definitions. %>
<%= pluralize(files.count, 'file') %> inspected, <%= pluralize(summary.offense_count, 'offense', no_for_zero: true) %> detected:
<% files.each do |file| %> <% if file.offenses.any? %>

 

<%= relative_path(file.path) %> - <%= pluralize(file.offenses.count, 'offense') %>

<% file.offenses.each do |offense| %>
Line #<%= offense.location.line %><%= offense.severity %>: <%= decorated_message(offense) %>
<% unless offense.location.source_line.strip.empty? %>
<%= highlighted_source_line(offense) %>
<% end %>
<% end %>
<% end %> <% end %>
rubocop-0.52.1/bin/000077500000000000000000000000001322072016200140135ustar00rootroot00000000000000rubocop-0.52.1/bin/rubocop000077500000000000000000000004411322072016200154110ustar00rootroot00000000000000#!/usr/bin/env ruby # frozen_string_literal: true $LOAD_PATH.unshift("#{__dir__}/../lib") require 'rubocop' require 'benchmark' cli = RuboCop::CLI.new result = 0 time = Benchmark.realtime do result = cli.run end puts "Finished in #{time} seconds" if cli.options[:debug] exit result rubocop-0.52.1/config/000077500000000000000000000000001322072016200145105ustar00rootroot00000000000000rubocop-0.52.1/config/default.yml000066400000000000000000001350461322072016200166700ustar00rootroot00000000000000# This is the default configuration file. Enabling and disabling is configured # in separate files. This file adds all other parameters apart from Enabled. inherit_from: - enabled.yml - disabled.yml # Common configuration. AllCops: # Include common Ruby source files. Include: - '**/*.builder' - '**/*.fcgi' - '**/*.gemspec' - '**/*.god' - '**/*.jb' - '**/*.jbuilder' - '**/*.mspec' - '**/*.opal' - '**/*.pluginspec' - '**/*.podspec' - '**/*.rabl' - '**/*.rake' - '**/*.rbuild' - '**/*.rbw' - '**/*.rbx' - '**/*.ru' - '**/*.ruby' - '**/*.spec' - '**/*.thor' - '**/*.watchr' - '**/.irbrc' - '**/.pryrc' - '**/buildfile' - '**/config.ru' - '**/Appraisals' - '**/Berksfile' - '**/Brewfile' - '**/Buildfile' - '**/Capfile' - '**/Cheffile' - '**/Dangerfile' - '**/Deliverfile' - '**/Fastfile' - '**/*Fastfile' - '**/Gemfile' - '**/Guardfile' - '**/Jarfile' - '**/Mavenfile' - '**/Podfile' - '**/Puppetfile' - '**/Rakefile' - '**/Snapfile' - '**/Thorfile' - '**/Vagabondfile' - '**/Vagrantfile' Exclude: - 'node_modules/**/*' - 'vendor/**/*' # Default formatter will be used if no `-f/--format` option is given. DefaultFormatter: progress # Cop names are displayed in offense messages by default. Change behavior # by overriding DisplayCopNames, or by giving the `--no-display-cop-names` # option. DisplayCopNames: true # Style guide URLs are not displayed in offense messages by default. Change # behavior by overriding `DisplayStyleGuide`, or by giving the # `-S/--display-style-guide` option. DisplayStyleGuide: false # When specifying style guide URLs, any paths and/or fragments will be # evaluated relative to the base URL. StyleGuideBaseURL: https://github.com/bbatsov/ruby-style-guide # Extra details are not displayed in offense messages by default. Change # behavior by overriding ExtraDetails, or by giving the # `-E/--extra-details` option. ExtraDetails: false # Additional cops that do not reference a style guide rule may be enabled by # default. Change behavior by overriding `StyleGuideCopsOnly`, or by giving # the `--only-guide-cops` option. StyleGuideCopsOnly: false # All cops except the ones in disabled.yml are enabled by default. Change # this behavior by overriding either `DisabledByDefault` or `EnabledByDefault`. # When `DisabledByDefault` is `true`, all cops in the default configuration # are disabled, and only cops in user configuration are enabled. This makes # cops opt-in instead of opt-out. Note that when `DisabledByDefault` is `true`, # cops in user configuration will be enabled even if they don't set the # Enabled parameter. # When `EnabledByDefault` is `true`, all cops, even those in disabled.yml, # are enabled by default. Cops can still be disabled in user configuration. # Note that it is invalid to set both EnabledByDefault and DisabledByDefault # to true in the same configuration. EnabledByDefault: false DisabledByDefault: false # Enables the result cache if `true`. Can be overridden by the `--cache` command # line option. UseCache: true # Threshold for how many files can be stored in the result cache before some # of the files are automatically removed. MaxFilesInCache: 20000 # The cache will be stored in "rubocop_cache" under this directory. If # CacheRootDirectory is ~ (nil), which it is by default, the root will be # taken from the environment variable `$XDG_CACHE_HOME` if it is set, or if # `$XDG_CACHE_HOME` is not set, it will be `$HOME/.cache/`. CacheRootDirectory: ~ # It is possible for a malicious user to know the location of RuboCop's cache # directory by looking at CacheRootDirectory, and create a symlink in its # place that could cause RuboCop to overwrite unintended files, or read # malicious input. If you are certain that your cache location is secure from # this kind of attack, and wish to use a symlinked cache location, set this # value to "true". AllowSymlinksInCacheRootDirectory: false # What MRI version of the Ruby interpreter is the inspected code intended to # run on? (If there is more than one, set this to the lowest version.) # If a value is specified for TargetRubyVersion then it is used. # Else if .ruby-version exists and it contains an MRI version it is used. # Otherwise we fallback to the oldest officially supported Ruby version (2.1). TargetRubyVersion: ~ TargetRailsVersion: 5.0 #################### Layout ########################### # Indent private/protected/public as deep as method definitions Layout/AccessModifierIndentation: EnforcedStyle: indent SupportedStyles: - outdent - indent # By default, the indentation width from Layout/IndentationWidth is used # But it can be overridden by setting this parameter IndentationWidth: ~ # Align the elements of a hash literal if they span more than one line. Layout/AlignHash: # Alignment of entries using hash rocket as separator. Valid values are: # # key - left alignment of keys # 'a' => 2 # 'bb' => 3 # separator - alignment of hash rockets, keys are right aligned # 'a' => 2 # 'bb' => 3 # table - left alignment of keys, hash rockets, and values # 'a' => 2 # 'bb' => 3 EnforcedHashRocketStyle: key SupportedHashRocketStyles: - key - separator - table # Alignment of entries using colon as separator. Valid values are: # # key - left alignment of keys # a: 0 # bb: 1 # separator - alignment of colons, keys are right aligned # a: 0 # bb: 1 # table - left alignment of keys and values # a: 0 # bb: 1 EnforcedColonStyle: key SupportedColonStyles: - key - separator - table # Select whether hashes that are the last argument in a method call should be # inspected? Valid values are: # # always_inspect - Inspect both implicit and explicit hashes. # Registers an offense for: # function(a: 1, # b: 2) # Registers an offense for: # function({a: 1, # b: 2}) # always_ignore - Ignore both implicit and explicit hashes. # Accepts: # function(a: 1, # b: 2) # Accepts: # function({a: 1, # b: 2}) # ignore_implicit - Ignore only implicit hashes. # Accepts: # function(a: 1, # b: 2) # Registers an offense for: # function({a: 1, # b: 2}) # ignore_explicit - Ignore only explicit hashes. # Accepts: # function({a: 1, # b: 2}) # Registers an offense for: # function(a: 1, # b: 2) EnforcedLastArgumentHashStyle: always_inspect SupportedLastArgumentHashStyles: - always_inspect - always_ignore - ignore_implicit - ignore_explicit Layout/AlignParameters: # Alignment of parameters in multi-line method calls. # # The `with_first_parameter` style aligns the following lines along the same # column as the first parameter. # # method_call(a, # b) # # The `with_fixed_indentation` style aligns the following lines with one # level of indentation relative to the start of the line with the method call. # # method_call(a, # b) EnforcedStyle: with_first_parameter SupportedStyles: - with_first_parameter - with_fixed_indentation # By default, the indentation width from Layout/IndentationWidth is used # But it can be overridden by setting this parameter IndentationWidth: ~ # Indentation of `when`. Layout/CaseIndentation: EnforcedStyle: case SupportedStyles: - case - end IndentOneStep: false # By default, the indentation width from `Layout/IndentationWidth` is used. # But it can be overridden by setting this parameter. # This only matters if `IndentOneStep` is `true` IndentationWidth: ~ # Multi-line method chaining should be done with leading dots. Layout/DotPosition: EnforcedStyle: leading SupportedStyles: - leading - trailing # Use empty lines between defs. Layout/EmptyLineBetweenDefs: # If `true`, this parameter means that single line method definitions don't # need an empty line between them. AllowAdjacentOneLineDefs: false # Can be array to specify minimum and maximum number of empty lines, e.g. [1, 2] NumberOfEmptyLines: 1 Layout/EmptyLinesAroundBlockBody: EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - no_empty_lines Layout/EmptyLinesAroundClassBody: EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - empty_lines_except_namespace - empty_lines_special - no_empty_lines Layout/EmptyLinesAroundModuleBody: EnforcedStyle: no_empty_lines SupportedStyles: - empty_lines - empty_lines_except_namespace - empty_lines_special - no_empty_lines Layout/EndOfLine: # The `native` style means that CR+LF (Carriage Return + Line Feed) is # enforced on Windows, and LF is enforced on other platforms. The other styles # mean LF and CR+LF, respectively. EnforcedStyle: native SupportedStyles: - native - lf - crlf Layout/ExtraSpacing: # When true, allows most uses of extra spacing if the intent is to align # things with the previous or next line, not counting empty lines or comment # lines. AllowForAlignment: true # When true, forces the alignment of `=` in assignments on consecutive lines. ForceEqualSignAlignment: false Layout/FirstParameterIndentation: EnforcedStyle: special_for_inner_method_call_in_parentheses SupportedStyles: # The first parameter should always be indented one step more than the # preceding line. - consistent # The first parameter should normally be indented one step more than the # preceding line, but if it's a parameter for a method call that is itself # a parameter in a method call, then the inner parameter should be indented # relative to the inner method. - special_for_inner_method_call # Same as `special_for_inner_method_call` except that the special rule only # applies if the outer method call encloses its arguments in parentheses. - special_for_inner_method_call_in_parentheses # By default, the indentation width from `Layout/IndentationWidth` is used # But it can be overridden by setting this parameter IndentationWidth: ~ Layout/IndentationConsistency: # The difference between `rails` and `normal` is that the `rails` style # prescribes that in classes and modules the `protected` and `private` # modifier keywords shall be indented the same as public methods and that # protected and private members shall be indented one step more than the # modifiers. Other than that, both styles mean that entities on the same # logical depth shall have the same indentation. EnforcedStyle: normal SupportedStyles: - normal - rails Layout/IndentationWidth: # Number of spaces for each indentation level. Width: 2 IgnoredPatterns: [] # Checks the indentation of the first element in an array literal. Layout/IndentArray: # The value `special_inside_parentheses` means that array literals with # brackets that have their opening bracket on the same line as a surrounding # opening round parenthesis, shall have their first element indented relative # to the first position inside the parenthesis. # # The value `consistent` means that the indentation of the first element shall # always be relative to the first position of the line where the opening # bracket is. # # The value `align_brackets` means that the indentation of the first element # shall always be relative to the position of the opening bracket. EnforcedStyle: special_inside_parentheses SupportedStyles: - special_inside_parentheses - consistent - align_brackets # By default, the indentation width from `Layout/IndentationWidth` is used # But it can be overridden by setting this parameter IndentationWidth: ~ # Checks the indentation of assignment RHS, when on a different line from LHS Layout/IndentAssignment: # By default, the indentation width from `Layout/IndentationWidth` is used # But it can be overridden by setting this parameter IndentationWidth: ~ # Checks the indentation of the first key in a hash literal. Layout/IndentHash: # The value `special_inside_parentheses` means that hash literals with braces # that have their opening brace on the same line as a surrounding opening # round parenthesis, shall have their first key indented relative to the # first position inside the parenthesis. # # The value `consistent` means that the indentation of the first key shall # always be relative to the first position of the line where the opening # brace is. # # The value `align_braces` means that the indentation of the first key shall # always be relative to the position of the opening brace. EnforcedStyle: special_inside_parentheses SupportedStyles: - special_inside_parentheses - consistent - align_braces # By default, the indentation width from `Layout/IndentationWidth` is used # But it can be overridden by setting this parameter IndentationWidth: ~ Layout/IndentHeredoc: EnforcedStyle: auto_detection SupportedStyles: - auto_detection - squiggly - active_support - powerpack - unindent Layout/SpaceInLambdaLiteral: EnforcedStyle: require_no_space SupportedStyles: - require_no_space - require_space Layout/MultilineArrayBraceLayout: EnforcedStyle: symmetrical SupportedStyles: # symmetrical: closing brace is positioned in same way as opening brace # new_line: closing brace is always on a new line # same_line: closing brace is always on the same line as last element - symmetrical - new_line - same_line Layout/MultilineAssignmentLayout: # The types of assignments which are subject to this rule. SupportedTypes: - block - case - class - if - kwbegin - module EnforcedStyle: new_line SupportedStyles: # Ensures that the assignment operator and the rhs are on the same line for # the set of supported types. - same_line # Ensures that the assignment operator and the rhs are on separate lines # for the set of supported types. - new_line Layout/MultilineHashBraceLayout: EnforcedStyle: symmetrical SupportedStyles: # symmetrical: closing brace is positioned in same way as opening brace # new_line: closing brace is always on a new line # same_line: closing brace is always on same line as last element - symmetrical - new_line - same_line Layout/MultilineMethodCallBraceLayout: EnforcedStyle: symmetrical SupportedStyles: # symmetrical: closing brace is positioned in same way as opening brace # new_line: closing brace is always on a new line # same_line: closing brace is always on the same line as last argument - symmetrical - new_line - same_line Layout/MultilineMethodCallIndentation: EnforcedStyle: aligned SupportedStyles: - aligned - indented - indented_relative_to_receiver # By default, the indentation width from Layout/IndentationWidth is used # But it can be overridden by setting this parameter IndentationWidth: ~ Layout/MultilineMethodDefinitionBraceLayout: EnforcedStyle: symmetrical SupportedStyles: # symmetrical: closing brace is positioned in same way as opening brace # new_line: closing brace is always on a new line # same_line: closing brace is always on the same line as last parameter - symmetrical - new_line - same_line Layout/MultilineOperationIndentation: EnforcedStyle: aligned SupportedStyles: - aligned - indented # By default, the indentation width from `Layout/IndentationWidth` is used # But it can be overridden by setting this parameter IndentationWidth: ~ Layout/SpaceAroundBlockParameters: EnforcedStyleInsidePipes: no_space SupportedStylesInsidePipes: - space - no_space Layout/SpaceAroundEqualsInParameterDefault: EnforcedStyle: space SupportedStyles: - space - no_space Layout/SpaceAroundOperators: # When `true`, allows most uses of extra spacing if the intent is to align # with an operator on the previous or next line, not counting empty lines # or comment lines. AllowForAlignment: true Layout/SpaceBeforeBlockBraces: EnforcedStyle: space SupportedStyles: - space - no_space EnforcedStyleForEmptyBraces: space SupportedStylesForEmptyBraces: - space - no_space Layout/SpaceBeforeFirstArg: # When `true`, allows most uses of extra spacing if the intent is to align # things with the previous or next line, not counting empty lines or comment # lines. AllowForAlignment: true Layout/SpaceInsideArrayLiteralBrackets: EnforcedStyle: no_space SupportedStyles: - space - no_space # 'compact' normally requires a space inside the brackets, with the exception # that successive left brackets or right brackets are collapsed together - compact EnforcedStyleForEmptyBrackets: no_space SupportedStylesForEmptyBrackets: - space - no_space Layout/SpaceInsideBlockBraces: EnforcedStyle: space SupportedStyles: - space - no_space EnforcedStyleForEmptyBraces: no_space SupportedStylesForEmptyBraces: - space - no_space # Space between `{` and `|`. Overrides `EnforcedStyle` if there is a conflict. SpaceBeforeBlockParameters: true Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: space SupportedStyles: - space - no_space # 'compact' normally requires a space inside hash braces, with the exception # that successive left braces or right braces are collapsed together - compact EnforcedStyleForEmptyBraces: no_space SupportedStylesForEmptyBraces: - space - no_space Layout/SpaceInsideReferenceBrackets: EnforcedStyle: no_space SupportedStyles: - space - no_space Layout/SpaceInsideStringInterpolation: EnforcedStyle: no_space SupportedStyles: - space - no_space Layout/ClassStructure: Categories: module_inclusion: - include - prepend - extend ExpectedOrder: - module_inclusion - constants - public_class_methods - initializer - public_methods - protected_methods - private_methods Layout/Tab: # By default, the indentation width from Layout/IndentationWidth is used # But it can be overridden by setting this parameter # It is used during auto-correction to determine how many spaces should # replace each tab. IndentationWidth: ~ Layout/TrailingBlankLines: EnforcedStyle: final_newline SupportedStyles: - final_newline - final_blank_line #################### Naming ########################## Naming/FileName: # File names listed in `AllCops:Include` are excluded by default. Add extra # excludes here. Exclude: [] # When `true`, requires that each source file should define a class or module # with a name which matches the file name (converted to ... case). # It further expects it to be nested inside modules which match the names # of subdirectories in its path. ExpectMatchingDefinition: false # If non-`nil`, expect all source file names to match the following regex. # Only the file name itself is matched, not the entire file path. # Use anchors as necessary if you want to match the entire name rather than # just a part of it. Regex: ~ # With `IgnoreExecutableScripts` set to `true`, this cop does not # report offending filenames for executable scripts (i.e. source # files with a shebang in the first line). IgnoreExecutableScripts: true AllowedAcronyms: - CLI - DSL - ACL - API - ASCII - CPU - CSS - DNS - EOF - GUID - HTML - HTTP - HTTPS - ID - IP - JSON - LHS - QPS - RAM - RHS - RPC - SLA - SMTP - SQL - SSH - TCP - TLS - TTL - UDP - UI - UID - UUID - URI - URL - UTF8 - VM - XML - XMPP - XSRF - XSS Naming/HeredocDelimiterNaming: Blacklist: - END - !ruby/regexp '/EO[A-Z]{1}/' Naming/HeredocDelimiterCase: EnforcedStyle: uppercase SupportedStyles: - lowercase - uppercase Naming/MethodName: EnforcedStyle: snake_case SupportedStyles: - snake_case - camelCase Naming/PredicateName: # Predicate name prefixes. NamePrefix: - is_ - has_ - have_ # Predicate name prefixes that should be removed. NamePrefixBlacklist: - is_ - has_ - have_ # Predicate names which, despite having a blacklisted prefix, or no `?`, # should still be accepted NameWhitelist: - is_a? # Method definition macros for dynamically generated methods. MethodDefinitionMacros: - define_method - define_singleton_method # Exclude Rspec specs because there is a strong convention to write spec # helpers in the form of `have_something` or `be_something`. Exclude: - 'spec/**/*' Naming/VariableName: EnforcedStyle: snake_case SupportedStyles: - snake_case - camelCase Naming/VariableNumber: EnforcedStyle: normalcase SupportedStyles: - snake_case - normalcase - non_integer #################### Style ########################### Style/Alias: EnforcedStyle: prefer_alias SupportedStyles: - prefer_alias - prefer_alias_method Style/AndOr: # Whether `and` and `or` are banned only in conditionals (conditionals) # or completely (always). EnforcedStyle: always SupportedStyles: - always - conditionals Style/AsciiComments: AllowedChars: [] # Checks if usage of `%()` or `%Q()` matches configuration. Style/BarePercentLiterals: EnforcedStyle: bare_percent SupportedStyles: - percent_q - bare_percent Style/BlockDelimiters: EnforcedStyle: line_count_based SupportedStyles: # The `line_count_based` style enforces braces around single line blocks and # do..end around multi-line blocks. - line_count_based # The `semantic` style enforces braces around functional blocks, where the # primary purpose of the block is to return a value and do..end for # procedural blocks, where the primary purpose of the block is its # side-effects. # # This looks at the usage of a block's method to determine its type (e.g. is # the result of a `map` assigned to a variable or passed to another # method) but exceptions are permitted in the `ProceduralMethods`, # `FunctionalMethods` and `IgnoredMethods` sections below. - semantic # The `braces_for_chaining` style enforces braces around single line blocks # and do..end around multi-line blocks, except for multi-line blocks whose # return value is being chained with another method (in which case braces # are enforced). - braces_for_chaining ProceduralMethods: # Methods that are known to be procedural in nature but look functional from # their usage, e.g. # # time = Benchmark.realtime do # foo.bar # end # # Here, the return value of the block is discarded but the return value of # `Benchmark.realtime` is used. - benchmark - bm - bmbm - create - each_with_object - measure - new - realtime - tap - with_object FunctionalMethods: # Methods that are known to be functional in nature but look procedural from # their usage, e.g. # # let(:foo) { Foo.new } # # Here, the return value of `Foo.new` is used to define a `foo` helper but # doesn't appear to be used from the return value of `let`. - let - let! - subject - watch IgnoredMethods: # Methods that can be either procedural or functional and cannot be # categorised from their usage alone, e.g. # # foo = lambda do |x| # puts "Hello, #{x}" # end # # foo = lambda do |x| # x * 100 # end # # Here, it is impossible to tell from the return value of `lambda` whether # the inner block's return value is significant. - lambda - proc - it Style/BracesAroundHashParameters: EnforcedStyle: no_braces SupportedStyles: # The `braces` style enforces braces around all method parameters that are # hashes. - braces # The `no_braces` style checks that the last parameter doesn't have braces # around it. - no_braces # The `context_dependent` style checks that the last parameter doesn't have # braces around it, but requires braces if the second to last parameter is # also a hash literal. - context_dependent Style/ClassAndModuleChildren: # Checks the style of children definitions at classes and modules. # # Basically there are two different styles: # # `nested` - have each child on a separate line # class Foo # class Bar # end # end # # `compact` - combine definitions as much as possible # class Foo::Bar # end # # The compact style is only forced, for classes or modules with one child. EnforcedStyle: nested SupportedStyles: - nested - compact Style/ClassCheck: EnforcedStyle: is_a? SupportedStyles: - is_a? - kind_of? # Align with the style guide. Style/CollectionMethods: # Mapping from undesired method to desired_method # e.g. to use `detect` over `find`: # # CollectionMethods: # PreferredMethods: # find: detect PreferredMethods: collect: 'map' collect!: 'map!' inject: 'reduce' detect: 'find' find_all: 'select' # Use '`' or '%x' around command literals. Style/CommandLiteral: EnforcedStyle: backticks # backticks: Always use backticks. # percent_x: Always use `%x`. # mixed: Use backticks on single-line commands, and `%x` on multi-line commands. SupportedStyles: - backticks - percent_x - mixed # If `false`, the cop will always recommend using `%x` if one or more backticks # are found in the command string. AllowInnerBackticks: false # Checks formatting of special comments Style/CommentAnnotation: Keywords: - TODO - FIXME - OPTIMIZE - HACK - REVIEW Style/ConditionalAssignment: EnforcedStyle: assign_to_condition SupportedStyles: - assign_to_condition - assign_inside_condition # When configured to `assign_to_condition`, `SingleLineConditionsOnly` # will only register an offense when all branches of a condition are # a single line. # When configured to `assign_inside_condition`, `SingleLineConditionsOnly` # will only register an offense for assignment to a condition that has # at least one multiline branch. SingleLineConditionsOnly: true IncludeTernaryExpressions: true # Checks that you have put a copyright in a comment before any code. # # You can override the default Notice in your .rubocop.yml file. # # In order to use autocorrect, you must supply a value for the # `AutocorrectNotice` key that matches the regexp Notice. A blank # `AutocorrectNotice` will cause an error during autocorrect. # # Autocorrect will add a copyright notice in a comment at the top # of the file immediately after any shebang or encoding comments. # # Example rubocop.yml: # # Style/Copyright: # Enabled: true # Notice: 'Copyright (\(c\) )?2015 Yahoo! Inc' # AutocorrectNotice: '# Copyright (c) 2015 Yahoo! Inc.' # Style/Copyright: Notice: '^Copyright (\(c\) )?2[0-9]{3} .+' AutocorrectNotice: '' Style/DocumentationMethod: RequireForNonPublicMethods: false # Warn on empty else statements # empty - warn only on empty `else` # nil - warn on `else` with nil in it # both - warn on empty `else` and `else` with `nil` in it Style/EmptyElse: EnforcedStyle: both SupportedStyles: - empty - nil - both Style/EmptyMethod: EnforcedStyle: compact SupportedStyles: - compact - expanded # Checks use of for or each in multiline loops. Style/For: EnforcedStyle: each SupportedStyles: - for - each # Enforce the method used for string formatting. Style/FormatString: EnforcedStyle: format SupportedStyles: - format - sprintf - percent # Enforce using either `%s` or `%{token}` Style/FormatStringToken: EnforcedStyle: annotated SupportedStyles: # Prefer tokens which contain a sprintf like type annotation like # `%s`, `%d`, `%f` - annotated # Prefer simple looking "template" style tokens like `%{name}`, `%{age}` - template - unannotated Style/FrozenStringLiteralComment: EnforcedStyle: when_needed SupportedStyles: # `when_needed` will add the frozen string literal comment to files # only when the `TargetRubyVersion` is set to 2.3+. - when_needed # `always` will always add the frozen string literal comment to a file # regardless of the Ruby version or if `freeze` or `<<` are called on a # string literal. If you run code against multiple versions of Ruby, it is # possible that this will create errors in Ruby 2.3.0+. - always # `never` will enforce that the frozen string literal comment does not # exist in a file. - never # Built-in global variables are allowed by default. Style/GlobalVars: AllowedVariables: [] # `MinBodyLength` defines the number of lines of the a body of an `if` or `unless` # needs to have to trigger this cop Style/GuardClause: MinBodyLength: 1 Style/HashSyntax: EnforcedStyle: ruby19 SupportedStyles: # checks for 1.9 syntax (e.g. {a: 1}) for all symbol keys - ruby19 # checks for hash rocket syntax for all hashes - hash_rockets # forbids mixed key syntaxes (e.g. {a: 1, :b => 2}) - no_mixed_keys # enforces both ruby19 and no_mixed_keys styles - ruby19_no_mixed_keys # Force hashes that have a symbol value to use hash rockets UseHashRocketsWithSymbolValues: false # Do not suggest { a?: 1 } over { :a? => 1 } in ruby19 style PreferHashRocketsForNonAlnumEndingSymbols: false Style/InverseMethods: # `InverseMethods` are methods that can be inverted by a not (`not` or `!`) # The relationship of inverse methods only needs to be defined in one direction. # Keys and values both need to be defined as symbols. InverseMethods: :any?: :none? :even?: :odd? :==: :!= :=~: :!~ :<: :>= :>: :<= # `ActiveSupport` defines some common inverse methods. They are listed below, # and not enabled by default. #:present?: :blank?, #:include?: :exclude? # `InverseBlocks` are methods that are inverted by inverting the return # of the block that is passed to the method InverseBlocks: :select: :reject :select!: :reject! Style/Lambda: EnforcedStyle: line_count_dependent SupportedStyles: - line_count_dependent - lambda - literal Style/LambdaCall: EnforcedStyle: call SupportedStyles: - call - braces Style/MethodCallWithArgsParentheses: IgnoreMacros: true IgnoredMethods: [] Style/MethodDefParentheses: EnforcedStyle: require_parentheses SupportedStyles: - require_parentheses - require_no_parentheses - require_no_parentheses_except_multiline # Checks the grouping of mixins (`include`, `extend`, `prepend`) in `class` and # `module` bodies. Style/MixinGrouping: EnforcedStyle: separated SupportedStyles: # separated: each mixed in module goes in a separate statement. # grouped: mixed in modules are grouped into a single statement. - separated - grouped Style/ModuleFunction: EnforcedStyle: module_function SupportedStyles: - module_function - extend_self Style/MultilineMemoization: EnforcedStyle: keyword SupportedStyles: - keyword - braces Style/NegatedIf: EnforcedStyle: both SupportedStyles: # both: prefix and postfix negated `if` should both use `unless` # prefix: only use `unless` for negated `if` statements positioned before the body of the statement # postfix: only use `unless` for negated `if` statements positioned after the body of the statement - both - prefix - postfix Style/NestedParenthesizedCalls: Whitelist: - be - be_a - be_an - be_between - be_falsey - be_kind_of - be_instance_of - be_truthy - be_within - eq - eql - end_with - include - match - raise_error - respond_to - start_with Style/Next: # With `always` all conditions at the end of an iteration needs to be # replaced by next - with `skip_modifier_ifs` the modifier if like this one # are ignored: [1, 2].each { |a| return 'yes' if a == 1 } EnforcedStyle: skip_modifier_ifs # `MinBodyLength` defines the number of lines of the a body of an `if` or `unless` # needs to have to trigger this cop MinBodyLength: 3 SupportedStyles: - skip_modifier_ifs - always Style/NonNilCheck: # With `IncludeSemanticChanges` set to `true`, this cop reports offenses for # `!x.nil?` and autocorrects that and `x != nil` to solely `x`, which is # **usually** OK, but might change behavior. # # With `IncludeSemanticChanges` set to `false`, this cop does not report # offenses for `!x.nil?` and does no changes that might change behavior. IncludeSemanticChanges: false Style/NumericLiterals: MinDigits: 5 Strict: false Style/NumericLiteralPrefix: EnforcedOctalStyle: zero_with_o SupportedOctalStyles: - zero_with_o - zero_only Style/NumericPredicate: EnforcedStyle: predicate SupportedStyles: - predicate - comparison # Exclude RSpec specs because assertions like `expect(1).to be > 0` cause # false positives. Exclude: - 'spec/**/*' Style/OptionHash: # A list of parameter names that will be flagged by this cop. SuspiciousParamNames: - options - opts - args - params - parameters # Allow safe assignment in conditions. Style/ParenthesesAroundCondition: AllowSafeAssignment: true Style/PercentLiteralDelimiters: # Specify the default preferred delimiter for all types with the 'default' key # Override individual delimiters (even with default specified) by specifying # an individual key PreferredDelimiters: default: () '%i': '[]' '%I': '[]' '%r': '{}' '%w': '[]' '%W': '[]' Style/PercentQLiterals: EnforcedStyle: lower_case_q SupportedStyles: - lower_case_q # Use `%q` when possible, `%Q` when necessary - upper_case_q # Always use `%Q` Style/PreferredHashMethods: EnforcedStyle: short SupportedStyles: - short - verbose Style/RaiseArgs: EnforcedStyle: exploded SupportedStyles: - compact # raise Exception.new(msg) - exploded # raise Exception, msg Style/RedundantReturn: # When `true` allows code like `return x, y`. AllowMultipleReturnValues: false # Use `/` or `%r` around regular expressions. Style/RegexpLiteral: EnforcedStyle: slashes # slashes: Always use slashes. # percent_r: Always use `%r`. # mixed: Use slashes on single-line regexes, and `%r` on multi-line regexes. SupportedStyles: - slashes - percent_r - mixed # If `false`, the cop will always recommend using `%r` if one or more slashes # are found in the regexp string. AllowInnerSlashes: false Style/RescueStandardError: EnforcedStyle: explicit # implicit: Do not include the error class, `rescue` # explicit: Require an error class `rescue StandardError` SupportedStyles: - implicit - explicit Style/ReturnNil: EnforcedStyle: return SupportedStyles: - return - return_nil Style/SafeNavigation: # Safe navigation may cause a statement to start returning `nil` in addition # to whatever it used to return. ConvertCodeThatCanStartToReturnNil: false Style/Semicolon: # Allow `;` to separate several expressions on the same line. AllowAsExpressionSeparator: false Style/SignalException: EnforcedStyle: only_raise SupportedStyles: - only_raise - only_fail - semantic Style/SingleLineBlockParams: Methods: - reduce: - acc - elem - inject: - acc - elem Style/SingleLineMethods: AllowIfMethodIsEmpty: true Style/SpecialGlobalVars: EnforcedStyle: use_english_names SupportedStyles: - use_perl_names - use_english_names Style/StabbyLambdaParentheses: EnforcedStyle: require_parentheses SupportedStyles: - require_parentheses - require_no_parentheses Style/StringLiterals: EnforcedStyle: single_quotes SupportedStyles: - single_quotes - double_quotes # If `true`, strings which span multiple lines using `\` for continuation must # use the same type of quotes on each line. ConsistentQuotesInMultiline: false Style/StringLiteralsInInterpolation: EnforcedStyle: single_quotes SupportedStyles: - single_quotes - double_quotes Style/StringMethods: # Mapping from undesired method to desired_method # e.g. to use `to_sym` over `intern`: # # StringMethods: # PreferredMethods: # intern: to_sym PreferredMethods: intern: to_sym Style/SymbolArray: EnforcedStyle: percent MinSize: 0 SupportedStyles: - percent - brackets Style/SymbolProc: # A list of method names to be ignored by the check. # The names should be fairly unique, otherwise you'll end up ignoring lots of code. IgnoredMethods: - respond_to - define_method Style/TernaryParentheses: EnforcedStyle: require_no_parentheses SupportedStyles: - require_parentheses - require_no_parentheses - require_parentheses_when_complex AllowSafeAssignment: true Style/TrailingCommaInArguments: # If `comma`, the cop requires a comma after the last argument, but only for # parenthesized method calls where each argument is on its own line. # If `consistent_comma`, the cop requires a comma after the last argument, # for all parenthesized method calls with arguments. EnforcedStyleForMultiline: no_comma SupportedStylesForMultiline: - comma - consistent_comma - no_comma Style/TrailingCommaInLiteral: # If `comma`, the cop requires a comma after the last item in an array or # hash, but only when each item is on its own line. # If `consistent_comma`, the cop requires a comma after the last item of all # non-empty array and hash literals. EnforcedStyleForMultiline: no_comma SupportedStylesForMultiline: - comma - consistent_comma - no_comma # `TrivialAccessors` requires exact name matches and doesn't allow # predicated methods by default. Style/TrivialAccessors: # When set to `false` the cop will suggest the use of accessor methods # in situations like: # # def name # @other_name # end # # This way you can uncover "hidden" attributes in your code. ExactNameMatch: true AllowPredicates: true # Allows trivial writers that don't end in an equal sign. e.g. # # def on_exception(action) # @on_exception=action # end # on_exception :restart # # Commonly used in DSLs AllowDSLWriters: false IgnoreClassMethods: false Whitelist: - to_ary - to_a - to_c - to_enum - to_h - to_hash - to_i - to_int - to_io - to_open - to_path - to_proc - to_r - to_regexp - to_str - to_s - to_sym # `WordArray` enforces how array literals of word-like strings should be expressed. Style/WordArray: EnforcedStyle: percent SupportedStyles: # percent style: %w(word1 word2) - percent # bracket style: ['word1', 'word2'] - brackets # The `MinSize` option causes the `WordArray` rule to be ignored for arrays # smaller than a certain size. The rule is only applied to arrays # whose element count is greater than or equal to `MinSize`. MinSize: 0 # The regular expression `WordRegex` decides what is considered a word. WordRegex: !ruby/regexp '/\A[\p{Word}\n\t]+\z/' Style/YodaCondition: EnforcedStyle: all_comparison_operators SupportedStyles: # check all comparison operators - all_comparison_operators # check only equality operators: `!=` and `==` - equality_operators_only #################### Metrics ############################### Metrics/AbcSize: # The ABC size is a calculated magnitude, so this number can be an Integer or # a Float. Max: 15 Metrics/BlockLength: CountComments: false # count full line comments? Max: 25 ExcludedMethods: [] Metrics/BlockNesting: CountBlocks: false Max: 3 Metrics/ClassLength: CountComments: false # count full line comments? Max: 100 # Avoid complex methods. Metrics/CyclomaticComplexity: Max: 6 Metrics/LineLength: Max: 80 # To make it possible to copy or click on URIs in the code, we allow lines # containing a URI to be longer than Max. AllowHeredoc: true AllowURI: true URISchemes: - http - https # The IgnoreCopDirectives option causes the LineLength rule to ignore cop # directives like '# rubocop: enable ...' when calculating a line's length. IgnoreCopDirectives: false # The IgnoredPatterns option is a list of !ruby/regexp and/or string # elements. Strings will be converted to Regexp objects. A line that matches # any regular expression listed in this option will be ignored by LineLength. IgnoredPatterns: [] Metrics/MethodLength: CountComments: false # count full line comments? Max: 10 Metrics/ModuleLength: CountComments: false # count full line comments? Max: 100 Metrics/ParameterLists: Max: 5 CountKeywordArgs: true Metrics/PerceivedComplexity: Max: 7 #################### Lint ################################## # Allow safe assignment in conditions. Lint/AssignmentInCondition: AllowSafeAssignment: true # checks whether the end keywords are aligned properly for `do` `end` blocks. Lint/BlockAlignment: # The value `start_of_block` means that the `end` should be aligned with line # where the `do` keyword appears. # The value `start_of_line` means it should be aligned with the whole # expression's starting line. # The value `either` means both are allowed. EnforcedStyleAlignWith: either SupportedStylesAlignWith: - either - start_of_block - start_of_line Lint/DefEndAlignment: # The value `def` means that `end` should be aligned with the def keyword. # The value `start_of_line` means that `end` should be aligned with method # calls like `private`, `public`, etc, if present in front of the `def` # keyword on the same line. EnforcedStyleAlignWith: start_of_line SupportedStylesAlignWith: - start_of_line - def AutoCorrect: false # Align ends correctly. Lint/EndAlignment: # The value `keyword` means that `end` should be aligned with the matching # keyword (`if`, `while`, etc.). # The value `variable` means that in assignments, `end` should be aligned # with the start of the variable on the left hand side of `=`. In all other # situations, `end` should still be aligned with the keyword. # The value `start_of_line` means that `end` should be aligned with the start # of the line which the matching keyword appears on. EnforcedStyleAlignWith: keyword SupportedStylesAlignWith: - keyword - variable - start_of_line AutoCorrect: false Lint/InheritException: # The default base class in favour of `Exception`. EnforcedStyle: runtime_error SupportedStyles: - runtime_error - standard_error Lint/MissingCopEnableDirective: # Maximum number of consecutive lines the cop can be disabled for. # 0 allows only single-line disables # 1 would mean the maximum allowed is the following: # # rubocop:disable SomeCop # a = 1 # # rubocop:enable SomeCop # .inf for any size MaximumRangeSize: .inf Lint/SafeNavigationChain: Whitelist: - present? - blank? - presence - try # Checks for shadowed arguments Lint/ShadowedArgument: IgnoreImplicitReferences: false # Checks for unused block arguments Lint/UnusedBlockArgument: IgnoreEmptyBlocks: true AllowUnusedKeywordArguments: false # Checks for unused method arguments. Lint/UnusedMethodArgument: AllowUnusedKeywordArguments: false IgnoreEmptyMethods: true #################### Performance ########################### Performance/DoubleStartEndWith: # Used to check for `starts_with?` and `ends_with?`. # These methods are defined by `ActiveSupport`. IncludeActiveSupportAliases: false Performance/RedundantMerge: # Max number of key-value pairs to consider an offense MaxKeyValuePairs: 2 #################### Rails ################################# Rails/ActionFilter: EnforcedStyle: action SupportedStyles: - action - filter Include: - app/controllers/**/*.rb Rails/CreateTableWithTimestamps: Include: - db/migrate/*.rb Rails/Date: # The value `strict` disallows usage of `Date.today`, `Date.current`, # `Date#to_time` etc. # The value `flexible` allows usage of `Date.current`, `Date.yesterday`, etc # (but not `Date.today`) which are overridden by ActiveSupport to handle current # time zone. EnforcedStyle: flexible SupportedStyles: - strict - flexible Rails/Delegate: # When set to true, using the target object as a prefix of the # method name without using the `delegate` method will be a # violation. When set to false, this case is legal. EnforceForPrefixed: true Rails/DynamicFindBy: Whitelist: - find_by_sql Rails/EnumUniqueness: Include: - app/models/**/*.rb Rails/Exit: Include: - app/**/*.rb - config/**/*.rb - lib/**/*.rb Exclude: - lib/**/*.rake Rails/FindBy: Include: - app/models/**/*.rb Rails/FindEach: Include: - app/models/**/*.rb Rails/HasAndBelongsToMany: Include: - app/models/**/*.rb Rails/HasManyOrHasOneDependent: Include: - app/models/**/*.rb Rails/InverseOf: Include: - app/models/**/*.rb Rails/LexicallyScopedActionFilter: Include: - app/controllers/**/*.rb Rails/NotNullColumn: Include: - db/migrate/*.rb Rails/Output: Include: - app/**/*.rb - config/**/*.rb - db/**/*.rb - lib/**/*.rb Rails/ReadWriteAttribute: Include: - app/models/**/*.rb Rails/RequestReferer: EnforcedStyle: referer SupportedStyles: - referer - referrer Rails/ReversibleMigration: Include: - db/migrate/*.rb Rails/SafeNavigation: # This will convert usages of `try` to use safe navigation as well as `try!`. # `try` and `try!` work slightly differently. `try!` and safe navigation will # both raise a `NoMethodError` if the receiver of the method call does not # implement the intended method. `try` will not raise an exception for this. ConvertTry: false Rails/ScopeArgs: Include: - app/models/**/*.rb Rails/TimeZone: # The value `strict` means that `Time` should be used with `zone`. # The value `flexible` allows usage of `in_time_zone` instead of `zone`. EnforcedStyle: flexible SupportedStyles: - strict - flexible Rails/UniqBeforePluck: EnforcedStyle: conservative SupportedStyles: - conservative - aggressive AutoCorrect: false Rails/UnknownEnv: Environments: - development - test - production Rails/SkipsModelValidations: Blacklist: - decrement! - decrement_counter - increment! - increment_counter - toggle! - touch - update_all - update_attribute - update_column - update_columns - update_counters Rails/Validation: Include: - app/models/**/*.rb Bundler/OrderedGems: TreatCommentsAsGroupSeparators: true Gemspec/OrderedDependencies: TreatCommentsAsGroupSeparators: true rubocop-0.52.1/config/disabled.yml000066400000000000000000000077561322072016200170210ustar00rootroot00000000000000# These are all the cops that are disabled in the default configuration. Layout/ClassStructure: Description: 'Enforces a configured order of definitions within a class body.' StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#consistent-classes' Enabled: false Layout/FirstArrayElementLineBreak: Description: >- Checks for a line break before the first element in a multi-line array. Enabled: false Layout/FirstHashElementLineBreak: Description: >- Checks for a line break before the first element in a multi-line hash. Enabled: false Layout/FirstMethodArgumentLineBreak: Description: >- Checks for a line break before the first argument in a multi-line method call. Enabled: false Layout/FirstMethodParameterLineBreak: Description: >- Checks for a line break before the first parameter in a multi-line method parameter definition. Enabled: false Layout/MultilineAssignmentLayout: Description: 'Check for a newline after the assignment operator in multi-line assignments.' StyleGuide: '#indent-conditional-assignment' Enabled: false # By default, the rails cops are not run. Override in project or home # directory .rubocop.yml files, or by giving the -R/--rails option. Rails: Enabled: false Rails/SaveBang: Description: 'Identifies possible cases where Active Record save! or related should be used.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#save-bang' Enabled: false Style/AutoResourceCleanup: Description: 'Suggests the usage of an auto resource cleanup version of a method (if available).' Enabled: false Style/CollectionMethods: Description: 'Preferred collection methods.' StyleGuide: '#map-find-select-reduce-size' Enabled: false Style/Copyright: Description: 'Include a copyright notice in each file before any code.' Enabled: false Style/DocumentationMethod: Description: 'Public methods.' Enabled: false Exclude: - 'spec/**/*' - 'test/**/*' Style/ImplicitRuntimeError: Description: >- Use `raise` or `fail` with an explicit exception class and message, rather than just a message. Enabled: false Style/InlineComment: Description: 'Avoid trailing inline comments.' Enabled: false Style/MethodCallWithArgsParentheses: Description: 'Use parentheses for method calls with arguments.' StyleGuide: '#method-invocation-parens' Enabled: false Style/MethodCalledOnDoEndBlock: Description: 'Avoid chaining a method call on a do...end block.' StyleGuide: '#single-line-blocks' Enabled: false Style/MissingElse: Description: >- Require if/case expressions to have an else branches. If enabled, it is recommended that Style/UnlessElse and Style/EmptyElse be enabled. This will conflict with Style/EmptyElse if Style/EmptyElse is configured to style "both" Enabled: false EnforcedStyle: both SupportedStyles: # if - warn when an if expression is missing an else branch # case - warn when a case expression is missing an else branch # both - warn when an if or case expression is missing an else branch - if - case - both Style/OptionHash: Description: "Don't use option hashes when you can use keyword arguments." Enabled: false Style/ReturnNil: Description: 'Use return instead of return nil.' Enabled: false Style/Send: Description: 'Prefer `Object#__send__` or `Object#public_send` to `send`, as `send` may overlap with existing methods.' StyleGuide: '#prefer-public-send' Enabled: false Style/SingleLineBlockParams: Description: 'Enforces the names of some block params.' Enabled: false Style/StringHashKeys: Description: 'Prefer symbols instead of strings as hash keys.' StyleGuide: '#symbols-as-keys' Enabled: false Style/StringMethods: Description: 'Checks if configured preferred methods are used over non-preferred.' Enabled: false rubocop-0.52.1/config/enabled.yml000066400000000000000000001650371322072016200166410ustar00rootroot00000000000000# These are all the cops that are enabled in the default configuration. #################### Bundler ############################### Bundler/DuplicatedGem: Description: 'Checks for duplicate gem entries in Gemfile.' Enabled: true Include: - '**/Gemfile' - '**/gems.rb' Bundler/InsecureProtocolSource: Description: >- The source `:gemcutter`, `:rubygems` and `:rubyforge` are deprecated because HTTP requests are insecure. Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. Enabled: true Include: - '**/Gemfile' - '**/gems.rb' Bundler/OrderedGems: Description: >- Gems within groups in the Gemfile should be alphabetically sorted. Enabled: true Include: - '**/Gemfile' - '**/gems.rb' #################### Gemspec ############################### Gemspec/DuplicatedAssignment: Description: 'An attribute assignment method calls should be listed only once in a gemspec.' Enabled: true Include: - '**/*.gemspec' Gemspec/OrderedDependencies: Description: >- Dependencies in the gemspec should be alphabetically sorted. Enabled: true Include: - '**/*.gemspec' Gemspec/RequiredRubyVersion: Description: 'Checks that `required_ruby_version` of gemspec and `TargetRubyVersion` of .rubocop.yml are equal.' Enabled: true Include: - '**/*.gemspec' #################### Layout ############################### Layout/AccessModifierIndentation: Description: Check indentation of private/protected visibility modifiers. StyleGuide: '#indent-public-private-protected' Enabled: true Layout/AlignArray: Description: >- Align the elements of an array literal if they span more than one line. StyleGuide: '#align-multiline-arrays' Enabled: true Layout/AlignHash: Description: >- Align the elements of a hash literal if they span more than one line. Enabled: true Layout/AlignParameters: Description: >- Align the parameters of a method call if they span more than one line. StyleGuide: '#no-double-indent' Enabled: true Layout/BlockEndNewline: Description: 'Put end statement of multiline block on its own line.' Enabled: true Layout/CaseIndentation: Description: 'Indentation of when in a case/when/[else/]end.' StyleGuide: '#indent-when-to-case' Enabled: true Layout/ClosingParenthesisIndentation: Description: 'Checks the indentation of hanging closing parentheses.' Enabled: true Layout/CommentIndentation: Description: 'Indentation of comments.' Enabled: true Layout/DotPosition: Description: 'Checks the position of the dot in multi-line method calls.' StyleGuide: '#consistent-multi-line-chains' Enabled: true Layout/ElseAlignment: Description: 'Align elses and elsifs correctly.' Enabled: true Layout/EmptyLineAfterMagicComment: Description: 'Add an empty line after magic comments to separate them from code.' StyleGuide: '#separate-magic-comments-from-code' Enabled: true Layout/EmptyLineBetweenDefs: Description: 'Use empty lines between defs.' StyleGuide: '#empty-lines-between-methods' Enabled: true Layout/EmptyLines: Description: "Don't use several empty lines in a row." StyleGuide: '#two-or-more-empty-lines' Enabled: true Layout/EmptyLinesAroundAccessModifier: Description: "Keep blank lines around access modifiers." StyleGuide: '#empty-lines-around-access-modifier' Enabled: true Layout/EmptyLinesAroundArguments: Description: "Keeps track of empty lines around method arguments." Enabled: true Layout/EmptyLinesAroundBeginBody: Description: "Keeps track of empty lines around begin-end bodies." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EmptyLinesAroundBlockBody: Description: "Keeps track of empty lines around block bodies." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EmptyLinesAroundClassBody: Description: "Keeps track of empty lines around class bodies." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EmptyLinesAroundExceptionHandlingKeywords: Description: "Keeps track of empty lines around exception handling keywords." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EmptyLinesAroundMethodBody: Description: "Keeps track of empty lines around method bodies." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EmptyLinesAroundModuleBody: Description: "Keeps track of empty lines around module bodies." StyleGuide: '#empty-lines-around-bodies' Enabled: true Layout/EndOfLine: Description: 'Use Unix-style line endings.' StyleGuide: '#crlf' Enabled: true Layout/ExtraSpacing: Description: 'Do not use unnecessary spacing.' Enabled: true Layout/FirstParameterIndentation: Description: 'Checks the indentation of the first parameter in a method call.' Enabled: true Layout/IndentArray: Description: >- Checks the indentation of the first element in an array literal. Enabled: true Layout/IndentAssignment: Description: >- Checks the indentation of the first line of the right-hand-side of a multi-line assignment. Enabled: true Layout/IndentHash: Description: 'Checks the indentation of the first key in a hash literal.' Enabled: true Layout/IndentHeredoc: Description: 'This cops checks the indentation of the here document bodies.' StyleGuide: '#squiggly-heredocs' Enabled: true Layout/IndentationConsistency: Description: 'Keep indentation straight.' StyleGuide: '#spaces-indentation' Enabled: true Layout/IndentationWidth: Description: 'Use 2 spaces for indentation.' StyleGuide: '#spaces-indentation' Enabled: true Layout/InitialIndentation: Description: >- Checks the indentation of the first non-blank non-comment line in a file. Enabled: true Layout/LeadingCommentSpace: Description: 'Comments should start with a space.' StyleGuide: '#hash-space' Enabled: true Layout/MultilineArrayBraceLayout: Description: >- Checks that the closing brace in an array literal is either on the same line as the last array element, or a new line. Enabled: true Layout/MultilineBlockLayout: Description: 'Ensures newlines after multiline block do statements.' Enabled: true Layout/MultilineHashBraceLayout: Description: >- Checks that the closing brace in a hash literal is either on the same line as the last hash element, or a new line. Enabled: true Layout/MultilineMethodCallBraceLayout: Description: >- Checks that the closing brace in a method call is either on the same line as the last method argument, or a new line. Enabled: true Layout/MultilineMethodCallIndentation: Description: >- Checks indentation of method calls with the dot operator that span more than one line. Enabled: true Layout/MultilineMethodDefinitionBraceLayout: Description: >- Checks that the closing brace in a method definition is either on the same line as the last method parameter, or a new line. Enabled: true Layout/MultilineOperationIndentation: Description: >- Checks indentation of binary operations that span more than one line. Enabled: true Layout/RescueEnsureAlignment: Description: 'Align rescues and ensures correctly.' Enabled: true Layout/SpaceAfterColon: Description: 'Use spaces after colons.' StyleGuide: '#spaces-operators' Enabled: true Layout/SpaceAfterComma: Description: 'Use spaces after commas.' StyleGuide: '#spaces-operators' Enabled: true Layout/SpaceAfterMethodName: Description: >- Do not put a space between a method name and the opening parenthesis in a method definition. StyleGuide: '#parens-no-spaces' Enabled: true Layout/SpaceAfterNot: Description: Tracks redundant space after the ! operator. StyleGuide: '#no-space-bang' Enabled: true Layout/SpaceAfterSemicolon: Description: 'Use spaces after semicolons.' StyleGuide: '#spaces-operators' Enabled: true Layout/SpaceAroundBlockParameters: Description: 'Checks the spacing inside and after block parameters pipes.' Enabled: true Layout/SpaceAroundEqualsInParameterDefault: Description: >- Checks that the equals signs in parameter default assignments have or don't have surrounding space depending on configuration. StyleGuide: '#spaces-around-equals' Enabled: true Layout/SpaceAroundKeyword: Description: 'Use a space around keywords if appropriate.' Enabled: true Layout/SpaceAroundOperators: Description: 'Use a single space around operators.' StyleGuide: '#spaces-operators' Enabled: true Layout/SpaceBeforeBlockBraces: Description: >- Checks that the left block brace has or doesn't have space before it. Enabled: true Layout/SpaceBeforeComma: Description: 'No spaces before commas.' Enabled: true Layout/SpaceBeforeComment: Description: >- Checks for missing space between code and a comment on the same line. Enabled: true Layout/SpaceBeforeFirstArg: Description: >- Checks that exactly one space is used between a method name and the first argument for method calls without parentheses. Enabled: true Layout/SpaceBeforeSemicolon: Description: 'No spaces before semicolons.' Enabled: true Layout/SpaceInLambdaLiteral: Description: 'Checks for spaces in lambda literals.' Enabled: true Layout/SpaceInsideArrayLiteralBrackets: Description: 'Checks the spacing inside array literal brackets.' Enabled: true Layout/SpaceInsideArrayPercentLiteral: Description: 'No unnecessary additional spaces between elements in %i/%w literals.' Enabled: true Layout/SpaceInsideBlockBraces: Description: >- Checks that block braces have or don't have surrounding space. For blocks taking parameters, checks that the left brace has or doesn't have trailing space. Enabled: true Layout/SpaceInsideHashLiteralBraces: Description: "Use spaces inside hash literal braces - or don't." StyleGuide: '#spaces-operators' Enabled: true Layout/SpaceInsideParens: Description: 'No spaces after ( or before ).' StyleGuide: '#spaces-braces' Enabled: true Layout/SpaceInsidePercentLiteralDelimiters: Description: 'No unnecessary spaces inside delimiters of %i/%w/%x literals.' Enabled: true Layout/SpaceInsideRangeLiteral: Description: 'No spaces inside range literals.' StyleGuide: '#no-space-inside-range-literals' Enabled: true Layout/SpaceInsideReferenceBrackets: Description: 'Checks the spacing inside referential brackets.' Enabled: true Layout/SpaceInsideStringInterpolation: Description: 'Checks for padding/surrounding spaces inside string interpolation.' StyleGuide: '#string-interpolation' Enabled: true Layout/Tab: Description: 'No hard tabs.' StyleGuide: '#spaces-indentation' Enabled: true Layout/TrailingBlankLines: Description: 'Checks trailing blank lines and final newline.' StyleGuide: '#newline-eof' Enabled: true Layout/TrailingWhitespace: Description: 'Avoid trailing whitespace.' StyleGuide: '#no-trailing-whitespace' Enabled: true #################### Lint ################################## ### Warnings Lint/AmbiguousBlockAssociation: Description: >- Checks for ambiguous block association with method when param passed without parentheses. StyleGuide: '#syntax' Enabled: true Lint/AmbiguousOperator: Description: >- Checks for ambiguous operators in the first argument of a method invocation without parentheses. StyleGuide: '#method-invocation-parens' Enabled: true Lint/AmbiguousRegexpLiteral: Description: >- Checks for ambiguous regexp literals in the first argument of a method invocation without parentheses. Enabled: true Lint/AssignmentInCondition: Description: "Don't use assignment in conditions." StyleGuide: '#safe-assignment-in-condition' Enabled: true Lint/BlockAlignment: Description: 'Align block ends correctly.' Enabled: true Lint/BooleanSymbol: Description: 'Check for `:true` and `:false` symbols.' Enabled: true Lint/CircularArgumentReference: Description: "Default values in optional keyword arguments and optional ordinal arguments should not refer back to the name of the argument." Enabled: true Lint/ConditionPosition: Description: >- Checks for condition placed in a confusing position relative to the keyword. StyleGuide: '#same-line-condition' Enabled: true Lint/Debugger: Description: 'Check for debugger calls.' Enabled: true Lint/DefEndAlignment: Description: 'Align ends corresponding to defs correctly.' Enabled: true Lint/DeprecatedClassMethods: Description: 'Check for deprecated class method calls.' Enabled: true Lint/DuplicateCaseCondition: Description: 'Do not repeat values in case conditionals.' Enabled: true Lint/DuplicateMethods: Description: 'Check for duplicate method definitions.' Enabled: true Lint/DuplicatedKey: Description: 'Check for duplicate keys in hash literals.' Enabled: true Lint/EachWithObjectArgument: Description: 'Check for immutable argument given to each_with_object.' Enabled: true Lint/ElseLayout: Description: 'Check for odd code arrangement in an else block.' Enabled: true Lint/EmptyEnsure: Description: 'Checks for empty ensure block.' Enabled: true AutoCorrect: false Lint/EmptyExpression: Description: 'Checks for empty expressions.' Enabled: true Lint/EmptyInterpolation: Description: 'Checks for empty string interpolation.' Enabled: true Lint/EmptyWhen: Description: 'Checks for `when` branches with empty bodies.' Enabled: true Lint/EndAlignment: Description: 'Align ends correctly.' Enabled: true Lint/EndInMethod: Description: 'END blocks should not be placed inside method definitions.' Enabled: true Lint/EnsureReturn: Description: 'Do not use return in an ensure block.' StyleGuide: '#no-return-ensure' Enabled: true Lint/FloatOutOfRange: Description: >- Catches floating-point literals too large or small for Ruby to represent. Enabled: true Lint/FormatParameterMismatch: Description: 'The number of parameters to format/sprint must match the fields.' Enabled: true Lint/HandleExceptions: Description: "Don't suppress exception." StyleGuide: '#dont-hide-exceptions' Enabled: true Lint/ImplicitStringConcatenation: Description: >- Checks for adjacent string literals on the same line, which could better be represented as a single string literal. Enabled: true Lint/IneffectiveAccessModifier: Description: >- Checks for attempts to use `private` or `protected` to set the visibility of a class method, which does not work. Enabled: true Lint/InheritException: Description: 'Avoid inheriting from the `Exception` class.' Enabled: true Lint/InterpolationCheck: Description: 'Raise warning for interpolation in single q strs' Enabled: true Lint/LiteralAsCondition: Description: 'Checks of literals used in conditions.' Enabled: true Lint/LiteralInInterpolation: Description: 'Checks for literals used in interpolation.' Enabled: true Lint/Loop: Description: >- Use Kernel#loop with break rather than begin/end/until or begin/end/while for post-loop tests. StyleGuide: '#loop-with-break' Enabled: true Lint/MissingCopEnableDirective: Description: 'Checks for a `# rubocop:enable` after `# rubocop:disable`' Enabled: true Lint/MultipleCompare: Description: "Use `&&` operator to compare multiple value." Enabled: true Lint/NestedMethodDefinition: Description: 'Do not use nested method definitions.' StyleGuide: '#no-nested-methods' Enabled: true Lint/NestedPercentLiteral: Description: 'Checks for nested percent literals.' Enabled: true Lint/NextWithoutAccumulator: Description: >- Do not omit the accumulator when calling `next` in a `reduce`/`inject` block. Enabled: true Lint/NonLocalExitFromIterator: Description: 'Do not use return in iterator to cause non-local exit.' Enabled: true Lint/ParenthesesAsGroupedExpression: Description: >- Checks for method calls with a space before the opening parenthesis. StyleGuide: '#parens-no-spaces' Enabled: true Lint/PercentStringArray: Description: >- Checks for unwanted commas and quotes in %w/%W literals. Enabled: true Lint/PercentSymbolArray: Description: >- Checks for unwanted commas and colons in %i/%I literals. Enabled: true Lint/RandOne: Description: >- Checks for `rand(1)` calls. Such calls always return `0` and most likely a mistake. Enabled: true Lint/RedundantWithIndex: Description: 'Checks for redundant `with_index`.' Enabled: true Lint/RedundantWithObject: Description: 'Checks for redundant `with_object`.' Enabled: true Lint/RegexpAsCondition: Description: >- Do not use regexp literal as a condition. The regexp literal matches `$_` implicitly. Enabled: true Lint/RequireParentheses: Description: >- Use parentheses in the method call to avoid confusion about precedence. Enabled: true Lint/RescueException: Description: 'Avoid rescuing the Exception class.' StyleGuide: '#no-blind-rescues' Enabled: true Lint/RescueType: Description: 'Avoid rescuing from non constants that could result in a `TypeError`.' Enabled: true Lint/ReturnInVoidContext: Description: 'Checks for return in void context.' Enabled: true Lint/SafeNavigationChain: Description: 'Do not chain ordinary method call after safe navigation operator.' Enabled: true Lint/ScriptPermission: Description: 'Grant script file execute permission.' Enabled: true Lint/ShadowedArgument: Description: 'Avoid reassigning arguments before they were used.' Enabled: true Lint/ShadowedException: Description: >- Avoid rescuing a higher level exception before a lower level exception. Enabled: true Lint/ShadowingOuterLocalVariable: Description: >- Do not use the same name as outer local variable for block arguments or block local variables. Enabled: true Lint/StringConversionInInterpolation: Description: 'Checks for Object#to_s usage in string interpolation.' StyleGuide: '#no-to-s' Enabled: true Lint/Syntax: Description: 'Checks syntax error' Enabled: true Lint/UnderscorePrefixedVariableName: Description: 'Do not use prefix `_` for a variable that is used.' Enabled: true Lint/UnifiedInteger: Description: 'Use Integer instead of Fixnum or Bignum' Enabled: true Lint/UnneededDisable: Description: >- Checks for rubocop:disable comments that can be removed. Note: this cop is not disabled when disabling all cops. It must be explicitly disabled. Enabled: true Lint/UnneededRequireStatement: Description: 'Checks for unnecessary `require` statement.' Enabled: true Lint/UnneededSplatExpansion: Description: 'Checks for splat unnecessarily being called on literals' Enabled: true Lint/UnreachableCode: Description: 'Unreachable code.' Enabled: true Lint/UnusedBlockArgument: Description: 'Checks for unused block arguments.' StyleGuide: '#underscore-unused-vars' Enabled: true Lint/UnusedMethodArgument: Description: 'Checks for unused method arguments.' StyleGuide: '#underscore-unused-vars' Enabled: true Lint/UriEscapeUnescape: Description: >- `URI.escape` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. Also `URI.unescape` method is obsolete and should not be used. Instead, use `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` depending on your specific use case. Enabled: true Lint/UriRegexp: Description: 'Use `URI::DEFAULT_PARSER.make_regexp` instead of `URI.regexp`.' Enabled: true Lint/UselessAccessModifier: Description: 'Checks for useless access modifiers.' Enabled: true ContextCreatingMethods: [] MethodCreatingMethods: [] Lint/UselessAssignment: Description: 'Checks for useless assignment to a local variable.' StyleGuide: '#underscore-unused-vars' Enabled: true Lint/UselessComparison: Description: 'Checks for comparison of something with itself.' Enabled: true Lint/UselessElseWithoutRescue: Description: 'Checks for useless `else` in `begin..end` without `rescue`.' Enabled: true Lint/UselessSetterCall: Description: 'Checks for useless setter call to a local variable.' Enabled: true Lint/Void: Description: 'Possible use of operator/literal/variable in void context.' Enabled: true #################### Metrics ############################### Metrics/AbcSize: Description: >- A calculated magnitude based on number of assignments, branches, and conditions. Reference: 'http://c2.com/cgi/wiki?AbcMetric' Enabled: true Metrics/BlockLength: Description: 'Avoid long blocks with many lines.' Enabled: true Metrics/BlockNesting: Description: 'Avoid excessive block nesting' StyleGuide: '#three-is-the-number-thou-shalt-count' Enabled: true Metrics/ClassLength: Description: 'Avoid classes longer than 100 lines of code.' Enabled: true Metrics/CyclomaticComplexity: Description: >- A complexity metric that is strongly correlated to the number of test cases needed to validate a method. Enabled: true Metrics/LineLength: Description: 'Limit lines to 80 characters.' StyleGuide: '#80-character-limits' Enabled: true Metrics/MethodLength: Description: 'Avoid methods longer than 10 lines of code.' StyleGuide: '#short-methods' Enabled: true Metrics/ModuleLength: Description: 'Avoid modules longer than 100 lines of code.' Enabled: true Metrics/ParameterLists: Description: 'Avoid parameter lists longer than three or four parameters.' StyleGuide: '#too-many-params' Enabled: true Metrics/PerceivedComplexity: Description: >- A complexity metric geared towards measuring complexity for a human reader. Enabled: true #################### Naming ############################## Naming/AccessorMethodName: Description: Check the naming of accessor methods for get_/set_. StyleGuide: '#accessor_mutator_method_names' Enabled: true Naming/AsciiIdentifiers: Description: 'Use only ascii symbols in identifiers.' StyleGuide: '#english-identifiers' Enabled: true Naming/BinaryOperatorParameterName: Description: 'When defining binary operators, name the argument other.' StyleGuide: '#other-arg' Enabled: true Naming/ClassAndModuleCamelCase: Description: 'Use CamelCase for classes and modules.' StyleGuide: '#camelcase-classes' Enabled: true Naming/ConstantName: Description: 'Constants should use SCREAMING_SNAKE_CASE.' StyleGuide: '#screaming-snake-case' Enabled: true Naming/FileName: Description: 'Use snake_case for source file names.' StyleGuide: '#snake-case-files' Enabled: true Naming/HeredocDelimiterCase: Description: 'Use configured case for heredoc delimiters.' StyleGuide: '#heredoc-delimiters' Enabled: true Naming/HeredocDelimiterNaming: Description: 'Use descriptive heredoc delimiters.' StyleGuide: '#heredoc-delimiters' Enabled: true Naming/MethodName: Description: 'Use the configured style when naming methods.' StyleGuide: '#snake-case-symbols-methods-vars' Enabled: true Naming/PredicateName: Description: 'Check the names of predicate methods.' StyleGuide: '#bool-methods-qmark' Enabled: true Naming/VariableName: Description: 'Use the configured style when naming variables.' StyleGuide: '#snake-case-symbols-methods-vars' Enabled: true Naming/VariableNumber: Description: 'Use the configured style when numbering variables.' Enabled: true #################### Performance ########################### Performance/Caller: Description: >- Use `caller(n..n)` instead of `caller`. Enabled: true Performance/CaseWhenSplat: Description: >- Place `when` conditions that use splat at the end of the list of `when` branches. Enabled: true Performance/Casecmp: Description: >- Use `casecmp` rather than `downcase ==`, `upcase ==`, `== downcase`, or `== upcase`.. Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringcasecmp-vs-stringdowncase---code' Enabled: true Performance/CompareWithBlock: Description: 'Use `sort_by(&:foo)` instead of `sort { |a, b| a.foo <=> b.foo }`.' Enabled: true Performance/Count: Description: >- Use `count` instead of `select...size`, `reject...size`, `select...count`, `reject...count`, `select...length`, and `reject...length`. # This cop has known compatibility issues with `ActiveRecord` and other # frameworks. ActiveRecord's `count` ignores the block that is passed to it. # For more information, see the documentation in the cop itself. # If you understand the known risk, you can disable `SafeMode`. SafeMode: true Enabled: true Performance/Detect: Description: >- Use `detect` instead of `select.first`, `find_all.first`, `select.last`, and `find_all.last`. Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerabledetect-vs-enumerableselectfirst-code' # This cop has known compatibility issues with `ActiveRecord` and other # frameworks. `ActiveRecord` does not implement a `detect` method and `find` # has its own meaning. Correcting `ActiveRecord` methods with this cop # should be considered unsafe. SafeMode: true Enabled: true Performance/DoubleStartEndWith: Description: >- Use `str.{start,end}_with?(x, ..., y, ...)` instead of `str.{start,end}_with?(x, ...) || str.{start,end}_with?(y, ...)`. Enabled: true Performance/EndWith: Description: 'Use `end_with?` instead of a regex match anchored to the end of a string.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringmatch-vs-stringstart_withstringend_with-code-start-code-end' # This will change to a new method call which isn't guaranteed to be on the # object. Switching these methods has to be done with knowledge of the types # of the variables which rubocop doesn't have. AutoCorrect: false Enabled: true Performance/FixedSize: Description: 'Do not compute the size of statically sized objects except in constants' Enabled: true Performance/FlatMap: Description: >- Use `Enumerable#flat_map` instead of `Enumerable#map...Array#flatten(1)` or `Enumberable#collect..Array#flatten(1)` Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablemaparrayflatten-vs-enumerableflat_map-code' Enabled: true EnabledForFlattenWithoutParams: false # If enabled, this cop will warn about usages of # `flatten` being called without any parameters. # This can be dangerous since `flat_map` will only flatten 1 level, and # `flatten` without any parameters can flatten multiple levels. Performance/HashEachMethods: Description: >- Use `Hash#each_key` and `Hash#each_value` instead of `Hash#keys.each` and `Hash#values.each`. StyleGuide: '#hash-each' Enabled: true AutoCorrect: false Performance/LstripRstrip: Description: 'Use `strip` instead of `lstrip.rstrip`.' Enabled: true Performance/RangeInclude: Description: 'Use `Range#cover?` instead of `Range#include?`.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#cover-vs-include-code' Enabled: true Performance/RedundantBlockCall: Description: 'Use `yield` instead of `block.call`.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#proccall-and-block-arguments-vs-yieldcode' Enabled: true Performance/RedundantMatch: Description: >- Use `=~` instead of `String#match` or `Regexp#match` in a context where the returned `MatchData` is not needed. Enabled: true Performance/RedundantMerge: Description: 'Use Hash#[]=, rather than Hash#merge! with a single key-value pair.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#hashmerge-vs-hash-code' Enabled: true Performance/RedundantSortBy: Description: 'Use `sort` instead of `sort_by { |x| x }`.' Enabled: true Performance/RegexpMatch: Description: >- Use `match?` instead of `Regexp#match`, `String#match`, `Symbol#match`, `Regexp#===`, or `=~` when `MatchData` is not used. Enabled: true Performance/ReverseEach: Description: 'Use `reverse_each` instead of `reverse.each`.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#enumerablereverseeach-vs-enumerablereverse_each-code' Enabled: true Performance/Sample: Description: >- Use `sample` instead of `shuffle.first`, `shuffle.last`, and `shuffle[Integer]`. Reference: 'https://github.com/JuanitoFatas/fast-ruby#arrayshufflefirst-vs-arraysample-code' Enabled: true Performance/Size: Description: >- Use `size` instead of `count` for counting the number of elements in `Array` and `Hash`. Reference: 'https://github.com/JuanitoFatas/fast-ruby#arraylength-vs-arraysize-vs-arraycount-code' Enabled: true Performance/StartWith: Description: 'Use `start_with?` instead of a regex match anchored to the beginning of a string.' Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringmatch-vs-stringstart_withstringend_with-code-start-code-end' # This will change to a new method call which isn't guaranteed to be on the # object. Switching these methods has to be done with knowledge of the types # of the variables which rubocop doesn't have. AutoCorrect: false Enabled: true Performance/StringReplacement: Description: >- Use `tr` instead of `gsub` when you are replacing the same number of characters. Use `delete` instead of `gsub` when you are deleting characters. Reference: 'https://github.com/JuanitoFatas/fast-ruby#stringgsub-vs-stringtr-code' Enabled: true Performance/TimesMap: Description: 'Checks for .times.map calls.' AutoCorrect: false Enabled: true Performance/UnfreezeString: Description: 'Use unary plus to get an unfrozen string literal.' Enabled: true Performance/UriDefaultParser: Description: 'Use `URI::DEFAULT_PARSER` instead of `URI::Parser.new`.' Enabled: true #################### Rails ################################# Rails/ActionFilter: Description: 'Enforces consistent use of action filter methods.' Enabled: true Rails/ActiveSupportAliases: Description: >- Avoid ActiveSupport aliases of standard ruby methods: `String#starts_with?`, `String#ends_with?`, `Array#append`, `Array#prepend`. Enabled: true Rails/ApplicationJob: Description: 'Check that jobs subclass ApplicationJob.' Enabled: true Rails/ApplicationRecord: Description: 'Check that models subclass ApplicationRecord.' Enabled: true Rails/Blank: Description: 'Enforce using `blank?` and `present?`.' Enabled: true # Convert checks for `nil` or `empty?` to `blank?` NilOrEmpty: true # Convert usages of not `present?` to `blank?` NotPresent: true # Convert usages of `unless` `present?` to `if` `blank?` UnlessPresent: true Rails/CreateTableWithTimestamps: Description: >- Checks the migration for which timestamps are not included when creating a new table. Enabled: true Rails/Date: Description: >- Checks the correct usage of date aware methods, such as Date.today, Date.current etc. Enabled: true Rails/Delegate: Description: 'Prefer delegate method for delegations.' Enabled: true Rails/DelegateAllowBlank: Description: 'Do not use allow_blank as an option to delegate.' Enabled: true Rails/DynamicFindBy: Description: 'Use `find_by` instead of dynamic `find_by_*`.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#find_by' Enabled: true Rails/EnumUniqueness: Description: 'Avoid duplicate integers in hash-syntax `enum` declaration.' Enabled: true Rails/EnvironmentComparison: Description: "Favor `Rails.env.production?` over `Rails.env == 'production'`" Enabled: true Rails/Exit: Description: >- Favor `fail`, `break`, `return`, etc. over `exit` in application or library code outside of Rake files to avoid exits during unit testing or running in production. Enabled: true Rails/FilePath: Description: 'Use `Rails.root.join` for file path joining.' Enabled: true Rails/FindBy: Description: 'Prefer find_by over where.first.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#find_by' Enabled: true Rails/FindEach: Description: 'Prefer all.find_each over all.find.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#find-each' Enabled: true Rails/HasAndBelongsToMany: Description: 'Prefer has_many :through to has_and_belongs_to_many.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#has-many-through' Enabled: true Rails/HasManyOrHasOneDependent: Description: 'Define the dependent option to the has_many and has_one associations.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#has_many-has_one-dependent-option' Enabled: true Rails/HttpPositionalArguments: Description: 'Use keyword arguments instead of positional arguments in http method calls.' Enabled: true Include: - 'spec/**/*' - 'test/**/*' Rails/InverseOf: Description: 'Checks for associations where the inverse cannot be determined automatically.' Enabled: true Rails/LexicallyScopedActionFilter: Description: "Checks that methods specified in the filter's `only` or `except` options are explicitly defined in the controller." StyleGuide: 'https://github.com/bbatsov/rails-style-guide#lexically-scoped-action-filter' Enabled: true Rails/NotNullColumn: Description: 'Do not add a NOT NULL column without a default value' Enabled: true Rails/Output: Description: 'Checks for calls to puts, print, etc.' Enabled: true Rails/OutputSafety: Description: 'The use of `html_safe` or `raw` may be a security risk.' Enabled: true Rails/PluralizationGrammar: Description: 'Checks for incorrect grammar when using methods like `3.day.ago`.' Enabled: true Rails/Presence: Description: 'Checks code that can be written more easily using `Object#presence` defined by Active Support.' Enabled: true Rails/Present: Description: 'Enforce using `blank?` and `present?`.' Enabled: true NotNilAndNotEmpty: true # Convert checks for not `nil` and not `empty?` to `present?` NotBlank: true # Convert usages of not `blank?` to `present?` UnlessBlank: true # Convert usages of `unless` `blank?` to `if` `present?` Rails/ReadWriteAttribute: Description: >- Checks for read_attribute(:attr) and write_attribute(:attr, val). StyleGuide: 'https://github.com/bbatsov/rails-style-guide#read-attribute' Enabled: true Rails/RedundantReceiverInWithOptions: Description: 'Checks for redundant receiver in `with_options`.' Enabled: true Rails/RelativeDateConstant: Description: 'Do not assign relative date to constants.' Enabled: true Rails/RequestReferer: Description: 'Use consistent syntax for request.referer.' Enabled: true Rails/ReversibleMigration: Description: 'Checks whether the change method of the migration file is reversible.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#reversible-migration' Reference: 'http://api.rubyonrails.org/classes/ActiveRecord/Migration/CommandRecorder.html' Enabled: true Rails/SafeNavigation: Description: "Use Ruby's safe navigation operator (`&.`) instead of `try!`" Enabled: true Rails/ScopeArgs: Description: 'Checks the arguments of ActiveRecord scopes.' Enabled: true Rails/SkipsModelValidations: Description: >- Use methods that skips model validations with caution. See reference for more information. Reference: 'http://guides.rubyonrails.org/active_record_validations.html#skipping-validations' Enabled: true Rails/TimeZone: Description: 'Checks the correct usage of time zone aware methods.' StyleGuide: 'https://github.com/bbatsov/rails-style-guide#time' Reference: 'http://danilenko.org/2012/7/6/rails_timezones' Enabled: true Rails/UniqBeforePluck: Description: 'Prefer the use of uniq or distinct before pluck.' Enabled: true Rails/UnknownEnv: Description: 'Use correct environment name.' Enabled: true Rails/Validation: Description: 'Use validates :attribute, hash of validations.' Enabled: true #################### Security ############################## Security/Eval: Description: 'The use of eval represents a serious security risk.' Enabled: true Security/JSONLoad: Description: >- Prefer usage of `JSON.parse` over `JSON.load` due to potential security issues. See reference for more information. Reference: 'http://ruby-doc.org/stdlib-2.3.0/libdoc/json/rdoc/JSON.html#method-i-load' Enabled: true # Autocorrect here will change to a method that may cause crashes depending # on the value of the argument. AutoCorrect: false Security/MarshalLoad: Description: >- Avoid using of `Marshal.load` or `Marshal.restore` due to potential security issues. See reference for more information. Reference: 'http://ruby-doc.org/core-2.3.3/Marshal.html#module-Marshal-label-Security+considerations' Enabled: true Security/YAMLLoad: Description: >- Prefer usage of `YAML.safe_load` over `YAML.load` due to potential security issues. See reference for more information. Reference: 'https://ruby-doc.org/stdlib-2.3.3/libdoc/yaml/rdoc/YAML.html#module-YAML-label-Security' Enabled: true #################### Style ############################### Style/Alias: Description: 'Use alias instead of alias_method.' StyleGuide: '#alias-method' Enabled: true Style/AndOr: Description: 'Use &&/|| instead of and/or.' StyleGuide: '#no-and-or-or' Enabled: true Style/ArrayJoin: Description: 'Use Array#join instead of Array#*.' StyleGuide: '#array-join' Enabled: true Style/AsciiComments: Description: 'Use only ascii symbols in comments.' StyleGuide: '#english-comments' Enabled: true Style/Attr: Description: 'Checks for uses of Module#attr.' StyleGuide: '#attr' Enabled: true Style/BarePercentLiterals: Description: 'Checks if usage of %() or %Q() matches configuration.' StyleGuide: '#percent-q-shorthand' Enabled: true Style/BeginBlock: Description: 'Avoid the use of BEGIN blocks.' StyleGuide: '#no-BEGIN-blocks' Enabled: true Style/BlockComments: Description: 'Do not use block comments.' StyleGuide: '#no-block-comments' Enabled: true Style/BlockDelimiters: Description: >- Avoid using {...} for multi-line blocks (multiline chaining is always ugly). Prefer {...} over do...end for single-line blocks. StyleGuide: '#single-line-blocks' Enabled: true Style/BracesAroundHashParameters: Description: 'Enforce braces style around hash parameters.' Enabled: true Style/CaseEquality: Description: 'Avoid explicit use of the case equality operator(===).' StyleGuide: '#no-case-equality' Enabled: true Style/CharacterLiteral: Description: 'Checks for uses of character literals.' StyleGuide: '#no-character-literals' Enabled: true Style/ClassAndModuleChildren: Description: 'Checks style of children classes and modules.' StyleGuide: '#namespace-definition' # Moving from compact to nested children requires knowledge of whether the # outer parent is a module or a class. Moving from nested to compact requires # verification that the outer parent is defined elsewhere. Rubocop does not # have the knowledge to perform either operation safely and thus requires # manual oversight. AutoCorrect: false Enabled: true Style/ClassCheck: Description: 'Enforces consistent use of `Object#is_a?` or `Object#kind_of?`.' Enabled: true Style/ClassMethods: Description: 'Use self when defining module/class methods.' StyleGuide: '#def-self-class-methods' Enabled: true Style/ClassVars: Description: 'Avoid the use of class variables.' StyleGuide: '#no-class-vars' Enabled: true Style/ColonMethodCall: Description: 'Do not use :: for method call.' StyleGuide: '#double-colons' Enabled: true Style/ColonMethodDefinition: Description: 'Do not use :: for defining class methods.' StyleGuide: '#colon-method-definition' Enabled: true Style/CommandLiteral: Description: 'Use `` or %x around command literals.' StyleGuide: '#percent-x' Enabled: true Style/CommentAnnotation: Description: >- Checks formatting of special comments (TODO, FIXME, OPTIMIZE, HACK, REVIEW). StyleGuide: '#annotate-keywords' Enabled: true Style/CommentedKeyword: Description: 'Do not place comments on the same line as certain keywords.' Enabled: true Style/ConditionalAssignment: Description: >- Use the return value of `if` and `case` statements for assignment to a variable and variable comparison instead of assigning that variable inside of each branch. Enabled: true Style/DateTime: Description: 'Use Date or Time over DateTime.' StyleGuide: '#date--time' Enabled: true Style/DefWithParentheses: Description: 'Use def with parentheses when there are arguments.' StyleGuide: '#method-parens' Enabled: true Style/Dir: Description: >- Use the `__dir__` method to retrieve the canonicalized absolute path to the current file. Enabled: true Style/Documentation: Description: 'Document classes and non-namespace modules.' Enabled: true Exclude: - 'spec/**/*' - 'test/**/*' Style/DoubleNegation: Description: 'Checks for uses of double negation (!!).' StyleGuide: '#no-bang-bang' Enabled: true Style/EachForSimpleLoop: Description: >- Use `Integer#times` for a simple loop which iterates a fixed number of times. Enabled: true Style/EachWithObject: Description: 'Prefer `each_with_object` over `inject` or `reduce`.' Enabled: true Style/EmptyBlockParameter: Description: 'Omit pipes for empty block parameters.' Enabled: true Style/EmptyCaseCondition: Description: 'Avoid empty condition in case statements.' Enabled: true Style/EmptyElse: Description: 'Avoid empty else-clauses.' Enabled: true Style/EmptyLambdaParameter: Description: 'Omit parens for empty lambda parameters.' Enabled: true Style/EmptyLiteral: Description: 'Prefer literals to Array.new/Hash.new/String.new.' StyleGuide: '#literal-array-hash' Enabled: true Style/EmptyMethod: Description: 'Checks the formatting of empty method definitions.' StyleGuide: '#no-single-line-methods' Enabled: true Style/Encoding: Description: 'Use UTF-8 as the source file encoding.' StyleGuide: '#utf-8' Enabled: true Style/EndBlock: Description: 'Avoid the use of END blocks.' StyleGuide: '#no-END-blocks' Enabled: true Style/EvalWithLocation: Description: 'Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.' Enabled: true Style/EvenOdd: Description: 'Favor the use of Integer#even? && Integer#odd?' StyleGuide: '#predicate-methods' Enabled: true Style/FlipFlop: Description: 'Checks for flip flops' StyleGuide: '#no-flip-flops' Enabled: true Style/For: Description: 'Checks use of for or each in multiline loops.' StyleGuide: '#no-for-loops' Enabled: true Style/FormatString: Description: 'Enforce the use of Kernel#sprintf, Kernel#format or String#%.' StyleGuide: '#sprintf' Enabled: true Style/FormatStringToken: Description: 'Use a consistent style for format string tokens.' Enabled: true Style/FrozenStringLiteralComment: Description: >- Add the frozen_string_literal comment to the top of files to help transition from Ruby 2.3.0 to Ruby 3.0. Enabled: true Style/GlobalVars: Description: 'Do not introduce global variables.' StyleGuide: '#instance-vars' Reference: 'http://www.zenspider.com/Languages/Ruby/QuickRef.html' Enabled: true Style/GuardClause: Description: 'Check for conditionals that can be replaced with guard clauses' StyleGuide: '#no-nested-conditionals' Enabled: true Style/HashSyntax: Description: >- Prefer Ruby 1.9 hash syntax { a: 1, b: 2 } over 1.8 syntax { :a => 1, :b => 2 }. StyleGuide: '#hash-literals' Enabled: true Style/IdenticalConditionalBranches: Description: >- Checks that conditional statements do not have an identical line at the end of each branch, which can validly be moved out of the conditional. Enabled: true Style/IfInsideElse: Description: 'Finds if nodes inside else, which can be converted to elsif.' Enabled: true Style/IfUnlessModifier: Description: >- Favor modifier if/unless usage when you have a single-line body. StyleGuide: '#if-as-a-modifier' Enabled: true Style/IfUnlessModifierOfIfUnless: Description: >- Avoid modifier if/unless usage on conditionals. Enabled: true Style/IfWithSemicolon: Description: 'Do not use if x; .... Use the ternary operator instead.' StyleGuide: '#no-semicolon-ifs' Enabled: true Style/InfiniteLoop: Description: 'Use Kernel#loop for infinite loops.' StyleGuide: '#infinite-loop' Enabled: true Style/InverseMethods: Description: >- Use the inverse method instead of `!.method` if an inverse method is defined. Enabled: true Style/Lambda: Description: 'Use the new lambda literal syntax for single-line blocks.' StyleGuide: '#lambda-multi-line' Enabled: true Style/LambdaCall: Description: 'Use lambda.call(...) instead of lambda.(...).' StyleGuide: '#proc-call' Enabled: true Style/LineEndConcatenation: Description: >- Use \ instead of + or << to concatenate two string literals at line end. Enabled: true Style/MethodCallWithoutArgsParentheses: Description: 'Do not use parentheses for method calls with no arguments.' StyleGuide: '#method-invocation-parens' Enabled: true Style/MethodDefParentheses: Description: >- Checks if the method definitions have or don't have parentheses. StyleGuide: '#method-parens' Enabled: true Style/MethodMissing: Description: 'Avoid using `method_missing`.' StyleGuide: '#no-method-missing' Enabled: true Style/MinMax: Description: >- Use `Enumerable#minmax` instead of `Enumerable#min` and `Enumerable#max` in conjunction.' Enabled: true Style/MixinGrouping: Description: 'Checks for grouping of mixins in `class` and `module` bodies.' StyleGuide: '#mixin-grouping' Enabled: true Style/MixinUsage: Description: 'Checks that `include`, `extend` and `prepend` exists at the top level.' Enabled: true Style/ModuleFunction: Description: 'Checks for usage of `extend self` in modules.' StyleGuide: '#module-function' Enabled: true Style/MultilineBlockChain: Description: 'Avoid multi-line chains of blocks.' StyleGuide: '#single-line-blocks' Enabled: true Style/MultilineIfModifier: Description: 'Only use if/unless modifiers on single line statements.' StyleGuide: '#no-multiline-if-modifiers' Enabled: true Style/MultilineIfThen: Description: 'Do not use then for multi-line if/unless.' StyleGuide: '#no-then' Enabled: true Style/MultilineMemoization: Description: 'Wrap multiline memoizations in a `begin` and `end` block.' Enabled: true Style/MultilineTernaryOperator: Description: >- Avoid multi-line ?: (the ternary operator); use if/unless instead. StyleGuide: '#no-multiline-ternary' Enabled: true Style/MultipleComparison: Description: >- Avoid comparing a variable with multiple items in a conditional, use Array#include? instead. Enabled: true Style/MutableConstant: Description: 'Do not assign mutable objects to constants.' Enabled: true Style/NegatedIf: Description: >- Favor unless over if for negative conditions (or control flow or). StyleGuide: '#unless-for-negatives' Enabled: true Style/NegatedWhile: Description: 'Favor until over while for negative conditions.' StyleGuide: '#until-for-negatives' Enabled: true Style/NestedModifier: Description: 'Avoid using nested modifiers.' StyleGuide: '#no-nested-modifiers' Enabled: true Style/NestedParenthesizedCalls: Description: >- Parenthesize method calls which are nested inside the argument list of another parenthesized method call. Enabled: true Style/NestedTernaryOperator: Description: 'Use one expression per branch in a ternary operator.' StyleGuide: '#no-nested-ternary' Enabled: true Style/Next: Description: 'Use `next` to skip iteration instead of a condition at the end.' StyleGuide: '#no-nested-conditionals' Enabled: true Style/NilComparison: Description: 'Prefer x.nil? to x == nil.' StyleGuide: '#predicate-methods' Enabled: true Style/NonNilCheck: Description: 'Checks for redundant nil checks.' StyleGuide: '#no-non-nil-checks' Enabled: true Style/Not: Description: 'Use ! instead of not.' StyleGuide: '#bang-not-not' Enabled: true Style/NumericLiteralPrefix: Description: 'Use smallcase prefixes for numeric literals.' StyleGuide: '#numeric-literal-prefixes' Enabled: true Style/NumericLiterals: Description: >- Add underscores to large numeric literals to improve their readability. StyleGuide: '#underscores-in-numerics' Enabled: true Style/NumericPredicate: Description: >- Checks for the use of predicate- or comparison methods for numeric comparisons. StyleGuide: '#predicate-methods' # This will change to a new method call which isn't guaranteed to be on the # object. Switching these methods has to be done with knowledge of the types # of the variables which rubocop doesn't have. AutoCorrect: false Enabled: true Style/OneLineConditional: Description: >- Favor the ternary operator(?:) over if/then/else/end constructs. StyleGuide: '#ternary-operator' Enabled: true Style/OptionalArguments: Description: >- Checks for optional arguments that do not appear at the end of the argument list StyleGuide: '#optional-arguments' Enabled: true Style/OrAssignment: Description: 'Recommend usage of double pipe equals (||=) where applicable.' StyleGuide: '#double-pipe-for-uninit' Enabled: true Style/ParallelAssignment: Description: >- Check for simple usages of parallel assignment. It will only warn when the number of variables matches on both sides of the assignment. StyleGuide: '#parallel-assignment' Enabled: true Style/ParenthesesAroundCondition: Description: >- Don't use parentheses around the condition of an if/unless/while. StyleGuide: '#no-parens-around-condition' Enabled: true Style/PercentLiteralDelimiters: Description: 'Use `%`-literal delimiters consistently' StyleGuide: '#percent-literal-braces' Enabled: true Style/PercentQLiterals: Description: 'Checks if uses of %Q/%q match the configured preference.' Enabled: true Style/PerlBackrefs: Description: 'Avoid Perl-style regex back references.' StyleGuide: '#no-perl-regexp-last-matchers' Enabled: true Style/PreferredHashMethods: Description: 'Checks use of `has_key?` and `has_value?` Hash methods.' StyleGuide: '#hash-key' Enabled: true Style/Proc: Description: 'Use proc instead of Proc.new.' StyleGuide: '#proc' Enabled: true Style/RaiseArgs: Description: 'Checks the arguments passed to raise/fail.' StyleGuide: '#exception-class-messages' Enabled: true Style/RandomWithOffset: Description: >- Prefer to use ranges when generating random numbers instead of integers with offsets. StyleGuide: '#random-numbers' Enabled: true Style/RedundantBegin: Description: "Don't use begin blocks when they are not needed." StyleGuide: '#begin-implicit' Enabled: true Style/RedundantConditional: Description: "Don't return true/false from a conditional." Enabled: true Style/RedundantException: Description: "Checks for an obsolete RuntimeException argument in raise/fail." StyleGuide: '#no-explicit-runtimeerror' Enabled: true Style/RedundantFreeze: Description: "Checks usages of Object#freeze on immutable objects." Enabled: true Style/RedundantParentheses: Description: "Checks for parentheses that seem not to serve any purpose." Enabled: true Style/RedundantReturn: Description: "Don't use return where it's not required." StyleGuide: '#no-explicit-return' Enabled: true Style/RedundantSelf: Description: "Don't use self where it's not needed." StyleGuide: '#no-self-unless-required' Enabled: true Style/RegexpLiteral: Description: 'Use / or %r around regular expressions.' StyleGuide: '#percent-r' Enabled: true Style/RescueModifier: Description: 'Avoid using rescue in its modifier form.' StyleGuide: '#no-rescue-modifiers' Enabled: true Style/RescueStandardError: Description: 'Avoid rescuing without specifying an error class.' Enabled: true Style/SafeNavigation: Description: >- This cop transforms usages of a method call safeguarded by a check for the existence of the object to safe navigation (`&.`). Enabled: true Style/SelfAssignment: Description: >- Checks for places where self-assignment shorthand should have been used. StyleGuide: '#self-assignment' Enabled: true Style/Semicolon: Description: "Don't use semicolons to terminate expressions." StyleGuide: '#no-semicolon' Enabled: true Style/SignalException: Description: 'Checks for proper usage of fail and raise.' StyleGuide: '#prefer-raise-over-fail' Enabled: true Style/SingleLineMethods: Description: 'Avoid single-line methods.' StyleGuide: '#no-single-line-methods' Enabled: true Style/SpecialGlobalVars: Description: 'Avoid Perl-style global variables.' StyleGuide: '#no-cryptic-perlisms' Enabled: true Style/StabbyLambdaParentheses: Description: 'Check for the usage of parentheses around stabby lambda arguments.' StyleGuide: '#stabby-lambda-with-args' Enabled: true Style/StderrPuts: Description: 'Use `warn` instead of `$stderr.puts`.' StyleGuide: '#warn' Enabled: true Style/StringLiterals: Description: 'Checks if uses of quotes match the configured preference.' StyleGuide: '#consistent-string-literals' Enabled: true Style/StringLiteralsInInterpolation: Description: >- Checks if uses of quotes inside expressions in interpolated strings match the configured preference. Enabled: true Style/StructInheritance: Description: 'Checks for inheritance from Struct.new.' StyleGuide: '#no-extend-struct-new' Enabled: true Style/SymbolArray: Description: 'Use %i or %I for arrays of symbols.' StyleGuide: '#percent-i' Enabled: true Style/SymbolLiteral: Description: 'Use plain symbols instead of string symbols when possible.' Enabled: true Style/SymbolProc: Description: 'Use symbols as procs instead of blocks when possible.' Enabled: true Style/TernaryParentheses: Description: 'Checks for use of parentheses around ternary conditions.' Enabled: true Style/TrailingBodyOnMethodDefinition: Description: 'Method body goes below definition.' Enabled: true Style/TrailingCommaInArguments: Description: 'Checks for trailing comma in argument lists.' StyleGuide: '#no-trailing-params-comma' Enabled: true Style/TrailingCommaInLiteral: Description: 'Checks for trailing comma in array and hash literals.' StyleGuide: '#no-trailing-array-commas' Enabled: true Style/TrailingMethodEndStatement: Description: 'Checks for trailing end statement on line of method body.' Enabled: true Style/TrailingUnderscoreVariable: Description: >- Checks for the usage of unneeded trailing underscores at the end of parallel variable assignment. AllowNamedUnderscoreVariables: true Enabled: true Style/TrivialAccessors: Description: 'Prefer attr_* methods to trivial readers/writers.' StyleGuide: '#attr_family' Enabled: true Style/UnlessElse: Description: >- Do not use unless with else. Rewrite these with the positive case first. StyleGuide: '#no-else-with-unless' Enabled: true Style/UnneededCapitalW: Description: 'Checks for %W when interpolation is not needed.' Enabled: true Style/UnneededInterpolation: Description: 'Checks for strings that are just an interpolated expression.' Enabled: true Style/UnneededPercentQ: Description: 'Checks for %q/%Q when single quotes or double quotes would do.' StyleGuide: '#percent-q' Enabled: true Style/VariableInterpolation: Description: >- Don't interpolate global, instance and class variables directly in strings. StyleGuide: '#curlies-interpolate' Enabled: true Style/WhenThen: Description: 'Use when x then ... for one-line cases.' StyleGuide: '#one-line-cases' Enabled: true Style/WhileUntilDo: Description: 'Checks for redundant do after while or until.' StyleGuide: '#no-multiline-while-do' Enabled: true Style/WhileUntilModifier: Description: >- Favor modifier while/until usage when you have a single-line body. StyleGuide: '#while-as-a-modifier' Enabled: true Style/WordArray: Description: 'Use %w or %W for arrays of words.' StyleGuide: '#percent-w' Enabled: true Style/YodaCondition: Description: 'Do not use literals as the first operand of a comparison.' Reference: 'https://en.wikipedia.org/wiki/Yoda_conditions' Enabled: true Style/ZeroLengthPredicate: Description: 'Use #empty? when testing for objects of length 0.' Enabled: true rubocop-0.52.1/lib/000077500000000000000000000000001322072016200140115ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop.rb000066400000000000000000000747751322072016200160330ustar00rootroot00000000000000# frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require 'powerpack/array/butfirst' require 'powerpack/enumerable/drop_last' require 'powerpack/hash/symbolize_keys' require 'powerpack/string/blank' require 'powerpack/string/strip_indent' require 'unicode/display_width' require_relative 'rubocop/version' require_relative 'rubocop/path_util' require_relative 'rubocop/platform' require_relative 'rubocop/string_util' require_relative 'rubocop/name_similarity' require_relative 'rubocop/node_pattern' require_relative 'rubocop/string_interpreter' require_relative 'rubocop/ast/sexp' require_relative 'rubocop/ast/node' require_relative 'rubocop/ast/node/mixin/method_identifier_predicates' require_relative 'rubocop/ast/node/mixin/binary_operator_node' require_relative 'rubocop/ast/node/mixin/collection_node' require_relative 'rubocop/ast/node/mixin/conditional_node' require_relative 'rubocop/ast/node/mixin/hash_element_node' require_relative 'rubocop/ast/node/mixin/method_dispatch_node' require_relative 'rubocop/ast/node/mixin/modifier_node' require_relative 'rubocop/ast/node/mixin/parameterized_node' require_relative 'rubocop/ast/node/mixin/predicate_operator_node' require_relative 'rubocop/ast/node/mixin/basic_literal_node' require_relative 'rubocop/ast/node/and_node' require_relative 'rubocop/ast/node/args_node' require_relative 'rubocop/ast/node/array_node' require_relative 'rubocop/ast/node/block_node' require_relative 'rubocop/ast/node/case_node' require_relative 'rubocop/ast/node/def_node' require_relative 'rubocop/ast/node/ensure_node' require_relative 'rubocop/ast/node/for_node' require_relative 'rubocop/ast/node/hash_node' require_relative 'rubocop/ast/node/if_node' require_relative 'rubocop/ast/node/keyword_splat_node' require_relative 'rubocop/ast/node/or_node' require_relative 'rubocop/ast/node/pair_node' require_relative 'rubocop/ast/node/regexp_node' require_relative 'rubocop/ast/node/resbody_node' require_relative 'rubocop/ast/node/send_node' require_relative 'rubocop/ast/node/str_node' require_relative 'rubocop/ast/node/super_node' require_relative 'rubocop/ast/node/symbol_node' require_relative 'rubocop/ast/node/until_node' require_relative 'rubocop/ast/node/when_node' require_relative 'rubocop/ast/node/while_node' require_relative 'rubocop/ast/node/yield_node' require_relative 'rubocop/ast/builder' require_relative 'rubocop/ast/traversal' require_relative 'rubocop/error' require_relative 'rubocop/warning' require_relative 'rubocop/cop/util' require_relative 'rubocop/cop/offense' require_relative 'rubocop/cop/message_annotator' require_relative 'rubocop/cop/ignored_node' require_relative 'rubocop/cop/autocorrect_logic' require_relative 'rubocop/cop/badge' require_relative 'rubocop/cop/registry' require_relative 'rubocop/cop/cop' require_relative 'rubocop/cop/commissioner' require_relative 'rubocop/cop/corrector' require_relative 'rubocop/cop/force' require_relative 'rubocop/cop/severity' require_relative 'rubocop/cop/generator' require_relative 'rubocop/cop/generator/require_file_injector' require_relative 'rubocop/cop/variable_force' require_relative 'rubocop/cop/variable_force/branch' require_relative 'rubocop/cop/variable_force/branchable' require_relative 'rubocop/cop/variable_force/variable' require_relative 'rubocop/cop/variable_force/assignment' require_relative 'rubocop/cop/variable_force/reference' require_relative 'rubocop/cop/variable_force/scope' require_relative 'rubocop/cop/variable_force/variable_table' require_relative 'rubocop/cop/mixin/annotation_comment' require_relative 'rubocop/cop/mixin/array_hash_indentation' require_relative 'rubocop/cop/mixin/array_min_size' require_relative 'rubocop/cop/mixin/array_syntax' require_relative 'rubocop/cop/mixin/alignment' require_relative 'rubocop/cop/mixin/check_assignment' require_relative 'rubocop/cop/mixin/configurable_max' require_relative 'rubocop/cop/mixin/code_length' # relies on configurable_max require_relative 'rubocop/cop/mixin/classish_length' # relies on code_length require_relative 'rubocop/cop/mixin/configurable_enforced_style' require_relative 'rubocop/cop/mixin/configurable_formatting' require_relative 'rubocop/cop/mixin/configurable_naming' require_relative 'rubocop/cop/mixin/configurable_numbering' require_relative 'rubocop/cop/mixin/def_node' require_relative 'rubocop/cop/mixin/documentation_comment' require_relative 'rubocop/cop/mixin/duplication' require_relative 'rubocop/cop/mixin/empty_lines_around_body' require_relative 'rubocop/cop/mixin/empty_parameter' require_relative 'rubocop/cop/mixin/end_keyword_alignment' require_relative 'rubocop/cop/mixin/enforce_superclass' require_relative 'rubocop/cop/mixin/first_element_line_break' require_relative 'rubocop/cop/mixin/frozen_string_literal' require_relative 'rubocop/cop/mixin/hash_alignment' require_relative 'rubocop/cop/mixin/ignored_pattern' require_relative 'rubocop/cop/mixin/integer_node' require_relative 'rubocop/cop/mixin/match_range' require_relative 'rubocop/cop/mixin/method_complexity' require_relative 'rubocop/cop/mixin/method_preference' require_relative 'rubocop/cop/mixin/min_body_length' require_relative 'rubocop/cop/mixin/multiline_expression_indentation' require_relative 'rubocop/cop/mixin/multiline_literal_brace_layout' require_relative 'rubocop/cop/mixin/negative_conditional' require_relative 'rubocop/cop/mixin/heredoc' require_relative 'rubocop/cop/mixin/on_normal_if_unless' require_relative 'rubocop/cop/mixin/ordered_gem_node' require_relative 'rubocop/cop/mixin/parentheses' require_relative 'rubocop/cop/mixin/parser_diagnostic' require_relative 'rubocop/cop/mixin/percent_array' require_relative 'rubocop/cop/mixin/percent_literal' require_relative 'rubocop/cop/mixin/preceding_following_alignment' require_relative 'rubocop/cop/mixin/rescue_node' require_relative 'rubocop/cop/mixin/safe_assignment' require_relative 'rubocop/cop/mixin/safe_mode' require_relative 'rubocop/cop/mixin/space_after_punctuation' require_relative 'rubocop/cop/mixin/space_before_punctuation' require_relative 'rubocop/cop/mixin/surrounding_space' require_relative 'rubocop/cop/mixin/statement_modifier' require_relative 'rubocop/cop/mixin/string_help' require_relative 'rubocop/cop/mixin/string_literals_help' require_relative 'rubocop/cop/mixin/target_ruby_version' require_relative 'rubocop/cop/mixin/target_rails_version' require_relative 'rubocop/cop/mixin/too_many_lines' require_relative 'rubocop/cop/mixin/trailing_comma' require_relative 'rubocop/cop/mixin/unused_argument' require_relative 'rubocop/cop/correctors/alignment_corrector' require_relative 'rubocop/cop/correctors/condition_corrector' require_relative 'rubocop/cop/correctors/empty_line_corrector' require_relative 'rubocop/cop/correctors/multiline_literal_brace_corrector' require_relative 'rubocop/cop/correctors/ordered_gem_corrector' require_relative 'rubocop/cop/correctors/parentheses_corrector' require_relative 'rubocop/cop/correctors/punctuation_corrector' require_relative 'rubocop/cop/correctors/space_corrector' require_relative 'rubocop/cop/correctors/string_literal_corrector' require_relative 'rubocop/cop/correctors/unused_arg_corrector' require_relative 'rubocop/cop/bundler/duplicated_gem' require_relative 'rubocop/cop/bundler/insecure_protocol_source' require_relative 'rubocop/cop/bundler/ordered_gems' require_relative 'rubocop/cop/gemspec/duplicated_assignment' require_relative 'rubocop/cop/gemspec/ordered_dependencies' require_relative 'rubocop/cop/gemspec/required_ruby_version' require_relative 'rubocop/cop/layout/access_modifier_indentation' require_relative 'rubocop/cop/layout/align_array' require_relative 'rubocop/cop/layout/align_hash' require_relative 'rubocop/cop/layout/align_parameters' require_relative 'rubocop/cop/layout/block_end_newline' require_relative 'rubocop/cop/layout/case_indentation' require_relative 'rubocop/cop/layout/class_structure' require_relative 'rubocop/cop/layout/closing_parenthesis_indentation' require_relative 'rubocop/cop/layout/comment_indentation' require_relative 'rubocop/cop/layout/dot_position' require_relative 'rubocop/cop/layout/else_alignment' require_relative 'rubocop/cop/layout/empty_line_after_magic_comment' require_relative 'rubocop/cop/layout/empty_line_between_defs' require_relative 'rubocop/cop/layout/empty_lines_around_access_modifier' require_relative 'rubocop/cop/layout/empty_lines_around_arguments' require_relative 'rubocop/cop/layout/empty_lines_around_begin_body' require_relative 'rubocop/cop/layout/empty_lines_around_block_body' require_relative 'rubocop/cop/layout/empty_lines_around_class_body' require_relative 'rubocop/cop/layout/empty_lines_around_exception_handling_keywords' # rubocop:disable Metrics/LineLength require_relative 'rubocop/cop/layout/empty_lines_around_method_body' require_relative 'rubocop/cop/layout/empty_lines_around_module_body' require_relative 'rubocop/cop/layout/empty_lines' require_relative 'rubocop/cop/layout/end_of_line' require_relative 'rubocop/cop/layout/extra_spacing' require_relative 'rubocop/cop/layout/first_array_element_line_break' require_relative 'rubocop/cop/layout/first_hash_element_line_break' require_relative 'rubocop/cop/layout/first_method_argument_line_break' require_relative 'rubocop/cop/layout/first_method_parameter_line_break' require_relative 'rubocop/cop/layout/first_parameter_indentation' require_relative 'rubocop/cop/layout/indent_array' require_relative 'rubocop/cop/layout/indent_assignment' require_relative 'rubocop/cop/layout/indentation_consistency' require_relative 'rubocop/cop/layout/indentation_width' require_relative 'rubocop/cop/layout/indent_hash' require_relative 'rubocop/cop/layout/indent_heredoc' require_relative 'rubocop/cop/layout/initial_indentation' require_relative 'rubocop/cop/layout/leading_comment_space' require_relative 'rubocop/cop/layout/multiline_array_brace_layout' require_relative 'rubocop/cop/layout/multiline_assignment_layout' require_relative 'rubocop/cop/layout/multiline_block_layout' require_relative 'rubocop/cop/layout/multiline_hash_brace_layout' require_relative 'rubocop/cop/layout/multiline_method_call_brace_layout' require_relative 'rubocop/cop/layout/multiline_method_call_indentation' require_relative 'rubocop/cop/layout/multiline_method_definition_brace_layout' require_relative 'rubocop/cop/layout/multiline_operation_indentation' require_relative 'rubocop/cop/layout/rescue_ensure_alignment' require_relative 'rubocop/cop/layout/space_after_colon' require_relative 'rubocop/cop/layout/space_after_comma' require_relative 'rubocop/cop/layout/space_after_method_name' require_relative 'rubocop/cop/layout/space_after_not' require_relative 'rubocop/cop/layout/space_after_semicolon' require_relative 'rubocop/cop/layout/space_around_block_parameters' require_relative 'rubocop/cop/layout/space_around_equals_in_parameter_default' require_relative 'rubocop/cop/layout/space_around_keyword' require_relative 'rubocop/cop/layout/space_around_operators' require_relative 'rubocop/cop/layout/space_before_block_braces' require_relative 'rubocop/cop/layout/space_before_comma' require_relative 'rubocop/cop/layout/space_before_comment' require_relative 'rubocop/cop/layout/space_before_first_arg' require_relative 'rubocop/cop/layout/space_before_semicolon' require_relative 'rubocop/cop/layout/space_in_lambda_literal' require_relative 'rubocop/cop/layout/space_inside_array_percent_literal' require_relative 'rubocop/cop/layout/space_inside_array_literal_brackets' require_relative 'rubocop/cop/layout/space_inside_block_braces' require_relative 'rubocop/cop/layout/space_inside_hash_literal_braces' require_relative 'rubocop/cop/layout/space_inside_parens' require_relative 'rubocop/cop/layout/space_inside_percent_literal_delimiters' require_relative 'rubocop/cop/layout/space_inside_range_literal' require_relative 'rubocop/cop/layout/space_inside_reference_brackets' require_relative 'rubocop/cop/layout/space_inside_string_interpolation' require_relative 'rubocop/cop/layout/tab' require_relative 'rubocop/cop/layout/trailing_blank_lines' require_relative 'rubocop/cop/layout/trailing_whitespace' require_relative 'rubocop/cop/lint/ambiguous_block_association' require_relative 'rubocop/cop/lint/ambiguous_operator' require_relative 'rubocop/cop/lint/ambiguous_regexp_literal' require_relative 'rubocop/cop/lint/assignment_in_condition' require_relative 'rubocop/cop/lint/block_alignment' require_relative 'rubocop/cop/lint/boolean_symbol' require_relative 'rubocop/cop/lint/circular_argument_reference' require_relative 'rubocop/cop/lint/condition_position' require_relative 'rubocop/cop/lint/debugger' require_relative 'rubocop/cop/lint/def_end_alignment' require_relative 'rubocop/cop/lint/deprecated_class_methods' require_relative 'rubocop/cop/lint/duplicate_case_condition' require_relative 'rubocop/cop/lint/duplicate_methods' require_relative 'rubocop/cop/lint/duplicated_key' require_relative 'rubocop/cop/lint/each_with_object_argument' require_relative 'rubocop/cop/lint/else_layout' require_relative 'rubocop/cop/lint/empty_ensure' require_relative 'rubocop/cop/lint/empty_expression' require_relative 'rubocop/cop/lint/empty_interpolation' require_relative 'rubocop/cop/lint/empty_when' require_relative 'rubocop/cop/lint/end_alignment' require_relative 'rubocop/cop/lint/end_in_method' require_relative 'rubocop/cop/lint/ensure_return' require_relative 'rubocop/cop/lint/float_out_of_range' require_relative 'rubocop/cop/lint/format_parameter_mismatch' require_relative 'rubocop/cop/lint/handle_exceptions' require_relative 'rubocop/cop/lint/implicit_string_concatenation' require_relative 'rubocop/cop/lint/inherit_exception' require_relative 'rubocop/cop/lint/ineffective_access_modifier' require_relative 'rubocop/cop/lint/interpolation_check' require_relative 'rubocop/cop/lint/literal_as_condition' require_relative 'rubocop/cop/lint/literal_in_interpolation' require_relative 'rubocop/cop/lint/loop' require_relative 'rubocop/cop/lint/missing_cop_enable_directive' require_relative 'rubocop/cop/lint/multiple_compare' require_relative 'rubocop/cop/lint/nested_method_definition' require_relative 'rubocop/cop/lint/nested_percent_literal' require_relative 'rubocop/cop/lint/next_without_accumulator' require_relative 'rubocop/cop/lint/non_local_exit_from_iterator' require_relative 'rubocop/cop/lint/parentheses_as_grouped_expression' require_relative 'rubocop/cop/lint/percent_string_array' require_relative 'rubocop/cop/lint/percent_symbol_array' require_relative 'rubocop/cop/lint/rand_one' require_relative 'rubocop/cop/lint/redundant_with_index' require_relative 'rubocop/cop/lint/redundant_with_object' require_relative 'rubocop/cop/lint/regexp_as_condition' require_relative 'rubocop/cop/lint/require_parentheses' require_relative 'rubocop/cop/lint/rescue_exception' require_relative 'rubocop/cop/lint/rescue_type' require_relative 'rubocop/cop/lint/return_in_void_context' require_relative 'rubocop/cop/lint/safe_navigation_chain' require_relative 'rubocop/cop/lint/script_permission' require_relative 'rubocop/cop/lint/shadowed_argument' require_relative 'rubocop/cop/lint/shadowed_exception' require_relative 'rubocop/cop/lint/shadowing_outer_local_variable' require_relative 'rubocop/cop/lint/string_conversion_in_interpolation' require_relative 'rubocop/cop/lint/syntax' require_relative 'rubocop/cop/lint/underscore_prefixed_variable_name' require_relative 'rubocop/cop/lint/unified_integer' require_relative 'rubocop/cop/lint/unneeded_disable' require_relative 'rubocop/cop/lint/unneeded_require_statement' require_relative 'rubocop/cop/lint/unneeded_splat_expansion' require_relative 'rubocop/cop/lint/unreachable_code' require_relative 'rubocop/cop/lint/unused_block_argument' require_relative 'rubocop/cop/lint/unused_method_argument' require_relative 'rubocop/cop/lint/uri_escape_unescape' require_relative 'rubocop/cop/lint/uri_regexp' require_relative 'rubocop/cop/lint/useless_access_modifier' require_relative 'rubocop/cop/lint/useless_assignment' require_relative 'rubocop/cop/lint/useless_comparison' require_relative 'rubocop/cop/lint/useless_else_without_rescue' require_relative 'rubocop/cop/lint/useless_setter_call' require_relative 'rubocop/cop/lint/void' require_relative 'rubocop/cop/metrics/cyclomatic_complexity' # relies on cyclomatic_complexity require_relative 'rubocop/cop/metrics/abc_size' require_relative 'rubocop/cop/metrics/block_length' require_relative 'rubocop/cop/metrics/block_nesting' require_relative 'rubocop/cop/metrics/class_length' require_relative 'rubocop/cop/metrics/line_length' require_relative 'rubocop/cop/metrics/method_length' require_relative 'rubocop/cop/metrics/module_length' require_relative 'rubocop/cop/metrics/parameter_lists' require_relative 'rubocop/cop/metrics/perceived_complexity' require_relative 'rubocop/cop/naming/accessor_method_name' require_relative 'rubocop/cop/naming/ascii_identifiers' require_relative 'rubocop/cop/naming/class_and_module_camel_case' require_relative 'rubocop/cop/naming/constant_name' require_relative 'rubocop/cop/naming/file_name' require_relative 'rubocop/cop/naming/heredoc_delimiter_case' require_relative 'rubocop/cop/naming/heredoc_delimiter_naming' require_relative 'rubocop/cop/naming/method_name' require_relative 'rubocop/cop/naming/binary_operator_parameter_name' require_relative 'rubocop/cop/naming/predicate_name' require_relative 'rubocop/cop/naming/variable_name' require_relative 'rubocop/cop/naming/variable_number' require_relative 'rubocop/cop/performance/caller' require_relative 'rubocop/cop/performance/case_when_splat' require_relative 'rubocop/cop/performance/casecmp' require_relative 'rubocop/cop/performance/count' require_relative 'rubocop/cop/performance/detect' require_relative 'rubocop/cop/performance/double_start_end_with' require_relative 'rubocop/cop/performance/end_with' require_relative 'rubocop/cop/performance/fixed_size' require_relative 'rubocop/cop/performance/flat_map' require_relative 'rubocop/cop/performance/hash_each_methods' require_relative 'rubocop/cop/performance/lstrip_rstrip' require_relative 'rubocop/cop/performance/range_include' require_relative 'rubocop/cop/performance/redundant_block_call' require_relative 'rubocop/cop/performance/redundant_match' require_relative 'rubocop/cop/performance/redundant_merge' require_relative 'rubocop/cop/performance/redundant_sort_by' require_relative 'rubocop/cop/performance/regexp_match' require_relative 'rubocop/cop/performance/reverse_each' require_relative 'rubocop/cop/performance/sample' require_relative 'rubocop/cop/performance/size' require_relative 'rubocop/cop/performance/compare_with_block' require_relative 'rubocop/cop/performance/start_with' require_relative 'rubocop/cop/performance/string_replacement' require_relative 'rubocop/cop/performance/times_map' require_relative 'rubocop/cop/performance/unfreeze_string' require_relative 'rubocop/cop/performance/uri_default_parser' require_relative 'rubocop/cop/style/alias' require_relative 'rubocop/cop/style/and_or' require_relative 'rubocop/cop/style/array_join' require_relative 'rubocop/cop/style/ascii_comments' require_relative 'rubocop/cop/style/attr' require_relative 'rubocop/cop/style/auto_resource_cleanup' require_relative 'rubocop/cop/style/bare_percent_literals' require_relative 'rubocop/cop/style/begin_block' require_relative 'rubocop/cop/style/block_comments' require_relative 'rubocop/cop/style/block_delimiters' require_relative 'rubocop/cop/style/braces_around_hash_parameters' require_relative 'rubocop/cop/style/case_equality' require_relative 'rubocop/cop/style/character_literal' require_relative 'rubocop/cop/style/class_and_module_children' require_relative 'rubocop/cop/style/class_check' require_relative 'rubocop/cop/style/class_methods' require_relative 'rubocop/cop/style/class_vars' require_relative 'rubocop/cop/style/collection_methods' require_relative 'rubocop/cop/style/colon_method_call' require_relative 'rubocop/cop/style/colon_method_definition' require_relative 'rubocop/cop/style/command_literal' require_relative 'rubocop/cop/style/comment_annotation' require_relative 'rubocop/cop/style/commented_keyword' require_relative 'rubocop/cop/style/conditional_assignment' require_relative 'rubocop/cop/style/copyright' require_relative 'rubocop/cop/style/date_time' require_relative 'rubocop/cop/style/def_with_parentheses' require_relative 'rubocop/cop/style/dir' require_relative 'rubocop/cop/style/documentation_method' require_relative 'rubocop/cop/style/documentation' require_relative 'rubocop/cop/style/double_negation' require_relative 'rubocop/cop/style/each_for_simple_loop' require_relative 'rubocop/cop/style/each_with_object' require_relative 'rubocop/cop/style/empty_block_parameter' require_relative 'rubocop/cop/style/empty_case_condition' require_relative 'rubocop/cop/style/empty_else' require_relative 'rubocop/cop/style/empty_lambda_parameter' require_relative 'rubocop/cop/style/empty_literal' require_relative 'rubocop/cop/style/empty_method' require_relative 'rubocop/cop/style/encoding' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/eval_with_location' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/style/for' require_relative 'rubocop/cop/style/format_string' require_relative 'rubocop/cop/style/format_string_token' require_relative 'rubocop/cop/style/frozen_string_literal_comment' require_relative 'rubocop/cop/style/global_vars' require_relative 'rubocop/cop/style/guard_clause' require_relative 'rubocop/cop/style/hash_syntax' require_relative 'rubocop/cop/style/identical_conditional_branches' require_relative 'rubocop/cop/style/if_inside_else' require_relative 'rubocop/cop/style/if_unless_modifier' require_relative 'rubocop/cop/style/if_unless_modifier_of_if_unless' require_relative 'rubocop/cop/style/if_with_semicolon' require_relative 'rubocop/cop/style/implicit_runtime_error' require_relative 'rubocop/cop/style/infinite_loop' require_relative 'rubocop/cop/style/inverse_methods' require_relative 'rubocop/cop/style/inline_comment' require_relative 'rubocop/cop/style/lambda' require_relative 'rubocop/cop/style/lambda_call' require_relative 'rubocop/cop/style/line_end_concatenation' require_relative 'rubocop/cop/style/method_call_without_args_parentheses' require_relative 'rubocop/cop/style/method_call_with_args_parentheses' require_relative 'rubocop/cop/style/method_called_on_do_end_block' require_relative 'rubocop/cop/style/method_def_parentheses' require_relative 'rubocop/cop/style/method_missing' require_relative 'rubocop/cop/style/min_max' require_relative 'rubocop/cop/style/missing_else' require_relative 'rubocop/cop/style/mixin_grouping' require_relative 'rubocop/cop/style/mixin_usage' require_relative 'rubocop/cop/style/module_function' require_relative 'rubocop/cop/style/multiline_block_chain' require_relative 'rubocop/cop/style/multiline_if_then' require_relative 'rubocop/cop/style/multiline_if_modifier' require_relative 'rubocop/cop/style/multiline_memoization' require_relative 'rubocop/cop/style/multiline_ternary_operator' require_relative 'rubocop/cop/style/multiple_comparison' require_relative 'rubocop/cop/style/mutable_constant' require_relative 'rubocop/cop/style/negated_if' require_relative 'rubocop/cop/style/negated_while' require_relative 'rubocop/cop/style/nested_modifier' require_relative 'rubocop/cop/style/nested_parenthesized_calls' require_relative 'rubocop/cop/style/nested_ternary_operator' require_relative 'rubocop/cop/style/next' require_relative 'rubocop/cop/style/nil_comparison' require_relative 'rubocop/cop/style/non_nil_check' require_relative 'rubocop/cop/style/not' require_relative 'rubocop/cop/style/numeric_literals' require_relative 'rubocop/cop/style/numeric_literal_prefix' require_relative 'rubocop/cop/style/numeric_predicate' require_relative 'rubocop/cop/style/one_line_conditional' require_relative 'rubocop/cop/style/or_assignment' require_relative 'rubocop/cop/style/option_hash' require_relative 'rubocop/cop/style/optional_arguments' require_relative 'rubocop/cop/style/parallel_assignment' require_relative 'rubocop/cop/style/parentheses_around_condition' require_relative 'rubocop/cop/style/percent_literal_delimiters' require_relative 'rubocop/cop/style/percent_q_literals' require_relative 'rubocop/cop/style/perl_backrefs' require_relative 'rubocop/cop/style/preferred_hash_methods' require_relative 'rubocop/cop/style/proc' require_relative 'rubocop/cop/style/raise_args' require_relative 'rubocop/cop/style/random_with_offset' require_relative 'rubocop/cop/style/redundant_begin' require_relative 'rubocop/cop/style/redundant_exception' require_relative 'rubocop/cop/style/redundant_freeze' require_relative 'rubocop/cop/style/redundant_parentheses' require_relative 'rubocop/cop/style/redundant_return' require_relative 'rubocop/cop/style/redundant_self' require_relative 'rubocop/cop/style/redundant_conditional' require_relative 'rubocop/cop/style/regexp_literal' require_relative 'rubocop/cop/style/rescue_modifier' require_relative 'rubocop/cop/style/rescue_standard_error' require_relative 'rubocop/cop/style/return_nil' require_relative 'rubocop/cop/style/safe_navigation' require_relative 'rubocop/cop/style/self_assignment' require_relative 'rubocop/cop/style/semicolon' require_relative 'rubocop/cop/style/send' require_relative 'rubocop/cop/style/signal_exception' require_relative 'rubocop/cop/style/single_line_block_params' require_relative 'rubocop/cop/style/single_line_methods' require_relative 'rubocop/cop/style/special_global_vars' require_relative 'rubocop/cop/style/stabby_lambda_parentheses' require_relative 'rubocop/cop/style/stderr_puts' require_relative 'rubocop/cop/style/string_hash_keys' require_relative 'rubocop/cop/style/string_literals' require_relative 'rubocop/cop/style/string_literals_in_interpolation' require_relative 'rubocop/cop/style/string_methods' require_relative 'rubocop/cop/style/struct_inheritance' require_relative 'rubocop/cop/style/symbol_array' require_relative 'rubocop/cop/style/symbol_literal' require_relative 'rubocop/cop/style/symbol_proc' require_relative 'rubocop/cop/style/ternary_parentheses' require_relative 'rubocop/cop/style/trailing_body_on_method_definition' require_relative 'rubocop/cop/style/trailing_comma_in_arguments' require_relative 'rubocop/cop/style/trailing_comma_in_literal' require_relative 'rubocop/cop/style/trailing_method_end_statement' require_relative 'rubocop/cop/style/trailing_underscore_variable' require_relative 'rubocop/cop/style/trivial_accessors' require_relative 'rubocop/cop/style/unless_else' require_relative 'rubocop/cop/style/unneeded_capital_w' require_relative 'rubocop/cop/style/unneeded_interpolation' require_relative 'rubocop/cop/style/unneeded_percent_q' require_relative 'rubocop/cop/style/variable_interpolation' require_relative 'rubocop/cop/style/when_then' require_relative 'rubocop/cop/style/while_until_do' require_relative 'rubocop/cop/style/while_until_modifier' require_relative 'rubocop/cop/style/word_array' require_relative 'rubocop/cop/style/yoda_condition' require_relative 'rubocop/cop/style/zero_length_predicate' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/rails/active_support_aliases' require_relative 'rubocop/cop/rails/application_job' require_relative 'rubocop/cop/rails/application_record' require_relative 'rubocop/cop/rails/blank' require_relative 'rubocop/cop/rails/create_table_with_timestamps' require_relative 'rubocop/cop/rails/date' require_relative 'rubocop/cop/rails/dynamic_find_by' require_relative 'rubocop/cop/rails/delegate' require_relative 'rubocop/cop/rails/delegate_allow_blank' require_relative 'rubocop/cop/rails/enum_uniqueness' require_relative 'rubocop/cop/rails/environment_comparison' require_relative 'rubocop/cop/rails/exit' require_relative 'rubocop/cop/rails/file_path' require_relative 'rubocop/cop/rails/find_by' require_relative 'rubocop/cop/rails/find_each' require_relative 'rubocop/cop/rails/has_and_belongs_to_many' require_relative 'rubocop/cop/rails/has_many_or_has_one_dependent' require_relative 'rubocop/cop/rails/http_positional_arguments' require_relative 'rubocop/cop/rails/inverse_of' require_relative 'rubocop/cop/rails/lexically_scoped_action_filter' require_relative 'rubocop/cop/rails/not_null_column' require_relative 'rubocop/cop/rails/output_safety' require_relative 'rubocop/cop/rails/output' require_relative 'rubocop/cop/rails/pluralization_grammar' require_relative 'rubocop/cop/rails/presence' require_relative 'rubocop/cop/rails/present' require_relative 'rubocop/cop/rails/read_write_attribute' require_relative 'rubocop/cop/rails/redundant_receiver_in_with_options' require_relative 'rubocop/cop/rails/request_referer' require_relative 'rubocop/cop/rails/reversible_migration' require_relative 'rubocop/cop/rails/relative_date_constant' require_relative 'rubocop/cop/rails/safe_navigation' require_relative 'rubocop/cop/rails/save_bang' require_relative 'rubocop/cop/rails/scope_args' require_relative 'rubocop/cop/rails/skips_model_validations' require_relative 'rubocop/cop/rails/time_zone' require_relative 'rubocop/cop/rails/uniq_before_pluck' require_relative 'rubocop/cop/rails/unknown_env' require_relative 'rubocop/cop/rails/validation' require_relative 'rubocop/cop/security/eval' require_relative 'rubocop/cop/security/json_load' require_relative 'rubocop/cop/security/marshal_load' require_relative 'rubocop/cop/security/yaml_load' require_relative 'rubocop/cop/team' require_relative 'rubocop/formatter/base_formatter' require_relative 'rubocop/formatter/simple_text_formatter' # relies on simple text require_relative 'rubocop/formatter/clang_style_formatter' require_relative 'rubocop/formatter/disabled_config_formatter' require_relative 'rubocop/formatter/disabled_lines_formatter' require_relative 'rubocop/formatter/emacs_style_formatter' require_relative 'rubocop/formatter/file_list_formatter' require_relative 'rubocop/formatter/fuubar_style_formatter' require_relative 'rubocop/formatter/html_formatter' require_relative 'rubocop/formatter/json_formatter' require_relative 'rubocop/formatter/offense_count_formatter' require_relative 'rubocop/formatter/progress_formatter' require_relative 'rubocop/formatter/quiet_formatter' require_relative 'rubocop/formatter/tap_formatter' require_relative 'rubocop/formatter/worst_offenders_formatter' require_relative 'rubocop/formatter/formatter_set' require_relative 'rubocop/cached_data' require_relative 'rubocop/config' require_relative 'rubocop/config_loader_resolver' require_relative 'rubocop/config_loader' require_relative 'rubocop/config_store' require_relative 'rubocop/target_finder' require_relative 'rubocop/token' require_relative 'rubocop/comment_config' require_relative 'rubocop/magic_comment' require_relative 'rubocop/processed_source' require_relative 'rubocop/result_cache' require_relative 'rubocop/runner' require_relative 'rubocop/cli' require_relative 'rubocop/options' require_relative 'rubocop/remote_config' rubocop-0.52.1/lib/rubocop/000077500000000000000000000000001322072016200154625ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/ast/000077500000000000000000000000001322072016200162515ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/ast/builder.rb000066400000000000000000000044051322072016200202270ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # `RuboCop::Builder` is an AST builder that is utilized to let `Parser` # generate ASTs with {RuboCop::AST::Node}. # # @example # buffer = Parser::Source::Buffer.new('(string)') # buffer.source = 'puts :foo' # # builder = RuboCop::Builder.new # parser = Parser::CurrentRuby.new(builder) # root_node = parser.parse(buffer) class Builder < Parser::Builders::Default NODE_MAP = { AndNode => [:and], ArgsNode => [:args], ArrayNode => [:array], BlockNode => [:block], CaseNode => [:case], DefNode => %i[def defs], EnsureNode => [:ensure], ForNode => [:for], HashNode => [:hash], IfNode => [:if], KeywordSplatNode => [:kwsplat], OrNode => [:or], PairNode => [:pair], RegexpNode => [:regexp], ResbodyNode => [:resbody], SendNode => %i[csend send], StrNode => %i[str dstr xstr], SuperNode => %i[super zsuper], SymbolNode => [:sym], UntilNode => %i[until until_post], WhenNode => [:when], WhileNode => %i[while while_post], YieldNode => [:yield] }.freeze # Generates {Node} from the given information. # # @return [Node] the generated node def n(type, children, source_map) node_klass(type).new(type, children, location: source_map) end # TODO: Figure out what to do about literal encoding handling... # More details here https://github.com/whitequark/parser/issues/283 def string_value(token) value(token) end private def node_klass(type) node_map[type] || Node end # Take the human readable constant and generate a hash map where each # (mapped) node type is a key with its constant as the value. def node_map @node_map ||= begin NODE_MAP.each_pair.each_with_object({}) do |(klass, types), map| types.each { |type| map[type] = klass } end end end end end end rubocop-0.52.1/lib/rubocop/ast/node.rb000066400000000000000000000504551322072016200175340ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # `RuboCop::AST::Node` is a subclass of `Parser::AST::Node`. It provides # access to parent nodes and an object-oriented way to traverse an AST with # the power of `Enumerable`. # # It has predicate methods for every node type, like this: # # @example # node.send_type? # Equivalent to: `node.type == :send` # node.op_asgn_type? # Equivalent to: `node.type == :op_asgn` # # # Non-word characters (other than a-zA-Z0-9_) in type names are omitted. # node.defined_type? # Equivalent to: `node.type == :defined?` # # # Find the first lvar node under the receiver node. # lvar_node = node.each_descendant.find(&:lvar_type?) # class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength include RuboCop::AST::Sexp extend NodePattern::Macros # <=> isn't included here, because it doesn't return a boolean. COMPARISON_OPERATORS = %i[== === != <= >= > <].freeze ARITHMETIC_OPERATORS = %i[+ - * / % **].freeze TRUTHY_LITERALS = %i[str dstr xstr int float sym dsym array hash regexp true irange erange complex rational regopt].freeze FALSEY_LITERALS = %i[false nil].freeze LITERALS = (TRUTHY_LITERALS + FALSEY_LITERALS).freeze COMPOSITE_LITERALS = %i[dstr xstr dsym array hash irange erange regexp].freeze BASIC_LITERALS = (LITERALS - COMPOSITE_LITERALS).freeze MUTABLE_LITERALS = %i[str dstr xstr array hash].freeze IMMUTABLE_LITERALS = (LITERALS - MUTABLE_LITERALS).freeze VARIABLES = %i[ivar gvar cvar lvar].freeze REFERENCES = %i[nth_ref back_ref].freeze KEYWORDS = %i[alias and break case class def defs defined? kwbegin do else ensure for if module next not or postexe redo rescue retry return self super zsuper then undef until when while yield].freeze OPERATOR_KEYWORDS = %i[and or].freeze SPECIAL_KEYWORDS = %w[__FILE__ __LINE__ __ENCODING__].freeze # @see http://rubydoc.info/gems/ast/AST/Node:initialize def initialize(type, children = [], properties = {}) @mutable_attributes = {} # ::AST::Node#initialize freezes itself. super # #parent= may be invoked multiple times for a node because there are # pending nodes while constructing AST and they are replaced later. # For example, `lvar` and `send` type nodes are initially created as an # `ident` type node and fixed to the appropriate type later. # So, the #parent attribute needs to be mutable. each_child_node do |child_node| child_node.parent = self unless child_node.complete? end end Parser::Meta::NODE_TYPES.each do |node_type| method_name = "#{node_type.to_s.gsub(/\W/, '')}_type?" define_method(method_name) do type == node_type end end # Returns the parent node, or `nil` if the receiver is a root node. # # @return [Node, nil] the parent node or `nil` def parent @mutable_attributes[:parent] end def parent=(node) @mutable_attributes[:parent] = node end def complete! @mutable_attributes.freeze each_child_node(&:complete!) end def complete? @mutable_attributes.frozen? end protected :parent= # Override `AST::Node#updated` so that `AST::Processor` does not try to # mutate our ASTs. Since we keep references from children to parents and # not just the other way around, we cannot update an AST and share # identical subtrees. Rather, the entire AST must be copied any time any # part of it is changed. def updated(type = nil, children = nil, properties = {}) properties[:location] ||= @location self.class.new(type || @type, children || @children, properties) end # Returns the index of the receiver node in its siblings. (Sibling index # uses zero based numbering.) # # @return [Integer] the index of the receiver node in its siblings def sibling_index parent.children.index { |sibling| sibling.equal?(self) } end # Calls the given block for each ancestor node from parent to root. # If no block is given, an `Enumerator` is returned. # # @overload each_ancestor # Yield all nodes. # @overload each_ancestor(type) # Yield only nodes matching the type. # @param [Symbol] type a node type # @overload each_ancestor(type_a, type_b, ...) # Yield only nodes matching any of the types. # @param [Symbol] type_a a node type # @param [Symbol] type_b a node type # @overload each_ancestor(types) # Yield only nodes matching any of types in the array. # @param [Array] types an array containing node types # @yieldparam [Node] node each ancestor node # @return [self] if a block is given # @return [Enumerator] if no block is given def each_ancestor(*types, &block) return to_enum(__method__, *types) unless block_given? visit_ancestors(types, &block) self end # Returns an array of ancestor nodes. # This is a shorthand for `node.each_ancestor.to_a`. # # @return [Array] an array of ancestor nodes def ancestors each_ancestor.to_a end # Calls the given block for each child node. # If no block is given, an `Enumerator` is returned. # # Note that this is different from `node.children.each { |child| ... }` # which yields all children including non-node elements. # # @overload each_child_node # Yield all nodes. # @overload each_child_node(type) # Yield only nodes matching the type. # @param [Symbol] type a node type # @overload each_child_node(type_a, type_b, ...) # Yield only nodes matching any of the types. # @param [Symbol] type_a a node type # @param [Symbol] type_b a node type # @overload each_child_node(types) # Yield only nodes matching any of types in the array. # @param [Array] types an array containing node types # @yieldparam [Node] node each child node # @return [self] if a block is given # @return [Enumerator] if no block is given def each_child_node(*types) return to_enum(__method__, *types) unless block_given? children.each do |child| next unless child.is_a?(Node) yield child if types.empty? || types.include?(child.type) end self end # Returns an array of child nodes. # This is a shorthand for `node.each_child_node.to_a`. # # @return [Array] an array of child nodes def child_nodes each_child_node.to_a end # Calls the given block for each descendant node with depth first order. # If no block is given, an `Enumerator` is returned. # # @overload each_descendant # Yield all nodes. # @overload each_descendant(type) # Yield only nodes matching the type. # @param [Symbol] type a node type # @overload each_descendant(type_a, type_b, ...) # Yield only nodes matching any of the types. # @param [Symbol] type_a a node type # @param [Symbol] type_b a node type # @overload each_descendant(types) # Yield only nodes matching any of types in the array. # @param [Array] types an array containing node types # @yieldparam [Node] node each descendant node # @return [self] if a block is given # @return [Enumerator] if no block is given def each_descendant(*types, &block) return to_enum(__method__, *types) unless block_given? visit_descendants(types, &block) self end # Returns an array of descendant nodes. # This is a shorthand for `node.each_descendant.to_a`. # # @return [Array] an array of descendant nodes def descendants each_descendant.to_a end # Calls the given block for the receiver and each descendant node in # depth-first order. # If no block is given, an `Enumerator` is returned. # # This method would be useful when you treat the receiver node as the root # of a tree and want to iterate over all nodes in the tree. # # @overload each_node # Yield all nodes. # @overload each_node(type) # Yield only nodes matching the type. # @param [Symbol] type a node type # @overload each_node(type_a, type_b, ...) # Yield only nodes matching any of the types. # @param [Symbol] type_a a node type # @param [Symbol] type_b a node type # @overload each_node(types) # Yield only nodes matching any of types in the array. # @param [Array] types an array containing node types # @yieldparam [Node] node each node # @return [self] if a block is given # @return [Enumerator] if no block is given def each_node(*types, &block) return to_enum(__method__, *types) unless block_given? yield self if types.empty? || types.include?(type) visit_descendants(types, &block) self end def source loc.expression.source end def source_range loc.expression end def first_line loc.line end def last_line loc.last_line end def line_count return 0 unless source_range source_range.last_line - source_range.first_line + 1 end def nonempty_line_count source.lines.grep(/\S/).size end def source_length source_range ? source_range.size : 0 end ## Destructuring def_node_matcher :receiver, <<-PATTERN {(send $_ ...) (block (send $_ ...) ...)} PATTERN def_node_matcher :method_name, <<-PATTERN {(send _ $_ ...) (block (send _ $_ ...) ...)} PATTERN # Note: for masgn, #asgn_rhs will be an array node def_node_matcher :asgn_rhs, '[assignment? (... $_)]' def_node_matcher :str_content, '(str $_)' def const_name return unless const_type? namespace, name = *self if namespace && !namespace.cbase_type? "#{namespace.const_name}::#{name}" else name.to_s end end def_node_matcher :defined_module0, <<-PATTERN {(class (const $_ $_) ...) (module (const $_ $_) ...) (casgn $_ $_ (send (const nil? {:Class :Module}) :new ...)) (casgn $_ $_ (block (send (const nil? {:Class :Module}) :new ...) ...))} PATTERN private :defined_module0 def defined_module namespace, name = *defined_module0 s(:const, namespace, name) if name end def defined_module_name (const = defined_module) && const.const_name end ## Searching the AST def parent_module_name # what class or module is this method/constant/etc definition in? # returns nil if answer cannot be determined ancestors = each_ancestor(:class, :module, :sclass, :casgn, :block) result = ancestors.map do |ancestor| parent_module_name_part(ancestor) { |full_name| return full_name } end.compact.reverse.join('::') result.empty? ? 'Object' : result end ## Predicates def multiline? line_count > 1 end def single_line? line_count == 1 end def empty_source? source_length.zero? end def asgn_method_call? !COMPARISON_OPERATORS.include?(method_name) && method_name.to_s.end_with?('='.freeze) end def arithmetic_operation? ARITHMETIC_OPERATORS.include?(method_name) end def_node_matcher :equals_asgn?, <<-PATTERN {lvasgn ivasgn cvasgn gvasgn casgn masgn} PATTERN def_node_matcher :shorthand_asgn?, '{op_asgn or_asgn and_asgn}' def_node_matcher :assignment?, <<-PATTERN {equals_asgn? shorthand_asgn? asgn_method_call?} PATTERN def literal? LITERALS.include?(type) end def basic_literal? BASIC_LITERALS.include?(type) end def truthy_literal? TRUTHY_LITERALS.include?(type) end def falsey_literal? FALSEY_LITERALS.include?(type) end def mutable_literal? MUTABLE_LITERALS.include?(type) end def immutable_literal? IMMUTABLE_LITERALS.include?(type) end %i[literal basic_literal].each do |kind| recursive_kind = :"recursive_#{kind}?" kind_filter = :"#{kind}?" define_method(recursive_kind) do case type when :send receiver, method_name, *args = *self [*COMPARISON_OPERATORS, :!, :<=>].include?(method_name) && receiver.send(recursive_kind) && args.all?(&recursive_kind) when :begin, :pair, *OPERATOR_KEYWORDS, *COMPOSITE_LITERALS children.all?(&recursive_kind) else send(kind_filter) end end end def variable? VARIABLES.include?(type) end def reference? REFERENCES.include?(type) end def keyword? return true if special_keyword? || keyword_not? return false unless KEYWORDS.include?(type) !OPERATOR_KEYWORDS.include?(type) || loc.operator.is?(type.to_s) end def special_keyword? SPECIAL_KEYWORDS.include?(source) end def operator_keyword? OPERATOR_KEYWORDS.include?(type) end def keyword_not? _receiver, method_name, *args = *self args.empty? && method_name == :! && loc.selector.is?('not'.freeze) end def keyword_bang? _receiver, method_name, *args = *self args.empty? && method_name == :! && loc.selector.is?('!'.freeze) end def unary_operation? return false unless loc.respond_to?(:selector) && loc.selector Cop::Util.operator?(loc.selector.source.to_sym) && source_range.begin_pos == loc.selector.begin_pos end def binary_operation? return false unless loc.respond_to?(:selector) && loc.selector Cop::Util.operator?(method_name) && source_range.begin_pos != loc.selector.begin_pos end def chained? return false unless argument? receiver, _method_name, *_args = *parent equal?(receiver) end def argument? parent && parent.send_type? end def numeric_type? int_type? || float_type? end def_node_matcher :guard_clause?, <<-PATTERN [{(send nil? {:raise :fail} ...) return break next} single_line?] PATTERN def_node_matcher :proc?, <<-PATTERN {(block (send nil? :proc) ...) (block (send (const nil? :Proc) :new) ...) (send (const nil? :Proc) :new)} PATTERN def_node_matcher :lambda?, '(block (send nil? :lambda) ...)' def_node_matcher :lambda_or_proc?, '{lambda? proc?}' def_node_matcher :class_constructor?, <<-PATTERN { (send (const nil? {:Class :Module}) :new ...) (block (send (const nil? {:Class :Module}) :new ...) ...)} PATTERN def_node_matcher :module_definition?, <<-PATTERN {class module (casgn _ _ class_constructor?)} PATTERN # Some expressions are evaluated for their value, some for their side # effects, and some for both # If we know that an expression is useful only for its side effects, that # means we can transform it in ways which preserve the side effects, but # change the return value # So, does the return value of this node matter? If we changed it to # `(...; nil)`, might that affect anything? # # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity def value_used? # Be conservative and return true if we're not sure. return false if parent.nil? case parent.type when :array, :defined?, :dstr, :dsym, :eflipflop, :erange, :float, :hash, :iflipflop, :irange, :not, :pair, :regexp, :str, :sym, :when, :xstr parent.value_used? when :begin, :kwbegin begin_value_used? when :for for_value_used? when :case, :if case_if_value_used? when :while, :until, :while_post, :until_post while_until_value_used? else true end end # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity # Some expressions are evaluated for their value, some for their side # effects, and some for both. # If we know that expressions are useful only for their return values, # and have no side effects, that means we can reorder them, change the # number of times they are evaluated, or replace them with other # expressions which are equivalent in value. # So, is evaluation of this node free of side effects? # def pure? # Be conservative and return false if we're not sure case type when :__FILE__, :__LINE__, :const, :cvar, :defined?, :false, :float, :gvar, :int, :ivar, :lvar, :nil, :str, :sym, :true, :regopt true when :and, :array, :begin, :case, :dstr, :dsym, :eflipflop, :ensure, :erange, :for, :hash, :if, :iflipflop, :irange, :kwbegin, :not, :or, :pair, :regexp, :until, :until_post, :when, :while, :while_post child_nodes.all?(&:pure?) else false end end protected def visit_descendants(types, &block) each_child_node do |child| yield child if types.empty? || types.include?(child.type) child.visit_descendants(types, &block) end end private def visit_ancestors(types) last_node = self while (current_node = last_node.parent) yield current_node if types.empty? || types.include?(current_node.type) last_node = current_node end end def begin_value_used? # the last child node determines the value of the parent sibling_index == parent.children.size - 1 ? parent.value_used? : false end def for_value_used? # `for var in enum; body; end` # (for ) sibling_index == 2 ? parent.value_used? : true end def case_if_value_used? # (case ) # (if ) sibling_index.zero? ? true : parent.value_used? end def while_until_value_used? # (while ) -> always evaluates to `nil` sibling_index.zero? end def parent_module_name_part(node) case node.type when :class, :module, :casgn # TODO: if constant name has cbase (leading ::), then we don't need # to keep traversing up through nested classes/modules node.defined_module_name when :sclass yield parent_module_name_for_sclass(node) else # block parent_module_name_for_block(node) { yield nil } end end def parent_module_name_for_sclass(sclass_node) # TODO: look for constant definition and see if it is nested # inside a class or module subject = sclass_node.children[0] if subject.const_type? "#" elsif subject.self_type? "#" end end def parent_module_name_for_block(ancestor) if ancestor.method_name == :class_eval # `class_eval` with no receiver applies to whatever module or class # we are currently in return unless (receiver = ancestor.receiver) yield unless receiver.const_type? receiver.const_name elsif !new_class_or_module_block?(ancestor) yield end end def_node_matcher :new_class_or_module_block?, <<-PATTERN ^(casgn _ _ (block (send (const _ {:Class :Module}) :new) ...)) PATTERN end end end rubocop-0.52.1/lib/rubocop/ast/node/000077500000000000000000000000001322072016200171765ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/ast/node/and_node.rb000066400000000000000000000022271322072016200212750ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `until` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `until` nodes within RuboCop. class AndNode < Node include BinaryOperatorNode include PredicateOperatorNode # Returns the alternate operator of the `and` as a string. # Returns `and` for `&&` and vice versa. # # @return [String] the alternate of the `and` operator def alternate_operator logical_operator? ? SEMANTIC_AND : LOGICAL_AND end # Returns the inverse keyword of the `and` node as a string. # Returns `||` for `&&` and `or` for `and`. # # @return [String] the inverse of the `and` operator def inverse_operator logical_operator? ? LOGICAL_OR : SEMANTIC_OR end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `and` predicate def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/args_node.rb000066400000000000000000000012761322072016200214720ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `args` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `args` nodes within RuboCop. class ArgsNode < Node include CollectionNode # It returns true if arguments are empty, and delimiters do not exist. # @example: # # true # def x; end # x { } # -> {} # # # false # def x(); end # def x a; end # x { || } # -> () {} # -> a {} def empty_and_without_delimiters? loc.expression.nil? end end end end rubocop-0.52.1/lib/rubocop/ast/node/array_node.rb000066400000000000000000000033171322072016200216520ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `array` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `array` nodes within RuboCop. class ArrayNode < Node PERCENT_LITERAL_TYPES = { string: /^%[wW]/, symbol: /^%[iI]/ }.freeze # Returns an array of all value nodes in the `array` literal. # # @return [Array] an array of value nodes def values each_child_node.to_a end # Checks whether the `array` literal is delimited by square brackets. # # @return [Boolean] whether the array is enclosed in square brackets def square_brackets? loc.begin && loc.begin.is?('[') end # Checks whether the `array` literal is delimited by percent brackets. # # @overload percent_literal? # Check for any percent literal. # # @overload percent_literal?(type) # Check for percent literal of type `type`. # # @param type [Symbol] an optional percent literal type # # @return [Boolean] whether the array is enclosed in percent brackets def percent_literal?(type = nil) if type loc.begin && loc.begin.source =~ PERCENT_LITERAL_TYPES[type] else loc.begin && loc.begin.source.start_with?('%') end end # Checks whether the `array` literal is delimited by either percent or # square brackets # # @return [Boolean] whether the array is enclosed in percent or square # brackets def bracketed? square_brackets? || percent_literal? end end end end rubocop-0.52.1/lib/rubocop/ast/node/block_node.rb000066400000000000000000000066531322072016200216340ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `block` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `send` nodes within RuboCop. # # A `block` node is essentially a method send with a block. Parser nests # the `send` node inside the `block` node. class BlockNode < Node VOID_CONTEXT_METHODS = %i[each].freeze # The `send` node associated with this block. # # @return [SendNode] the `send` node associated with the `block` node def send_node node_parts[0] end # The arguments of this block. # # @return [Array] def arguments node_parts[1] end # The body of this block. # # @return [Node, nil] the body of the `block` node or `nil` def body node_parts[2] end # Checks whether this block takes any arguments. # # @return [Boolean] whether this `block` node takes any arguments def arguments? !arguments.empty? end # Checks whether the `block` literal is delimited by curly braces. # # @return [Boolean] whether the `block` literal is enclosed in braces def braces? loc.end && loc.end.is?('}') end # Checks whether the `block` literal is delimited by `do`-`end` keywords. # # @return [Boolean] whether the `block` literal is enclosed in `do`-`end` def keywords? loc.end && loc.end.is?('end') end # The delimiters for this `block` literal. # # @return [Array] the delimiters for the `block` literal def delimiters [loc.begin.source, loc.end.source].freeze end # The opening delimiter for this `block` literal. # # @return [String] the opening delimiter for the `block` literal def opening_delimiter delimiters.first end # The closing delimiter for this `block` literal. # # @return [String] the closing delimiter for the `block` literal def closing_delimiter delimiters.last end # Checks whether this is a single line block. This is overridden here # because the general version in `Node` does not work for `block` nodes. # # @return [Boolean] whether the `block` literal is on a single line def single_line? loc.begin.line == loc.end.line end # Checks whether this is a multiline block. This is overridden here # because the general version in `Node` does not work for `block` nodes. # # @return [Boolean] whether the `block` literal is on a several lines def multiline? !single_line? end # Checks whether this `block` literal belongs to a lambda. # # @return [Boolean] whether the `block` literal belongs to a lambda def lambda? send_node.method?(:lambda) end # Checks whether this node body is a void context. # # @return [Boolean] whether the `block` node body is a void context def void_context? VOID_CONTEXT_METHODS.include?(send_node.method_name) end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `block` node def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/case_node.rb000066400000000000000000000035061322072016200214470ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `case` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `case` nodes within RuboCop. class CaseNode < Node include ConditionalNode # Returns the keyword of the `case` statement as a string. # # @return [String] the keyword of the `case` statement def keyword 'case' end # Calls the given block for each `when` node in the `case` statement. # If no block is given, an `Enumerator` is returned. # # @return [self] if a block is given # @return [Enumerator] if no block is given def each_when return when_branches.to_enum(__method__) unless block_given? when_branches.each do |condition| yield condition end self end # Returns an array of all the when branches in the `case` statement. # # @return [Array] an array of `when` nodes def when_branches node_parts[1...-1] end # Returns the else branch of the `case` statement, if any. # # @return [Node] the else branch node of the `case` statement # @return [nil] if the case statement does not have an else branch. def else_branch node_parts[-1] end # Checks whether this case statement has an `else` branch. # # @return [Boolean] whether the `case` statement has an `else` branch def else? loc.else end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `case` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/def_node.rb000066400000000000000000000041071322072016200212700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `def` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `def` nodes within RuboCop. class DefNode < Node include ParameterizedNode include MethodIdentifierPredicates # Checks whether this node body is a void context. # # @return [Boolean] whether the `def` node body is a void context def void_context? method?(:initialize) || assignment_method? end # The name of the defined method as a symbol. # # @return [Symbol] the name of the defined method def method_name node_parts[2] end # An array containing the arguments of the method definition. # # @return [Array] the arguments of the method definition def arguments node_parts[1] end # The body of the method definition. # # @note this can be either a `begin` node, if the method body contains # multiple expressions, or any other node, if it contains a single # expression. # # @return [Node] the body of the method definition def body node_parts[0] end # The receiver of the method definition, if any. # # @return [Node, nil] the receiver of the method definition, or `nil`. def receiver node_parts[3] end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # In this case, the `def` node destructures into: # # `method_name, arguments, body` # # while the `defs` node destructures into: # # `receiver, method_name, arguments, body` # # so we reverse the destructured array to get the optional receiver # at the end, where it can be discarded. # # @return [Array] the different parts of the `def` or `defs` node def node_parts to_a.reverse end end end end rubocop-0.52.1/lib/rubocop/ast/node/ensure_node.rb000066400000000000000000000013211322072016200220260ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `ensure` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `ensure` nodes within RuboCop. class EnsureNode < Node # Returns the body of the `ensure` clause. # # @return [Node, nil] The body of the `ensure`. def body node_parts[1] end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `ensure` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/for_node.rb000066400000000000000000000032201322072016200213130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `for` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `for` nodes within RuboCop. class ForNode < Node # Returns the keyword of the `for` statement as a string. # # @return [String] the keyword of the `until` statement def keyword 'for' end # Checks whether the `for` node has a `do` keyword. # # @return [Boolean] whether the `for` node has a `do` keyword def do? loc.begin && loc.begin.is?('do') end # Checks whether this node body is a void context. # Always `true` for `for`. # # @return [true] whether the `for` node body is a void context def void_context? true end # Returns the iteration variable of the `for` loop. # # @return [Node] The iteration variable of the `for` loop def variable node_parts[0] end # Returns the collection the `for` loop is iterating over. # # @return [Node] The collection the `for` loop is iterating over def collection node_parts[1] end # Returns the body of the `for` loop. # # @return [Node, nil] The body of the `for` loop. def body node_parts[2] end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `until` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/hash_node.rb000066400000000000000000000062701322072016200214600ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `hash` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `hash` nodes within RuboCop. class HashNode < Node # Returns an array of all the key value pairs in the `hash` literal. # # @return [Array] an array of `pair` nodes def pairs each_pair.to_a end # Checks whether the `hash` node contains any `pair`- or `kwsplat` nodes. # # @return[Boolean] whether the `hash` is empty def empty? children.empty? end # Calls the given block for each `pair` node in the `hash` literal. # If no block is given, an `Enumerator` is returned. # # @return [self] if a block is given # @return [Enumerator] if no block is given def each_pair return each_child_node(:pair).to_enum unless block_given? each_child_node(:pair) do |pair| yield(*pair) end self end # Returns an array of all the keys in the `hash` literal. # # @return [Array] an array of keys in the `hash` literal def keys each_key.to_a end # Calls the given block for each `key` node in the `hash` literal. # If no block is given, an `Enumerator` is returned. # # @return [self] if a block is given # @return [Enumerator] if no block is given def each_key return pairs.map(&:key).to_enum unless block_given? pairs.map(&:key).each do |key| yield key end self end # Returns an array of all the values in the `hash` literal. # # @return [Array] an array of values in the `hash` literal def values each_pair.map(&:value) end # Calls the given block for each `value` node in the `hash` literal. # If no block is given, an `Enumerator` is returned. # # @return [self] if a block is given # @return [Enumerator] if no block is given def each_value return pairs.map(&:value).to_enum unless block_given? pairs.map(&:value).each do |value| yield value end self end # Checks whether any of the key value pairs in the `hash` literal are on # the same line. # # @note A multiline `pair` is considered to be on the same line if it # shares any of its lines with another `pair` # # @return [Boolean] whether any `pair` nodes are on the same line def pairs_on_same_line? pairs.each_cons(2).any? { |first, second| first.same_line?(second) } end # Checks whether this `hash` uses a mix of hash rocket and colon # delimiters for its pairs. # # @return [Boolean] whether the `hash` uses mixed delimiters def mixed_delimiters? pairs.map(&:delimiter).uniq.size > 1 end # Checks whether the `hash` literal is delimited by curly braces. # # @return [Boolean] whether the `hash` literal is enclosed in braces def braces? loc.end && loc.end.is?('}') end end end end rubocop-0.52.1/lib/rubocop/ast/node/if_node.rb000066400000000000000000000107501322072016200211310ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `if` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `if` nodes within RuboCop. class IfNode < Node include ConditionalNode include ModifierNode # Checks whether this node is an `if` statement. (This is not true of # ternary operators and `unless` statements.) # # @return [Boolean] whether the node is an `if` statement def if? keyword == 'if' end # Checks whether this node is an `unless` statement. (This is not true # of ternary operators and `if` statements.) # # @return [Boolean] whether the node is an `unless` statement def unless? keyword == 'unless' end # Checks whether the `if` is an `elsif`. Parser handles these by nesting # `if` nodes in the `else` branch. # # @return [Boolean] whether the node is an `elsif` def elsif? keyword == 'elsif' end # Checks whether the `if` node has an `else` clause. # # @note This returns `true` for nodes containing an `elsif` clause. # This is legacy behavior, and many cops rely on it. # # @return [Boolean] whether the node has an `else` clause def else? loc.respond_to?(:else) && loc.else end # Checks whether the `if` node is a ternary operator. # # @return [Boolean] whether the `if` node is a ternary operator def ternary? loc.respond_to?(:question) end # Returns the keyword of the `if` statement as a string. Returns an empty # string for ternary operators. # # @return [String] the keyword of the `if` statement def keyword ternary? ? '' : loc.keyword.source end # Returns the inverse keyword of the `if` node as a string. Returns `if` # for `unless` nodes and vice versa. Returns an empty string for ternary # operators. # # @return [String] the inverse keyword of the `if` statement def inverse_keyword if keyword == 'if' 'unless' elsif keyword == 'unless' 'if' else '' end end # Checks whether the `if` node is in a modifier form, i.e. a condition # trailing behind an expression. Only `if` and `unless` nodes without # other branches can be modifiers. # # @return [Boolean] whether the `if` node is a modifier def modifier_form? (if? || unless?) && super end # Chacks whether the `if` node has nested `if` nodes in any of its # branches. # # @note This performs a shallow search. # # @return [Boolean] whether the `if` node contains nested conditionals def nested_conditional? node_parts[1..2].compact.each do |branch| branch.each_node(:if) do |nested| return true unless nested.elsif? end end false end # Checks whether the `if` node has at least one `elsif` branch. Returns # true if this `if` node itself is an `elsif`. # # @return [Boolean] whether the `if` node has at least one `elsif` branch def elsif_conditional? else_branch && else_branch.if_type? && else_branch.elsif? end # Returns the branch of the `if` node that gets evaluated when its # condition is truthy. # # @note This is normalized for `unless` nodes. # # @return [Node] the truthy branch node of the `if` node # @return [nil] if the truthy branch is empty def if_branch node_parts[1] end # Returns the branch of the `if` node that gets evaluated when its # condition is falsey. # # @note This is normalized for `unless` nodes. # # @return [Node] the falsey branch node of the `if` node # @return [nil] when there is no else branch def else_branch node_parts[2] end # Custom destructuring method. This is used to normalize the branches # for `if` and `unless` nodes, to aid comparisons and conversions. # # @return [Array] the different parts of the `if` statement def node_parts if unless? condition, false_branch, true_branch = *self else condition, true_branch, false_branch = *self end [condition, true_branch, false_branch] end end end end rubocop-0.52.1/lib/rubocop/ast/node/keyword_splat_node.rb000066400000000000000000000022611322072016200234200ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `kwsplat` nodes. This will be used in place of a # plain node when the builder constructs the AST, making its methods # available to all `kwsplat` nodes within RuboCop. class KeywordSplatNode < Node include HashElementNode DOUBLE_SPLAT = '**'.freeze # This is used for duck typing with `pair` nodes which also appear as # `hash` elements. # # @return [false] def hash_rocket? false end # This is used for duck typing with `pair` nodes which also appear as # `hash` elements. # # @return [false] def colon? false end # Returns the operator for the `kwsplat` as a string. # # @return [String] the double splat operator def operator DOUBLE_SPLAT end # Custom destructuring method. This is used to normalize the branches # for `pair` and `kwsplat` nodes, to add duck typing to `hash` elements. # # @return [Array] the different parts of the `kwsplat` def node_parts [self, self] end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/000077500000000000000000000000001322072016200203225ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/ast/node/mixin/basic_literal_node.rb000066400000000000000000000005341322072016200244530ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for primitive literal nodes: `sym`, `str`, # `int`, `float`, ... module BasicLiteralNode # Returns the value of the literal. # # @return [mixed] the value of the literal def value node_parts[0] end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/binary_operator_node.rb000066400000000000000000000010671322072016200250570ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that are binary operations: # `or`, `and` ... module BinaryOperatorNode # Returns the left hand side node of the binary operation. # # @return [Node] the left hand side of the binary operation def lhs node_parts[0] end # Returns the right hand side node of the binary operation. # # @return [Node] the right hand side of the binary operation def rhs node_parts[1] end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/collection_node.rb000066400000000000000000000005221322072016200240060ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A mixin that helps give collection nodes array polymorphism. module CollectionNode extend Forwardable ARRAY_METHODS = (Array.instance_methods - Object.instance_methods - [:to_a]).freeze def_delegators :to_a, *ARRAY_METHODS end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/conditional_node.rb000066400000000000000000000026471322072016200241700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that have conditions: # `if`, `while`, `until`, `case`. # This currently doesn't include `when` nodes, because they have multiple # conditions, and need to be checked for that. module ConditionalNode # Checks whether the condition of the node is written on a single line. # # @return [Boolean] whether the condition is on a single line def single_line_condition? loc.keyword.line == condition.source_range.line end # Checks whether the condition of the node is written on more than # one line. # # @return [Boolean] whether the condition is on more than one line def multiline_condition? !single_line_condition? end # Returns the condition of the node. This works together with each node's # custom destructuring method to select the correct part of the node. # # @return [Node, nil] the condition of the node def condition node_parts[0] end # Returns the body associated with the condition. This works together with # each node's custom destructuring method to select the correct part of # the node. # # @note For `if` nodes, this is the truthy branch. # # @return [Node, nil] the body of the node def body node_parts[1] end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/hash_element_node.rb000066400000000000000000000071501322072016200243130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that can be used as hash elements: # `pair`, `kwsplat` module HashElementNode # Returns the key of this `hash` element. # # @note For keyword splats, this returns the whole node # # @return [Node] the key of the hash element def key node_parts[0] end # Returns the value of this `hash` element. # # @note For keyword splats, this returns the whole node # # @return [Node] the value of the hash element def value node_parts[1] end # Checks whether this `hash` element is on the same line as `other`. # # @note A multiline element is considered to be on the same line if it # shares any of its lines with `other` # # @return [Boolean] whether this element is on the same line as `other` def same_line?(other) loc.last_line == other.loc.line || loc.line == other.loc.last_line end # Returns the delta between this pair's key and the argument pair's. # # @note Keys on the same line always return a delta of 0 # @note Keyword splats always return a delta of 0 for right alignment # # @param [Symbol] alignment whether to check the left or right side # @return [Integer] the delta between the two keys def key_delta(other, alignment = :left) HashElementDelta.new(self, other).key_delta(alignment) end # Returns the delta between this element's value and the argument's. # # @note Keyword splats always return a delta of 0 # # @return [Integer] the delta between the two values def value_delta(other) HashElementDelta.new(self, other).value_delta end # Returns the delta between this element's delimiter and the argument's. # # @note Pairs with different delimiter styles return a delta of 0 # # @return [Integer] the delta between the two delimiters def delimiter_delta(other) HashElementDelta.new(self, other).delimiter_delta end # A helper class for comparing the positions of different parts of a # `pair` node. class HashElementDelta def initialize(first, second) @first = first @second = second raise ArgumentError unless valid_argument_types? end def key_delta(alignment = :left) return 0 if first.same_line?(second) return 0 if keyword_splat? && alignment == :right delta(first.key.loc, second.key.loc, alignment) end def value_delta return 0 if first.same_line?(second) return 0 if keyword_splat? delta(first.value.loc, second.value.loc) end def delimiter_delta return 0 if first.same_line?(second) return 0 if first.delimiter != second.delimiter delta(first.loc.operator, second.loc.operator) end private attr_reader :first, :second def valid_argument_types? [first, second].all? do |argument| argument.pair_type? || argument.kwsplat_type? end end def delta(first, second, alignment = :left) case alignment when :left first.column - second.column when :right first.last_column - second.last_column else 0 end end def keyword_splat? [first, second].any?(&:kwsplat_type?) end end private_constant :HashElementDelta end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/method_dispatch_node.rb000066400000000000000000000127351322072016200250230ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that are a kind of method dispatch: # `send`, `csend`, `super`, `zsuper`, `yield` module MethodDispatchNode extend NodePattern::Macros include MethodIdentifierPredicates # The receiving node of the method dispatch. # # @return [Node, nil] the receiver of the dispatched method or `nil` def receiver node_parts[0] end # The name of the dispatched method as a symbol. # # @return [Symbol] the name of the dispatched method def method_name node_parts[1] end # An array containing the arguments of the dispatched method. # # @return [Array] the arguments of the dispatched method def arguments node_parts[2..-1] end # Checks whether the dispatched method is a macro method. A macro method # is defined as a method that sits in a class, module, or block body and # has an implicit receiver. # # @note This does not include DSLs that use nested blocks, like RSpec # # @return [Boolean] whether the dispatched method is a macro method def macro? !receiver && macro_scope? end # Checks whether the dispatched method is a bare access modifier affects # all methods defined after the macro. # # @return [Boolean] whether the dispatched method is access modifier def access_modifier? macro? && bare_access_modifier? end # Checks whether the name of the dispatched method matches the argument # and has an implicit receiver. # # @param [Symbol, String] name the method name to check for # @return [Boolean] whether the method name matches the argument def command?(name) !receiver && method?(name) end # Checks whether the dispatched method is a setter method. # # @return [Boolean] whether the dispatched method is a setter def setter_method? loc.respond_to?(:operator) && loc.operator end # Checks whether the dispatched method uses a dot to connect the # receiver and the method name. # # This is useful for comparison operators, which can be called either # with or without a dot, i.e. `foo == bar` or `foo.== bar`. # # @return [Boolean] whether the method was called with a connecting dot def dot? loc.respond_to?(:dot) && loc.dot && loc.dot.is?('.') end # Checks whether the dispatched method uses a double colon to connect the # receiver and the method name. # # @return [Boolean] whether the method was called with a connecting dot def double_colon? loc.respond_to?(:dot) && loc.dot && loc.dot.is?('::') end # Checks whether the *explicit* receiver of this method dispatch is # `self`. # # @return [Boolean] whether the receiver of this method dispatch is `self` def self_receiver? receiver && receiver.self_type? end # Checks whether the *explicit* receiver of this method dispatch is a # `const` node. # # @return [Boolean] whether the receiver of this method dispatch # is a `const` node def const_receiver? receiver && receiver.const_type? end # Checks whether the method dispatch is the implicit form of `#call`, # e.g. `foo.(bar)`. # # @return [Boolean] whether the method is the implicit form of `#call` def implicit_call? method?(:call) && !loc.selector end # Whether this method dispatch has an explicit block. # # @return [Boolean] whether the dispatched method has a block def block_literal? parent && parent.block_type? && eql?(parent.send_node) end # The `block` node associated with this method dispatch, if any. # # @return [BlockNode, nil] the `block` node associated with this method # call or `nil` def block_node parent if block_literal? end # Checks if this node is part of a chain of `def` modifiers. # # @example # # private def foo; end # # @return [Boolean] whether the dispatched method is a `def` modifier def def_modifier? send_type? && [self, *each_descendant(:send)].any?(&:adjacent_def_modifier?) end private def_node_matcher :macro_scope?, <<-PATTERN {^{({sclass class module block} ...) class_constructor?} ^^{({sclass class module block} ... (begin ...)) class_constructor?} ^#macro_kwbegin_wrapper? #root_node?} PATTERN # Check if a node's parent is a kwbegin wrapper within a macro scope # # @param parent [Node] parent of the node being checked # # @return [Boolean] true if the parent is a kwbegin in a macro scope def macro_kwbegin_wrapper?(parent) parent.kwbegin_type? && macro_scope?(parent) end # Check if a node does not have a parent # # @param node [Node] # # @return [Boolean] if the parent is nil def root_node?(node) node.parent.nil? end def_node_matcher :adjacent_def_modifier?, <<-PATTERN (send nil? _ ({def defs} ...)) PATTERN def_node_matcher :bare_access_modifier?, <<-PATTERN (send nil? {:public :protected :private :module_function}) PATTERN end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb000066400000000000000000000055761322072016200265510ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common predicates for nodes that reference method identifiers: # `send`, `csend`, `def`, `defs`, `super`, `zsuper` # # @note this mixin expects `#method_name` and `#receiver` to be implemented module MethodIdentifierPredicates ENUMERATOR_METHODS = %i[collect collect_concat detect downto each find find_all find_index inject loop map! map reduce reject reject! reverse_each select select! times upto].freeze # Checks whether the method name matches the argument. # # @param [Symbol, String] name the method name to check for # @return [Boolean] whether the method name matches the argument def method?(name) method_name == name.to_sym end # Checks whether the method is an operator method. # # @return [Boolean] whether the method is an operator def operator_method? RuboCop::Cop::Util::OPERATOR_METHODS.include?(method_name) end # Checks whether the method is a comparison method. # # @return [Boolean] whether the method is a comparison def comparison_method? Node::COMPARISON_OPERATORS.include?(method_name) end # Checks whether the method is an assignment method. # # @return [Boolean] whether the method is an assignment def assignment_method? !comparison_method? && method_name.to_s.end_with?('=') end # Checks whether the method is an enumerator method. # # @return [Boolean] whether the method is an enumerator def enumerator_method? ENUMERATOR_METHODS.include?(method_name) || method_name.to_s.start_with?('each_') end # Checks whether the method is a predicate method. # # @return [Boolean] whether the method is a predicate method def predicate_method? method_name.to_s.end_with?('?') end # Checks whether the method is a bang method. # # @return [Boolean] whether the method is a bang method def bang_method? method_name.to_s.end_with?('!') end # Checks whether the method is a camel case method, # e.g. `Integer()`. # # @return [Boolean] whether the method is a camel case method def camel_case_method? method_name.to_s =~ /\A[A-Z]/ end # Checks whether the *explicit* receiver of this node is `self`. # # @return [Boolean] whether the receiver of this node is `self` def self_receiver? receiver && receiver.self_type? end # Checks whether the *explicit* receiver of node is a `const` node. # # @return [Boolean] whether the receiver of this node is a `const` node def const_receiver? receiver && receiver.const_type? end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/modifier_node.rb000066400000000000000000000006561322072016200234610ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that can be used as modifiers: # `if`, `while`, `until` module ModifierNode # Checks whether the node is in a modifier form, i.e. a condition # trailing behind an expression. # # @return [Boolean] whether the node is a modifier def modifier_form? loc.end.nil? end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/parameterized_node.rb000066400000000000000000000035401322072016200245120ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that are parameterized: # `send`, `super`, `zsuper`, `def`, `defs` module ParameterizedNode # Checks whether this node's arguments are wrapped in parentheses. # # @return [Boolean] whether this node's arguments are # wrapped in parentheses def parenthesized? loc.end && loc.end.is?(')') end # A shorthand for getting the first argument of the node. # Equivalent to `arguments.first`. # # @return [Node, nil] the first argument of the node, # or `nil` if there are no arguments def first_argument arguments[0] end # A shorthand for getting the last argument of the node. # Equivalent to `arguments.last`. # # @return [Node, nil] the last argument of the node, # or `nil` if there are no arguments def last_argument arguments[-1] end # Checks whether this node has any arguments. # # @return [Boolean] whether this node has any arguments def arguments? !arguments.empty? end # Checks whether any argument of the node is a splat # argument, i.e. `*splat`. # # @return [Boolean] whether the node is a splat argument def splat_argument? arguments? && (arguments.any?(&:splat_type?) || arguments.any?(&:restarg_type?)) end alias rest_argument? splat_argument? # Whether the last argument of the node is a block pass, # i.e. `&block`. # # @return [Boolean] whether the last argument of the node is a block pass def block_argument? arguments? && (last_argument.block_pass_type? || last_argument.blockarg_type?) end end end end rubocop-0.52.1/lib/rubocop/ast/node/mixin/predicate_operator_node.rb000066400000000000000000000016141322072016200255310ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Common functionality for nodes that are predicates: # `or`, `and` ... module PredicateOperatorNode LOGICAL_AND = '&&'.freeze SEMANTIC_AND = 'and'.freeze LOGICAL_OR = '||'.freeze SEMANTIC_OR = 'or'.freeze # Returns the operator as a string. # # @return [String] the operator def operator loc.operator.source end # Checks whether this is a logical operator. # # @return [Boolean] whether this is a logical operator def logical_operator? operator == LOGICAL_AND || operator == LOGICAL_OR end # Checks whether this is a semantic operator. # # @return [Boolean] whether this is a semantic operator def semantic_operator? operator == SEMANTIC_AND || operator == SEMANTIC_OR end end end end rubocop-0.52.1/lib/rubocop/ast/node/or_node.rb000066400000000000000000000022121322072016200211450ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `or` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `or` nodes within RuboCop. class OrNode < Node include BinaryOperatorNode include PredicateOperatorNode # Returns the alternate operator of the `or` as a string. # Returns `or` for `||` and vice versa. # # @return [String] the alternate of the `or` operator def alternate_operator logical_operator? ? SEMANTIC_OR : LOGICAL_OR end # Returns the inverse keyword of the `or` node as a string. # Returns `and` for `or` and `&&` for `||`. # # @return [String] the inverse of the `or` operator def inverse_operator logical_operator? ? LOGICAL_AND : SEMANTIC_AND end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `or` predicate def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/pair_node.rb000066400000000000000000000037761322072016200215000ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `pair` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `pair` nodes within RuboCop. class PairNode < Node include HashElementNode HASH_ROCKET = '=>'.freeze SPACED_HASH_ROCKET = ' => '.freeze COLON = ':'.freeze SPACED_COLON = ': '.freeze # Checks whether the `pair` uses a hash rocket delimiter. # # @return [Boolean] whether this `pair` uses a hash rocket delimiter def hash_rocket? loc.operator.is?(HASH_ROCKET) end # Checks whether the `pair` uses a colon delimiter. # # @return [Boolean] whether this `pair` uses a colon delimiter def colon? loc.operator.is?(COLON) end # Returns the delimiter of the `pair` as a string. Returns `=>` for a # colon delimited `pair`, and `:` for a hash rocket delimited `pair`. # # @param [Boolean] with_spacing whether to include spacing # @return [String] the delimiter of the `pair` def delimiter(with_spacing = false) if with_spacing hash_rocket? ? SPACED_HASH_ROCKET : SPACED_COLON else hash_rocket? ? HASH_ROCKET : COLON end end # Returns the inverse delimiter of the `pair` as a string. # # @param [Boolean] with_spacing whether to include spacing # @return [String] the inverse delimiter of the `pair` def inverse_delimiter(with_spacing = false) if with_spacing hash_rocket? ? SPACED_COLON : SPACED_HASH_ROCKET else hash_rocket? ? COLON : HASH_ROCKET end end # Custom destructuring method. This is used to normalize the branches # for `pair` and `kwsplat` nodes, to add duck typing to `hash` elements. # # @return [Array] the different parts of the `pair` def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/regexp_node.rb000066400000000000000000000016521322072016200220260ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `regexp` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `regexp` nodes within RuboCop. class RegexpNode < Node OPTIONS = { x: Regexp::EXTENDED, i: Regexp::IGNORECASE, m: Regexp::MULTILINE, n: Regexp::NOENCODING }.freeze # @return [Regexp] a regexp of this node def to_regexp option = regopt.children.map { |opt| OPTIONS[opt] }.inject(:|) Regexp.new(content, option) end # @return [RuboCop::AST::Node] a regopt node def regopt first, second = *self first.regopt_type? ? first : second end # @return [String] a string of regexp content def content str = children.first str.str_content || '' end end end end rubocop-0.52.1/lib/rubocop/ast/node/resbody_node.rb000066400000000000000000000013261322072016200222010ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `resbody` nodes. This will be used in place of a # plain node when the builder constructs the AST, making its methods # available to all `resbody` nodes within RuboCop. class ResbodyNode < Node # Returns the body of the `rescue` clause. # # @return [Node, nil] The body of the `resbody`. def body node_parts[2] end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `resbody` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/send_node.rb000066400000000000000000000025461322072016200214700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `send` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `send` nodes within RuboCop. class SendNode < Node include ParameterizedNode include MethodDispatchNode ARROW = '->'.freeze # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `send` node def node_parts to_a end # Checks whether this is a negation method, i.e. `!` or keyword `not`. # # @return [Boolean] whether this method is a negation method def negation_method? keyword_bang? || keyword_not? end # Checks whether this is a lambda. Some versions of parser parses # non-literal lambdas as a method send. # # @return [Boolean] whether this method is a lambda def lambda? parent && parent.block_type? && method?(:lambda) end # Checks whether this is a stabby lambda. e.g. `-> () {}` # # @return [Boolean] whether this method is a staby lambda def stabby_lambda? selector = loc.selector selector && selector.source == ARROW end end end end rubocop-0.52.1/lib/rubocop/ast/node/str_node.rb000066400000000000000000000006121322072016200213370ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `str`, `dstr` and `xstr` nodes. This will be used # in place of a plain node when the builder constructs the AST, making # its methods available to all `str` nodes within RuboCop. class StrNode < Node def heredoc? loc.is_a?(Parser::Source::Map::Heredoc) end end end end rubocop-0.52.1/lib/rubocop/ast/node/super_node.rb000066400000000000000000000012211322072016200216620ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `super`- and `zsuper` nodes. This will be used in # place of a plain node when the builder constructs the AST, making its # methods available to all `super`- and `zsuper` nodes within RuboCop. class SuperNode < Node include ParameterizedNode include MethodDispatchNode # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `super` node def node_parts [nil, :super, *to_a] end end end end rubocop-0.52.1/lib/rubocop/ast/node/symbol_node.rb000066400000000000000000000010771322072016200220420ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `sym` nodes. This will be used in place of a # plain node when the builder constructs the AST, making its methods # available to all `sym` nodes within RuboCop. class SymbolNode < Node include BasicLiteralNode # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `sym` node def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/until_node.rb000066400000000000000000000023531322072016200216660ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `until` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `until` nodes within RuboCop. class UntilNode < Node include ConditionalNode include ModifierNode # Returns the keyword of the `until` statement as a string. # # @return [String] the keyword of the `until` statement def keyword 'until' end # Returns the inverse keyword of the `until` node as a string. # Returns `while` for `until` nodes and vice versa. # # @return [String] the inverse keyword of the `until` statement def inverse_keyword 'while' end # Checks whether the `until` node has a `do` keyword. # # @return [Boolean] whether the `until` node has a `do` keyword def do? loc.begin && loc.begin.is?('do') end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `until` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/when_node.rb000066400000000000000000000033431322072016200214740ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `when` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `when` nodes within RuboCop. class WhenNode < Node # Returns an array of all the conditions in the `when` branch. # # @return [Array] an array of condition nodes def conditions node_parts[0...-1] end # Calls the given block for each condition node in the `when` branch. # If no block is given, an `Enumerator` is returned. # # @return [self] if a block is given # @return [Enumerator] if no block is given def each_condition return conditions.to_enum(__method__) unless block_given? conditions.each do |condition| yield condition end self end # Returns the index of the `when` branch within the `case` statement. # # @return [Integer] the index of the `when` branch def branch_index parent.when_branches.index(self) end # Checks whether the `when` node has a `then` keyword. # # @return [Boolean] whether the `when` node has a `then` keyword def then? loc.begin && loc.begin.is?('then') end # Returns the body of the `when` node. # # @return [Node, nil] the body of the `when` node def body node_parts[-1] end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `until` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/while_node.rb000066400000000000000000000023531322072016200216430ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `while` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `while` nodes within RuboCop. class WhileNode < Node include ConditionalNode include ModifierNode # Returns the keyword of the `while` statement as a string. # # @return [String] the keyword of the `while` statement def keyword 'while' end # Returns the inverse keyword of the `while` node as a string. # Returns `until` for `while` nodes and vice versa. # # @return [String] the inverse keyword of the `while` statement def inverse_keyword 'until' end # Checks whether the `until` node has a `do` keyword. # # @return [Boolean] whether the `until` node has a `do` keyword def do? loc.begin && loc.begin.is?('do') end # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `while` statement def node_parts to_a end end end end rubocop-0.52.1/lib/rubocop/ast/node/yield_node.rb000066400000000000000000000011641322072016200216400ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # A node extension for `yield` nodes. This will be used in place of a plain # node when the builder constructs the AST, making its methods available # to all `yield` nodes within RuboCop. class YieldNode < Node include ParameterizedNode include MethodDispatchNode # Custom destructuring method. This can be used to normalize # destructuring for different variations of the node. # # @return [Array] the different parts of the `send` node def node_parts [nil, :yield, *to_a] end end end end rubocop-0.52.1/lib/rubocop/ast/sexp.rb000066400000000000000000000006001322072016200175510ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # This module provides a shorthand method to create a {Node} like # `Parser::AST::Sexp`. # # @see http://rubydoc.info/gems/ast/AST/Sexp module Sexp # Creates a {Node} with type `type` and children `children`. def s(type, *children) Node.new(type, children) end end end end rubocop-0.52.1/lib/rubocop/ast/traversal.rb000066400000000000000000000120701322072016200206010ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module AST # Provides methods for traversing an AST. # Does not transform an AST; for that, use Parser::AST::Processor. # Override methods to perform custom processing. Remember to call `super` # if you want to recursively process descendant nodes. module Traversal def walk(node) return if node.nil? send(:"on_#{node.type}", node) nil end NO_CHILD_NODES = %i[true false nil int float complex rational str sym regopt self lvar ivar cvar gvar nth_ref back_ref cbase arg restarg blockarg shadowarg kwrestarg zsuper lambda redo retry].freeze ONE_CHILD_NODE = %i[splat kwsplat block_pass not break next preexe postexe match_current_line defined? arg_expr].freeze MANY_CHILD_NODES = %i[dstr dsym xstr regexp array hash pair irange erange mlhs masgn or_asgn and_asgn undef alias args super yield or and while_post until_post iflipflop eflipflop match_with_lvasgn begin kwbegin return].freeze SECOND_CHILD_ONLY = %i[lvasgn ivasgn cvasgn gvasgn optarg kwarg kwoptarg].freeze NO_CHILD_NODES.each do |type| module_eval("def on_#{type}(node); end", __FILE__, __LINE__) end ONE_CHILD_NODE.each do |type| module_eval(<<-RUBY, __FILE__, __LINE__ + 1) def on_#{type}(node) if (child = node.children[0]) send(:"on_\#{child.type}", child) end end RUBY end MANY_CHILD_NODES.each do |type| module_eval(<<-RUBY, __FILE__, __LINE__ + 1) def on_#{type}(node) node.children.each { |child| send(:"on_\#{child.type}", child) } nil end RUBY end SECOND_CHILD_ONLY.each do |type| # Guard clause is for nodes nested within mlhs module_eval(<<-RUBY, __FILE__, __LINE__ + 1) def on_#{type}(node) if (child = node.children[1]) send(:"on_\#{child.type}", child) end end RUBY end def on_const(node) return unless (child = node.children[0]) send(:"on_#{child.type}", child) end def on_casgn(node) children = node.children if (child = children[0]) # always const??? send(:"on_#{child.type}", child) end return unless (child = children[2]) send(:"on_#{child.type}", child) end def on_class(node) children = node.children child = children[0] # always const??? send(:"on_#{child.type}", child) if (child = children[1]) send(:"on_#{child.type}", child) end return unless (child = children[2]) send(:"on_#{child.type}", child) end def on_def(node) children = node.children on_args(children[1]) return unless (child = children[2]) send(:"on_#{child.type}", child) end def on_send(node) node.children.each_with_index do |child, i| next if i == 1 send(:"on_#{child.type}", child) if child end nil end alias on_csend on_send def on_op_asgn(node) children = node.children child = children[0] send(:"on_#{child.type}", child) child = children[2] send(:"on_#{child.type}", child) end def on_defs(node) children = node.children child = children[0] send(:"on_#{child.type}", child) on_args(children[2]) return unless (child = children[3]) send(:"on_#{child.type}", child) end def on_if(node) children = node.children child = children[0] send(:"on_#{child.type}", child) if (child = children[1]) send(:"on_#{child.type}", child) end return unless (child = children[2]) send(:"on_#{child.type}", child) end def on_while(node) children = node.children child = children[0] send(:"on_#{child.type}", child) return unless (child = children[1]) send(:"on_#{child.type}", child) end alias on_until on_while alias on_module on_while alias on_sclass on_while def on_block(node) children = node.children child = children[0] send(:"on_#{child.type}", child) # can be send, zsuper... on_args(children[1]) return unless (child = children[2]) send(:"on_#{child.type}", child) end def on_case(node) node.children.each do |child| send(:"on_#{child.type}", child) if child end nil end alias on_rescue on_case alias on_resbody on_case alias on_ensure on_case alias on_for on_case alias on_when on_case end end end rubocop-0.52.1/lib/rubocop/cached_data.rb000066400000000000000000000032631322072016200202130ustar00rootroot00000000000000# frozen_string_literal: true require 'json' module RuboCop # Converts RuboCop objects to and from the serialization format JSON. class CachedData def initialize(filename) @filename = filename end def from_json(text) deserialize_offenses(JSON.parse(text)) end def to_json(offenses) JSON.dump(offenses.map { |o| serialize_offense(o) }) end private def serialize_offense(offense) { # Calling #to_s here ensures that the serialization works when using # other json serializers such as Oj. Some of these gems do not call # #to_s implicitly. severity: offense.severity.to_s, location: { begin_pos: offense.location.begin_pos, end_pos: offense.location.end_pos }, message: message(offense), cop_name: offense.cop_name, status: offense.status } end def message(offense) # JSON.dump will fail if the offense message contains text which is not # valid UTF-8 offense.message.scrub end # Restore an offense object loaded from a JSON file. def deserialize_offenses(offenses) source_buffer = Parser::Source::Buffer.new(@filename) source_buffer.source = File.read(@filename, encoding: Encoding::UTF_8) offenses.map! do |o| location = Parser::Source::Range.new(source_buffer, o['location']['begin_pos'], o['location']['end_pos']) Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'], o['status'].to_sym) end end end end rubocop-0.52.1/lib/rubocop/cli.rb000066400000000000000000000204121322072016200165550ustar00rootroot00000000000000# frozen_string_literal: true # rubocop:disable Metrics/ClassLength module RuboCop # The CLI is a class responsible of handling all the command line interface # logic. class CLI include Formatter::TextUtil SKIPPED_PHASE_1 = 'Phase 1 of 2: run Metrics/LineLength cop (skipped ' \ 'because the default Metrics/LineLength:Max is ' \ 'overridden)'.freeze class Finished < RuntimeError; end attr_reader :options, :config_store def initialize @options = {} @config_store = ConfigStore.new end # @api public # # Entry point for the application logic. Here we # do the command line arguments processing and inspect # the target files. # # @param args [Array] command line arguments # @return [Integer] UNIX exit code # # rubocop:disable Metrics/MethodLength def run(args = ARGV) @options, paths = Options.new.parse(args) validate_options_vs_config act_on_options apply_default_formatter execute_runners(paths) rescue RuboCop::Error => e warn Rainbow("Error: #{e.message}").red return 2 rescue Finished return 0 rescue IncorrectCopNameError => e warn e.message return 2 rescue StandardError, SyntaxError, LoadError => e warn e.message warn e.backtrace return 2 end # rubocop:enable Metrics/MethodLength def trap_interrupt(runner) Signal.trap('INT') do exit!(1) if runner.aborting? runner.abort warn warn 'Exiting... Interrupt again to exit immediately.' end end private def execute_runners(paths) if @options[:auto_gen_config] reset_config_and_auto_gen_file line_length_contents = if max_line_length(@config_store.for(Dir.pwd)) == max_line_length(ConfigLoader.default_configuration) run_line_length_cop_auto_gen_config(paths) else puts Rainbow(SKIPPED_PHASE_1).yellow '' end run_all_cops_auto_gen_config(line_length_contents, paths) else execute_runner(paths) end end def max_line_length(config) config.for_cop('Metrics/LineLength')['Max'] end # Do an initial run with only Metrics/LineLength so that cops that depend # on Metrics/LineLength:Max get the correct value for that parameter. def run_line_length_cop_auto_gen_config(paths) puts Rainbow('Phase 1 of 2: run Metrics/LineLength cop').yellow @options[:only] = ['Metrics/LineLength'] execute_runner(paths) @options.delete(:only) @config_store = ConfigStore.new # Save the todo configuration of the LineLength cop. IO.read(ConfigLoader::AUTO_GENERATED_FILE) .lines .drop_while { |line| line.start_with?('#') } .join end def run_all_cops_auto_gen_config(line_length_contents, paths) puts Rainbow('Phase 2 of 2: run all cops').yellow result = execute_runner(paths) # This run was made with the current maximum length allowed, so append # the saved setting for LineLength. File.open(ConfigLoader::AUTO_GENERATED_FILE, 'a') do |f| f.write(line_length_contents) end result end def reset_config_and_auto_gen_file @config_store = ConfigStore.new File.open(ConfigLoader::AUTO_GENERATED_FILE, 'w') {} ConfigLoader.add_inheritance_from_auto_generated_file end def validate_options_vs_config if @options[:parallel] && !@config_store.for(Dir.pwd).for_all_cops['UseCache'] raise ArgumentError, '-P/--parallel uses caching to speed up ' \ 'execution, so combining with AllCops: ' \ 'UseCache: false is not allowed.' end end def act_on_options ConfigLoader.debug = @options[:debug] ConfigLoader.auto_gen_config = @options[:auto_gen_config] ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion] @config_store.options_config = @options[:config] if @options[:config] @config_store.force_default_config! if @options[:force_default_config] handle_exiting_options if @options[:color] # color output explicitly forced on Rainbow.enabled = true elsif @options[:color] == false # color output explicitly forced off Rainbow.enabled = false end end def execute_runner(paths) runner = Runner.new(@options, @config_store) trap_interrupt(runner) all_passed = runner.run(paths) display_warning_summary(runner.warnings) display_error_summary(runner.errors) maybe_print_corrected_source all_passed && !runner.aborting? && runner.errors.empty? ? 0 : 1 end def handle_exiting_options return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o } puts RuboCop::Version.version(false) if @options[:version] puts RuboCop::Version.version(true) if @options[:verbose_version] print_available_cops if @options[:show_cops] raise Finished end def apply_default_formatter # This must be done after the options have already been processed, # because they can affect how ConfigStore behaves @options[:formatters] ||= begin cfg = @config_store.for(Dir.pwd).for_all_cops formatter = cfg['DefaultFormatter'] || 'progress' [[formatter, @options[:output_path]]] end return unless @options[:auto_gen_config] @options[:formatters] << [Formatter::DisabledConfigFormatter, ConfigLoader::AUTO_GENERATED_FILE] end def print_available_cops # Load the configs so the require()s are done for custom cops @config_store.for(Dir.pwd) registry = Cop::Cop.registry show_all = @options[:show_cops].empty? if show_all puts "# Available cops (#{registry.length}) + config for #{Dir.pwd}: " end registry.departments.sort!.each do |department| print_cops_of_department(registry, department, show_all) end end def print_cops_of_department(registry, department, show_all) selected_cops = if show_all cops_of_department(registry, department) else selected_cops_of_department(registry, department) end puts "# Department '#{department}' (#{selected_cops.length}):" if show_all print_cop_details(selected_cops) end def print_cop_details(cops) cops.each do |cop| puts '# Supports --auto-correct' if cop.new.support_autocorrect? puts "#{cop.cop_name}:" puts config_lines(cop) puts end end def selected_cops_of_department(cops, department) cops_of_department(cops, department).select do |cop| @options[:show_cops].include?(cop.cop_name) end end def cops_of_department(cops, department) cops.with_department(department).sort! end def config_lines(cop) cnf = @config_store.for(Dir.pwd).for_cop(cop) cnf.to_yaml.lines.to_a.butfirst.map { |line| ' ' + line } end def display_warning_summary(warnings) return if warnings.empty? warn Rainbow("\n#{pluralize(warnings.size, 'warning')}:").yellow warnings.each { |warning| warn warning } end def display_error_summary(errors) return if errors.empty? warn Rainbow("\n#{pluralize(errors.size, 'error')} occurred:").red errors.each { |error| warn error } warn <<-WARNING.strip_indent Errors are usually caused by RuboCop bugs. Please, report your problems to RuboCop's issue tracker. Mention the following information in the issue report: #{RuboCop::Version.version(true)} WARNING end def maybe_print_corrected_source # If we are asked to autocorrect source code read from stdin, the only # reasonable place to write it is to stdout # Unfortunately, we also write other information to stdout # So a delimiter is needed for tools to easily identify where the # autocorrected source begins return unless @options[:stdin] && @options[:auto_correct] puts '=' * 20 print @options[:stdin] end end end # rubocop:enable Metrics/ClassLength rubocop-0.52.1/lib/rubocop/comment_config.rb000066400000000000000000000105541322072016200210030ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop # This class parses the special `rubocop:disable` comments in a source # and provides a way to check if each cop is enabled at arbitrary line. class CommentConfig UNNEEDED_DISABLE = 'Lint/UnneededDisable'.freeze COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'.freeze COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}".freeze COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})".freeze COMMENT_DIRECTIVE_REGEXP = Regexp.new( ('# rubocop : ((?:dis|en)able)\b ' + COPS_PATTERN).gsub(' ', '\s*') ) CopAnalysis = Struct.new(:line_ranges, :start_line_number) attr_reader :processed_source def initialize(processed_source) @processed_source = processed_source end def cop_enabled_at_line?(cop, line_number) cop = cop.cop_name if cop.respond_to?(:cop_name) disabled_line_ranges = cop_disabled_line_ranges[cop] return true unless disabled_line_ranges disabled_line_ranges.none? { |range| range.include?(line_number) } end def cop_disabled_line_ranges @cop_disabled_line_ranges ||= analyze end private def analyze analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) } each_mentioned_cop do |cop_name, disabled, line, single_line| analyses[cop_name] = analyze_cop(analyses[cop_name], disabled, line, single_line) end analyses.each_with_object({}) do |element, hash| cop_name, analysis = *element hash[cop_name] = cop_line_ranges(analysis) end end def analyze_cop(analysis, disabled, line, single_line) if single_line analyze_single_line(analysis, line, disabled) elsif disabled analyze_disabled(analysis, line) else analyze_rest(analysis, line) end end def analyze_single_line(analysis, line, disabled) return analysis unless disabled CopAnalysis.new(analysis.line_ranges + [(line..line)], analysis.start_line_number) end def analyze_disabled(analysis, line) if (start_line = analysis.start_line_number) # Cop already disabled on this line, so we end the current disabled # range before we start a new range. return CopAnalysis.new(analysis.line_ranges + [start_line..line], line) end CopAnalysis.new(analysis.line_ranges, line) end def analyze_rest(analysis, line) if (start_line = analysis.start_line_number) return CopAnalysis.new(analysis.line_ranges + [start_line..line], nil) end CopAnalysis.new(analysis.line_ranges, nil) end def cop_line_ranges(analysis) return analysis.line_ranges unless analysis.start_line_number analysis.line_ranges + [(analysis.start_line_number..Float::INFINITY)] end def each_mentioned_cop each_directive do |comment, cop_names, disabled| comment_line_number = comment.loc.expression.line single_line = !comment_only_line?(comment_line_number) cop_names.each do |cop_name| yield qualified_cop_name(cop_name), disabled, comment_line_number, single_line end end end def each_directive return if processed_source.comments.nil? processed_source.comments.each do |comment| directive = directive_parts(comment) next unless directive yield comment, *directive end end def directive_parts(comment) match = comment.text.match(COMMENT_DIRECTIVE_REGEXP) return unless match switch, cops_string = match.captures cop_names = cops_string == 'all' ? all_cop_names : cops_string.split(/,\s*/) disabled = (switch == 'disable') [cop_names, disabled] end def qualified_cop_name(cop_name) Cop::Cop.qualified_cop_name(cop_name.strip, processed_source.buffer.name) end def all_cop_names @all_cop_names ||= Cop::Cop.registry.names - [UNNEEDED_DISABLE] end def comment_only_line?(line_number) non_comment_token_line_numbers.none? do |non_comment_line_number| non_comment_line_number == line_number end end def non_comment_token_line_numbers @non_comment_token_line_numbers ||= begin non_comment_tokens = processed_source.tokens.reject(&:comment?) non_comment_tokens.map(&:line).uniq end end end end rubocop-0.52.1/lib/rubocop/config.rb000066400000000000000000000443561322072016200172700ustar00rootroot00000000000000# frozen_string_literal: true require 'pathname' module RuboCop # This class represents the configuration of the RuboCop application # and all its cops. A Config is associated with a YAML configuration # file from which it was read. Several different Configs can be used # during a run of the rubocop program, if files in several # directories are inspected. # rubocop:disable Metrics/ClassLength class Config include PathUtil COMMON_PARAMS = %w[Exclude Include Severity AutoCorrect StyleGuide Details].freeze # 2.1 is the oldest officially supported Ruby version. DEFAULT_RUBY_VERSION = 2.1 KNOWN_RUBIES = [2.1, 2.2, 2.3, 2.4, 2.5].freeze OBSOLETE_RUBIES = { 1.9 => '0.50', 2.0 => '0.50' }.freeze RUBY_VERSION_FILENAME = '.ruby-version'.freeze DEFAULT_RAILS_VERSION = 5.0 OBSOLETE_COPS = { 'Style/TrailingComma' => 'The `Style/TrailingComma` cop no longer exists. Please use ' \ '`Style/TrailingCommaInLiteral` and/or ' \ '`Style/TrailingCommaInArguments` instead.', 'Rails/DefaultScope' => 'The `Rails/DefaultScope` cop no longer exists.', 'Lint/InvalidCharacterLiteral' => 'The `Lint/InvalidCharacterLiteral` cop has been removed since it ' \ 'was never being actually triggered.', 'Style/SingleSpaceBeforeFirstArg' => 'The `Style/SingleSpaceBeforeFirstArg` cop has been renamed to ' \ '`Layout/SpaceBeforeFirstArg`.', 'Lint/RescueWithoutErrorClass' => 'The `Lint/RescueWithoutErrorClass` cop has been replaced by ' \ '`Style/RescueStandardError`.', 'Lint/SpaceBeforeFirstArg' => 'The `Lint/SpaceBeforeFirstArg` cop has been removed, since it was a ' \ 'duplicate of `Layout/SpaceBeforeFirstArg`. Please use ' \ '`Layout/SpaceBeforeFirstArg` instead.', 'Layout/SpaceAfterControlKeyword' => 'The `Layout/SpaceAfterControlKeyword` cop has been removed. Please ' \ 'use `Layout/SpaceAroundKeyword` instead.', 'Layout/SpaceBeforeModifierKeyword' => 'The `Layout/SpaceBeforeModifierKeyword` cop has been removed. ' \ 'Please use `Layout/SpaceAroundKeyword` instead.', 'Style/SpaceAfterControlKeyword' => 'The `Style/SpaceAfterControlKeyword` cop has been removed. Please ' \ 'use `Layout/SpaceAroundKeyword` instead.', 'Style/SpaceBeforeModifierKeyword' => 'The `Style/SpaceBeforeModifierKeyword` cop has been removed. Please ' \ 'use `Layout/SpaceAroundKeyword` instead.', 'Style/MethodCallParentheses' => 'The `Style/MethodCallParentheses` cop has been renamed to ' \ '`Style/MethodCallWithoutArgsParentheses`.', 'Lint/Eval' => 'The `Lint/Eval` cop has been renamed to `Security/Eval`.', 'Style/DeprecatedHashMethods' => 'The `Style/DeprecatedHashMethods` cop has been renamed to ' \ '`Style/PreferredHashMethods`.', 'Style/AccessorMethodName' => 'The `Style/AccessorMethodName` cop has been moved to ' \ '`Naming/AccessorMethodName`.', 'Style/AsciiIdentifiers' => 'The `Style/AsciiIdentifiers` cop has been moved to ' \ '`Naming/AccessorMethodName`.', 'Style/OpMethod' => 'The `Style/OpMethod` cop has been renamed and moved to ' \ '`Naming/BinaryOperatorParameterName`.', 'Style/ClassAndModuleCamelCase' => 'The `Style/ClassAndModuleCamelCase` cop has been renamed to ' \ '`Naming/ClassAndModuleCamelCase`.', 'Style/ConstantName' => 'The `Style/ConstantName` cop has been renamed to ' \ '`Naming/ConstantName`.', 'Style/FileName' => 'The `Style/FileName` cop has been renamed to `Naming/FileName`.', 'Style/MethodName' => 'The `Style/MethodName` cop has been renamed to ' \ '`Naming/MethodName`.', 'Style/PredicateName' => 'The `Style/PredicateName` cop has been renamed to ' \ '`Naming/PredicateName`.', 'Style/VariableName' => 'The `Style/VariableName` cop has been renamed to ' \ '`Naming/VariableName`.', 'Style/VariableNumber' => 'The `Style/VariableNumber` cop has been renamed to ' \ '`Naming/VariableNumber`.' }.freeze OBSOLETE_PARAMETERS = [ { cop: 'Layout/SpaceAroundOperators', parameter: 'MultiSpaceAllowedForOperators', alternative: 'If your intention was to allow extra spaces ' \ 'for alignment, please use AllowForAlignment: ' \ 'true instead.' }, { cop: 'Style/Encoding', parameter: 'EnforcedStyle', alternative: 'Style/Encoding no longer supports styles. ' \ 'The "never" behavior is always assumed.' }, { cop: 'Style/Encoding', parameter: 'SupportedStyles', alternative: 'Style/Encoding no longer supports styles. ' \ 'The "never" behavior is always assumed.' }, { cop: 'Style/Encoding', parameter: 'AutoCorrectEncodingComment', alternative: 'Style/Encoding no longer supports styles. ' \ 'The "never" behavior is always assumed.' }, { cop: 'Style/IfUnlessModifier', parameter: 'MaxLineLength', alternative: '`Style/IfUnlessModifier: MaxLineLength` has been removed. Use ' \ '`Metrics/LineLength: Max` instead' }, { cop: 'Style/SpaceAroundOperators', parameter: 'MultiSpaceAllowedForOperators', alternative: 'If your intention was to allow extra spaces ' \ 'for alignment, please use AllowForAlignment: ' \ 'true instead.' }, { cop: 'Style/WhileUntilModifier', parameter: 'MaxLineLength', alternative: '`Style/WhileUntilModifier: MaxLineLength` has been removed. Use ' \ '`Metrics/LineLength: Max` instead' }, { cop: 'AllCops', parameter: 'RunRailsCops', alternative: "Use the following configuration instead:\n" \ "Rails:\n Enabled: true" }, { cop: 'Layout/CaseIndentation', parameter: 'IndentWhenRelativeTo', alternative: '`IndentWhenRelativeTo` has been renamed to ' \ '`EnforcedStyle`' }, { cop: 'Lint/BlockAlignment', parameter: 'AlignWith', alternative: '`AlignWith` has been renamed to ' \ '`EnforcedStyleAlignWith`' }, { cop: 'Lint/EndAlignment', parameter: 'AlignWith', alternative: '`AlignWith` has been renamed to ' \ '`EnforcedStyleAlignWith`' }, { cop: 'Lint/DefEndAlignment', parameter: 'AlignWith', alternative: '`AlignWith` has been renamed to ' \ '`EnforcedStyleAlignWith`' }, { cop: 'Rails/UniqBeforePluck', parameter: 'EnforcedMode', alternative: '`EnforcedMode` has been renamed to ' \ '`EnforcedStyle`' } ].freeze attr_reader :loaded_path def initialize(hash = {}, loaded_path = nil) @loaded_path = loaded_path @for_cop = Hash.new do |h, cop| qualified_cop_name = Cop::Cop.qualified_cop_name(cop, loaded_path) cop_options = self[qualified_cop_name] || {} cop_options['Enabled'] = enable_cop?(qualified_cop_name, cop_options) h[cop] = cop_options end @hash = hash end def self.create(hash, path) new(hash, path).check end def check deprecation_check do |deprecation_message| warn("#{loaded_path} - #{deprecation_message}") end validate make_excludes_absolute self end def [](key) @hash[key] end def []=(key, value) @hash[key] = value end def delete(key) @hash.delete(key) end def each(&block) @hash.each(&block) end def key?(key) @hash.key?(key) end def keys @hash.keys end def each_key(&block) @hash.each_key(&block) end def map(&block) @hash.map(&block) end def merge(other_hash) @hash.merge(other_hash) end def to_h @hash end def to_hash @hash end def to_s @to_s ||= @hash.to_s end def make_excludes_absolute each_key do |key| validate_section_presence(key) next unless self[key]['Exclude'] self[key]['Exclude'].map! do |exclude_elem| if exclude_elem.is_a?(String) && !absolute?(exclude_elem) File.expand_path(File.join(base_dir_for_path_parameters, exclude_elem)) else exclude_elem end end end end def add_excludes_from_higher_level(highest_config) return unless highest_config.for_all_cops['Exclude'] excludes = for_all_cops['Exclude'] ||= [] highest_config.for_all_cops['Exclude'].each do |path| unless path.is_a?(Regexp) || absolute?(path) path = File.join(File.dirname(highest_config.loaded_path), path) end excludes << path unless excludes.include?(path) end end def deprecation_check %w[Exclude Include].each do |key| plural = "#{key}s" next unless for_all_cops[plural] for_all_cops[key] = for_all_cops[plural] # Stay backwards compatible. for_all_cops.delete(plural) yield "AllCops/#{plural} was renamed to AllCops/#{key}" end end def for_cop(cop) @for_cop[cop.respond_to?(:cop_name) ? cop.cop_name : cop] end def for_all_cops @for_all_cops ||= self['AllCops'] || {} end def validate # Don't validate RuboCop's own files. Avoids infinite recursion. base_config_path = File.expand_path(File.join(ConfigLoader::RUBOCOP_HOME, 'config')) return if File.expand_path(loaded_path).start_with?(base_config_path) valid_cop_names, invalid_cop_names = keys.partition do |key| ConfigLoader.default_configuration.key?(key) end reject_obsolete_cops_and_parameters warn_about_unrecognized_cops(invalid_cop_names) check_target_ruby validate_parameter_names(valid_cop_names) validate_enforced_styles(valid_cop_names) validate_syntax_cop reject_mutually_exclusive_defaults end def file_to_include?(file) relative_file_path = path_relative_to_config(file) # Optimization to quickly decide if the given file is hidden (on the top # level) and can not be matched by any pattern. is_hidden = relative_file_path.start_with?('.') && !relative_file_path.start_with?('..') return false if is_hidden && !possibly_include_hidden? absolute_file_path = File.expand_path(file) patterns_to_include.any? do |pattern| match_path?(pattern, relative_file_path) || match_path?(pattern, absolute_file_path) end end # Returns true if there's a chance that an Include pattern matches hidden # files, false if that's definitely not possible. def possibly_include_hidden? return @possibly_include_hidden if defined?(@possibly_include_hidden) @possibly_include_hidden = patterns_to_include.any? do |s| s.is_a?(Regexp) || s.start_with?('.') || s.include?('/.') end end def file_to_exclude?(file) file = File.expand_path(file) patterns_to_exclude.any? do |pattern| match_path?(pattern, file) end end def patterns_to_include for_all_cops['Include'] end def patterns_to_exclude for_all_cops['Exclude'] end def path_relative_to_config(path) relative_path(path, base_dir_for_path_parameters) end # Paths specified in configuration files starting with .rubocop are # relative to the directory where that file is. Paths in other config files # are relative to the current directory. This is so that paths in # config/default.yml, for example, are not relative to RuboCop's config # directory since that wouldn't work. def base_dir_for_path_parameters @base_dir_for_path_parameters ||= if File.basename(loaded_path).start_with?('.rubocop') && loaded_path != File.join(Dir.home, ConfigLoader::DOTFILE) File.expand_path(File.dirname(loaded_path)) else Dir.pwd end end def target_ruby_version @target_ruby_version ||= if for_all_cops['TargetRubyVersion'] @target_ruby_version_source = :rubocop_yml for_all_cops['TargetRubyVersion'] elsif target_ruby_version_from_version_file @target_ruby_version_source = :ruby_version_file target_ruby_version_from_version_file else DEFAULT_RUBY_VERSION end end def target_rails_version @target_rails_version ||= for_all_cops.fetch('TargetRailsVersion', DEFAULT_RAILS_VERSION) end private def warn_about_unrecognized_cops(invalid_cop_names) invalid_cop_names.each do |name| # There could be a custom cop with this name. If so, don't warn next if Cop::Cop.registry.contains_cop_matching?([name]) warn Rainbow("Warning: unrecognized cop #{name} found in " \ "#{smart_loaded_path}").yellow end end def validate_syntax_cop syntax_config = self['Lint/Syntax'] default_config = ConfigLoader.default_configuration['Lint/Syntax'] return unless syntax_config && default_config.merge(syntax_config) != default_config raise ValidationError, "configuration for Syntax cop found in #{smart_loaded_path}\n" \ 'It\'s not possible to disable this cop.' end def validate_section_presence(name) return unless key?(name) && self[name].nil? raise ValidationError, "empty section #{name} found in #{smart_loaded_path}" end def validate_parameter_names(valid_cop_names) valid_cop_names.each do |name| validate_section_presence(name) self[name].each_key do |param| next if COMMON_PARAMS.include?(param) || ConfigLoader.default_configuration[name].key?(param) warn Rainbow("Warning: unrecognized parameter #{name}:#{param} " \ "found in #{smart_loaded_path}").yellow end end end def validate_enforced_styles(valid_cop_names) valid_cop_names.each do |name| styles = self[name].select { |key, _| key.start_with?('Enforced') } styles.each do |style_name, style| supported_key = RuboCop::Cop::Util.to_supported_styles(style_name) valid = ConfigLoader.default_configuration[name][supported_key] next unless valid next if valid.include?(style) msg = "invalid #{style_name} '#{style}' for #{name} found in " \ "#{smart_loaded_path}\n" \ "Valid choices are: #{valid.join(', ')}" raise ValidationError, msg end end end def reject_obsolete_cops_and_parameters messages = [ obsolete_cops, obsolete_parameters ].flatten.compact return if messages.empty? raise ValidationError, messages.join("\n") end def obsolete_parameters OBSOLETE_PARAMETERS.map do |params| obsolete_parameter_message(params[:cop], params[:parameter], params[:alternative]) end end def obsolete_parameter_message(cop, parameter, alternative) return unless self[cop] && self[cop].key?(parameter) "obsolete parameter #{parameter} (for #{cop}) " \ "found in #{smart_loaded_path}" \ "\n#{alternative}" end def obsolete_cops OBSOLETE_COPS.map do |cop_name, message| next unless key?(cop_name) || key?(Cop::Badge.parse(cop_name).cop_name) message + "\n(obsolete configuration found in #{smart_loaded_path}," \ ' please update it)' end end def check_target_ruby return if KNOWN_RUBIES.include?(target_ruby_version) msg = if OBSOLETE_RUBIES.include?(target_ruby_version) "Unsupported Ruby version #{target_ruby_version} found in " \ "#{target_ruby_source}. #{target_ruby_version}-compatible " \ 'analysis was dropped after version ' \ "#{OBSOLETE_RUBIES[target_ruby_version]}." else "Unknown Ruby version #{target_ruby_version.inspect} found in " \ "#{target_ruby_source}." end msg += "\nSupported versions: #{KNOWN_RUBIES.join(', ')}" raise ValidationError, msg end def target_ruby_source case @target_ruby_version_source when :ruby_version_file "`#{RUBY_VERSION_FILENAME}`" when :rubocop_yml "`TargetRubyVersion` parameter (in #{smart_loaded_path})" end end def ruby_version_file @ruby_version_file ||= PathUtil.find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters) end def target_ruby_version_from_version_file file = ruby_version_file return unless file && File.file?(file) @target_ruby_version_from_version_file ||= File.read(file).match(/\A(ruby-)?(?\d+\.\d+)/) do |md| md[:version].to_f end end def reject_mutually_exclusive_defaults disabled_by_default = for_all_cops['DisabledByDefault'] enabled_by_default = for_all_cops['EnabledByDefault'] return unless disabled_by_default && enabled_by_default msg = 'Cops cannot be both enabled by default and disabled by default' raise ValidationError, msg end def enable_cop?(qualified_cop_name, cop_options) cop_department, cop_name = qualified_cop_name.split('/') department = cop_name.nil? unless department department_options = self[cop_department] if department_options && department_options['Enabled'] == false return false end end cop_options.fetch('Enabled', true) end def smart_loaded_path PathUtil.smart_path(@loaded_path) end end # rubocop:enable Metrics/ClassLength end rubocop-0.52.1/lib/rubocop/config_loader.rb000066400000000000000000000164001322072016200206030ustar00rootroot00000000000000# frozen_string_literal: true require 'yaml' require 'pathname' module RuboCop # This class represents the configuration of the RuboCop application # and all its cops. A Config is associated with a YAML configuration # file from which it was read. Several different Configs can be used # during a run of the rubocop program, if files in several # directories are inspected. class ConfigLoader DOTFILE = '.rubocop.yml'.freeze RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..')) DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml') AUTO_GENERATED_FILE = '.rubocop_todo.yml'.freeze class << self attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion attr_writer :root_level # The upwards search is stopped at this level. attr_writer :default_configuration alias debug? debug alias auto_gen_config? auto_gen_config alias ignore_parent_exclusion? ignore_parent_exclusion def clear_options @debug = @auto_gen_config = @root_level = nil end def load_file(file) return if file.nil? path = File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file) hash = load_yaml_configuration(path) # Resolve requires first in case they define additional cops resolver.resolve_requires(path, hash) add_missing_namespaces(path, hash) target_ruby_version_to_f!(hash) resolver.resolve_inheritance_from_gems(hash, hash.delete('inherit_gem')) resolver.resolve_inheritance(path, hash, file) hash.delete('inherit_from') Config.create(hash, path) end # rubocop:disable Performance/HashEachMethods def add_missing_namespaces(path, hash) hash.keys.each do |key| q = Cop::Cop.qualified_cop_name(key, path) next if q == key hash[q] = hash.delete(key) end end # rubocop:enable Performance/HashEachMethods # Return a recursive merge of two hashes. That is, a normal hash merge, # with the addition that any value that is a hash, and occurs in both # arguments, will also be merged. And so on. def merge(base_hash, derived_hash) resolver.merge(base_hash, derived_hash) end # Returns the path of .rubocop.yml searching upwards in the # directory structure starting at the given directory where the # inspected file is. If no .rubocop.yml is found there, the # user's home directory is checked. If there's no .rubocop.yml # there either, the path to the default file is returned. def configuration_file_for(target_dir) config_files_in_path(target_dir).first || DEFAULT_FILE end def configuration_from_file(config_file) config = load_file(config_file) return config if config_file == DEFAULT_FILE if ignore_parent_exclusion? print 'Ignoring AllCops/Exclude from parent folders' if debug? else add_excludes_from_files(config, config_file) end merge_with_default(config, config_file) end def add_excludes_from_files(config, config_file) found_files = config_files_in_path(config_file) return unless found_files.any? && found_files.last != config_file print 'AllCops/Exclude ' if debug? config.add_excludes_from_higher_level(load_file(found_files.last)) end def default_configuration @default_configuration ||= begin print 'Default ' if debug? load_file(DEFAULT_FILE) end end # Merges the given configuration with the default one. If # AllCops:DisabledByDefault is true, it changes the Enabled params so # that only cops from user configuration are enabled. # If AllCops::EnabledByDefault is true, it changes the Enabled params # so that only cops explicitly disabled in user configuration are # disabled. def merge_with_default(config, config_file) resolver.merge_with_default(config, config_file) end def target_ruby_version_to_f!(hash) version = 'TargetRubyVersion' return unless hash['AllCops'] && hash['AllCops'][version] hash['AllCops'][version] = hash['AllCops'][version].to_f end def add_inheritance_from_auto_generated_file file_string = " #{AUTO_GENERATED_FILE}" if File.exist?(DOTFILE) files = Array(load_yaml_configuration(DOTFILE)['inherit_from']) return if files.include?(AUTO_GENERATED_FILE) files.unshift(AUTO_GENERATED_FILE) file_string = "\n - " + files.join("\n - ") if files.size > 1 rubocop_yml_contents = IO.read(DOTFILE, encoding: Encoding::UTF_8) .sub(/^inherit_from: *[.\w]+/, '') .sub(/^inherit_from: *(\n *- *[.\w]+)+/, '') end write_dotfile(file_string, rubocop_yml_contents) puts "Added inheritance from `#{AUTO_GENERATED_FILE}` in `#{DOTFILE}`." end private def write_dotfile(file_string, rubocop_yml_contents) File.open(DOTFILE, 'w') do |f| f.write "inherit_from:#{file_string}\n\n" f.write rubocop_yml_contents if rubocop_yml_contents end end def resolver @resolver ||= ConfigLoaderResolver.new end def load_yaml_configuration(absolute_path) yaml_code = read_file(absolute_path) hash = yaml_safe_load(yaml_code, absolute_path) || {} puts "configuration from #{absolute_path}" if debug? unless hash.is_a?(Hash) raise(TypeError, "Malformed configuration in #{absolute_path}") end hash end # Read the specified file, or exit with a friendly, concise message on # stderr. Care is taken to use the standard OS exit code for a "file not # found" error. def read_file(absolute_path) IO.read(absolute_path, encoding: Encoding::UTF_8) rescue Errno::ENOENT warn(format('Configuration file not found: %s', absolute_path)) exit(Errno::ENOENT::Errno) end def yaml_safe_load(yaml_code, filename) if YAML.respond_to?(:safe_load) # Ruby 2.1+ if defined?(SafeYAML) && SafeYAML.respond_to?(:load) SafeYAML.load(yaml_code, filename, whitelisted_tags: %w[!ruby/regexp]) else YAML.safe_load(yaml_code, [Regexp, Symbol], [], false, filename) end else YAML.load(yaml_code, filename) # rubocop:disable Security/YAMLLoad end end def config_files_in_path(target) possible_config_files = dirs_to_search(target).map do |dir| File.join(dir, DOTFILE) end possible_config_files.select { |config_file| File.exist?(config_file) } end def dirs_to_search(target_dir) dirs_to_search = [] Pathname.new(File.expand_path(target_dir)).ascend do |dir_pathname| break if dir_pathname.to_s == @root_level dirs_to_search << dir_pathname.to_s end dirs_to_search << Dir.home if ENV.key? 'HOME' dirs_to_search end end # Initializing class ivars clear_options end end rubocop-0.52.1/lib/rubocop/config_loader_resolver.rb000066400000000000000000000116111322072016200225230ustar00rootroot00000000000000# frozen_string_literal: true require 'yaml' require 'pathname' module RuboCop # A help class for ConfigLoader that handles configuration resolution. class ConfigLoaderResolver def resolve_requires(path, hash) config_dir = File.dirname(path) Array(hash.delete('require')).each do |r| if r.start_with?('.') require(File.join(config_dir, r)) else require(r) end end end def resolve_inheritance(path, hash, file) base_configs(path, hash['inherit_from'], file) .reverse_each do |base_config| base_config.each do |k, v| hash[k] = hash.key?(k) ? merge(v, hash[k]) : v if v.is_a?(Hash) end end end def resolve_inheritance_from_gems(hash, gems) (gems || {}).each_pair do |gem_name, config_path| if gem_name == 'rubocop' raise ArgumentError, "can't inherit configuration from the rubocop gem" end hash['inherit_from'] = Array(hash['inherit_from']) Array(config_path).reverse.each do |path| # Put gem configuration first so local configuration overrides it. hash['inherit_from'].unshift gem_config_path(gem_name, path) end end end # Merges the given configuration with the default one. If # AllCops:DisabledByDefault is true, it changes the Enabled params so that # only cops from user configuration are enabled. If # AllCops::EnabledByDefault is true, it changes the Enabled params so that # only cops explicitly disabled in user configuration are disabled. def merge_with_default(config, config_file) default_configuration = ConfigLoader.default_configuration disabled_by_default = config.for_all_cops['DisabledByDefault'] enabled_by_default = config.for_all_cops['EnabledByDefault'] if disabled_by_default || enabled_by_default default_configuration = transform(default_configuration) do |params| params.merge('Enabled' => !disabled_by_default) end end if disabled_by_default config = handle_disabled_by_default(config, default_configuration) end Config.new(merge(default_configuration, config), config_file) end # Returns a new hash where the parameters of the given config hash have # been replaced by parameters returned by the given block. # Return a recursive merge of two hashes. That is, a normal hash merge, # with the addition that any value that is a hash, and occurs in both # arguments, will also be merged. And so on. def merge(base_hash, derived_hash) result = base_hash.merge(derived_hash) keys_appearing_in_both = base_hash.keys & derived_hash.keys keys_appearing_in_both.each do |key| next unless base_hash[key].is_a?(Hash) result[key] = merge(base_hash[key], derived_hash[key]) end result end private def base_configs(path, inherit_from, file) configs = Array(inherit_from).compact.map do |f| ConfigLoader.load_file(inherited_file(path, f, file)) end configs.compact end def inherited_file(path, inherit_from, file) regex = URI::DEFAULT_PARSER.make_regexp(%w[http https]) if inherit_from =~ /\A#{regex}\z/ RemoteConfig.new(inherit_from, File.dirname(path)) elsif file.is_a?(RemoteConfig) file.inherit_from_remote(inherit_from, path) else print 'Inheriting ' if ConfigLoader.debug? File.expand_path(inherit_from, File.dirname(path)) end end def handle_disabled_by_default(config, new_default_configuration) department_config = config.to_hash.reject { |cop| cop.include?('/') } department_config.each do |dept, dept_params| # Rails is always disabled by default and the department's Enabled flag # works like the --rails command line option, which is that when # AllCops:DisabledByDefault is true, each Rails cop must still be # explicitly mentioned in user configuration in order to be enabled. next if dept == 'Rails' next unless dept_params['Enabled'] new_default_configuration.each do |cop, params| next unless cop.start_with?(dept + '/') # Retain original default configuration for cops in the department. params['Enabled'] = ConfigLoader.default_configuration[cop]['Enabled'] end end transform(config) do |params| { 'Enabled' => true }.merge(params) # Set true if not set. end end def transform(config) Hash[config.map { |cop, params| [cop, yield(params)] }] end def gem_config_path(gem_name, relative_config_path) spec = Gem::Specification.find_by_name(gem_name) return File.join(spec.gem_dir, relative_config_path) rescue Gem::LoadError => e raise Gem::LoadError, "Unable to find gem #{gem_name}; is the gem installed? #{e}" end end end rubocop-0.52.1/lib/rubocop/config_store.rb000066400000000000000000000031141322072016200204670ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop # Handles caching of configurations and association of inspected # ruby files to configurations. class ConfigStore def initialize # @options_config stores a config that is specified in the command line. # This takes precedence over configs located in any directories @options_config = nil # @path_cache maps directories to configuration paths. We search # for .rubocop.yml only if we haven't already found it for the # given directory. @path_cache = {} # @object_cache maps configuration file paths to # configuration objects so we only need to load them once. @object_cache = {} end def options_config=(options_config) loaded_config = ConfigLoader.load_file(options_config) @options_config = ConfigLoader.merge_with_default(loaded_config, options_config) end def force_default_config! @options_config = ConfigLoader.default_configuration end def for(file_or_dir) return @options_config if @options_config dir = if File.directory?(file_or_dir) file_or_dir else File.dirname(file_or_dir) end @path_cache[dir] ||= ConfigLoader.configuration_file_for(dir) path = @path_cache[dir] @object_cache[path] ||= begin print "For #{dir}: " if ConfigLoader.debug? ConfigLoader.configuration_from_file(path) end end end end rubocop-0.52.1/lib/rubocop/cop/000077500000000000000000000000001322072016200162435ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/autocorrect_logic.rb000066400000000000000000000012041322072016200222740ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This module encapsulates the logic for autocorrect behavior for a cop. module AutocorrectLogic def autocorrect? autocorrect_requested? && support_autocorrect? && autocorrect_enabled? end def autocorrect_requested? @options.fetch(:auto_correct, false) end def support_autocorrect? respond_to?(:autocorrect) end def autocorrect_enabled? # allow turning off autocorrect on a cop by cop basis return true unless cop_config cop_config['AutoCorrect'] != false end end end end rubocop-0.52.1/lib/rubocop/cop/badge.rb000066400000000000000000000033561322072016200176410ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # Identifier of all cops containing a department and cop name. # # All cops are identified by their badge. For example, the badge # for `RuboCop::Cop::Layout::Tab` is `Layout/Tab`. Badges can be # parsed as either `Department/CopName` or just `CopName` to allow # for badge references in source files that omit the department # for RuboCop to infer. class Badge # Error raised when a badge parse fails. class InvalidBadge < Error MSG = 'Invalid badge %p. ' \ 'Expected `Department/CopName` or `CopName`.'.freeze def initialize(token) super(format(MSG, badge: token)) end end attr_reader :department, :cop_name def self.for(class_name) new(*class_name.split('::').last(2)) end def self.parse(identifier) parts = identifier.split('/', 2) raise InvalidBadge, identifier if parts.size > 2 if parts.one? new(nil, *parts) else new(*parts) end end def initialize(department, cop_name) @department = department.to_sym if department @cop_name = cop_name end def ==(other) hash == other.hash end alias eql? == def hash [department, cop_name].hash end def match?(other) cop_name == other.cop_name && (!qualified? || department == other.department) end def to_s qualified? ? "#{department}/#{cop_name}" : cop_name end def qualified? !department.nil? end def with_department(department) self.class.new(department, cop_name) end end end end rubocop-0.52.1/lib/rubocop/cop/bundler/000077500000000000000000000000001322072016200176765ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/bundler/duplicated_gem.rb000066400000000000000000000036031322072016200231730ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Bundler # A Gem's requirements should be listed only once in a Gemfile. # @example # # bad # gem 'rubocop' # gem 'rubocop' # # # bad # group :development do # gem 'rubocop' # end # # group :test do # gem 'rubocop' # end # # # good # group :development, :test do # gem 'rubocop' # end # # # good # gem 'rubocop', groups: [:development, :test] class DuplicatedGem < Cop MSG = 'Gem `%s` requirements already given on line '\ '%d of the Gemfile.'.freeze def investigate(processed_source) return unless processed_source.ast duplicated_gem_nodes.each do |nodes| nodes[1..-1].each do |node| register_offense( node, node.first_argument.to_a.first, nodes.first.first_line ) end end end private def_node_search :gem_declarations, '(send nil? :gem str ...)' def duplicated_gem_nodes gem_declarations(processed_source.ast) .group_by(&:first_argument) .values .select { |nodes| nodes.size > 1 } end def register_offense(node, gem_name, line_of_first_occurrence) line_range = node.loc.column...node.loc.last_column offense_location = source_range(processed_source.buffer, node.first_line, line_range) message = format( MSG, gem_name: gem_name, line_of_first_occurrence: line_of_first_occurrence ) add_offense(node, location: offense_location, message: message) end end end end end rubocop-0.52.1/lib/rubocop/cop/bundler/insecure_protocol_source.rb000066400000000000000000000042161322072016200253440ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Bundler # The symbol argument `:gemcutter`, `:rubygems` and `:rubyforge` # are deprecated. So please change your source to URL string that # 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. # # This autocorrect will replace these symbols with 'https://rubygems.org'. # Because it is secure, HTTPS request is strongly recommended. And in # most use cases HTTPS will be fine. # # However, it don't replace all `sources` of `http://` with `https://`. # For example, when specifying an internal gem server using HTTP on the # intranet, a use case where HTTPS can not be specified was considered. # Consider using HTTP only if you can not use HTTPS. # # @example # # bad # source :gemcutter # source :rubygems # source :rubyforge # # # good # source 'https://rubygems.org' # strongly recommended # source 'http://rubygems.org' class InsecureProtocolSource < Cop MSG = 'The source `:%s` is deprecated because HTTP requests ' \ 'are insecure. ' \ "Please change your source to 'https://rubygems.org' " \ "if possible, or 'http://rubygems.org' if not.".freeze def_node_matcher :insecure_protocol_source?, <<-PATTERN (send nil? :source (sym ${:gemcutter :rubygems :rubyforge})) PATTERN def on_send(node) insecure_protocol_source?(node) do |source| message = format(MSG, source: source) add_offense( node, location: source_range(node.first_argument.loc.expression), message: message ) end end def autocorrect(node) lambda do |corrector| corrector.replace( node.first_argument.loc.expression, "'https://rubygems.org'" ) end end private def source_range(node) range_between(node.begin_pos, node.end_pos) end end end end end rubocop-0.52.1/lib/rubocop/cop/bundler/ordered_gems.rb000066400000000000000000000035441322072016200226700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Bundler # Gems should be alphabetically sorted within groups. # # @example # # bad # gem 'rubocop' # gem 'rspec' # # # good # gem 'rspec' # gem 'rubocop' # # # good # gem 'rubocop' # # gem 'rspec' # # # good only if TreatCommentsAsGroupSeparators is true # # For code quality # gem 'rubocop' # # For tests # gem 'rspec' class OrderedGems < Cop include ConfigurableEnforcedStyle include OrderedGemNode MSG = 'Gems should be sorted in an alphabetical order within their '\ 'section of the Gemfile. '\ 'Gem `%s` should appear before `%s`.'.freeze def investigate(processed_source) return if processed_source.ast.nil? gem_declarations(processed_source.ast) .each_cons(2) do |previous, current| next unless consecutive_lines(previous, current) next unless case_insensitive_out_of_order?( gem_name(current), gem_name(previous) ) register_offense(previous, current) end end def autocorrect(node) OrderedGemCorrector.correct( processed_source, node, previous_declaration(node), treat_comments_as_separators ) end private def previous_declaration(node) declarations = gem_declarations(processed_source.ast) node_index = declarations.find_index(node) declarations.to_a[node_index - 1] end def_node_search :gem_declarations, <<-PATTERN (:send nil? :gem str ...) PATTERN end end end end rubocop-0.52.1/lib/rubocop/cop/commissioner.rb000066400000000000000000000073571322072016200213130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # Commissioner class is responsible for processing the AST and delegating # work to the specified cops. class Commissioner include RuboCop::AST::Traversal CopError = Struct.new(:error, :line, :column) attr_reader :errors def self.callback_methods Parser::Meta::NODE_TYPES.map { |type| :"on_#{type}" } end def initialize(cops, forces = [], options = {}) @cops = cops @forces = forces @options = options @callbacks = {} reset_errors end # In the dynamically generated methods below, a call to `super` is used # to continue iterating over the children of a node. # However, if we know that a certain node type (like `int`) never has # child nodes, there is no reason to pay the cost of calling `super`. no_child_callbacks = NO_CHILD_NODES.map do |type| :"on_#{type}" end callback_methods.each do |callback| next unless method_defined?(callback) class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{callback}(node) @callbacks[:"#{callback}"] ||= @cops.select do |cop| cop.respond_to?(:"#{callback}") end @callbacks[:#{callback}].each do |cop| with_cop_error_handling(cop, node) do cop.send(:#{callback}, node) end end #{!no_child_callbacks.include?(callback) && 'super'} end RUBY end def investigate(processed_source) reset_errors remove_irrelevant_cops(processed_source.buffer.name) reset_callbacks prepare(processed_source) invoke_custom_processing(@cops, processed_source) invoke_custom_processing(@forces, processed_source) walk(processed_source.ast) if processed_source.ast @cops.flat_map(&:offenses) end private def reset_errors @errors = Hash.new { |hash, k| hash[k] = [] } end def remove_irrelevant_cops(filename) @cops.reject! { |cop| cop.excluded_file?(filename) } @cops.reject! do |cop| cop.class.respond_to?(:support_target_ruby_version?) && !cop.class.support_target_ruby_version?(cop.target_ruby_version) end @cops.reject! do |cop| cop.class.respond_to?(:support_target_rails_version?) && !cop.class.support_target_rails_version?(cop.target_rails_version) end end def reset_callbacks @callbacks.clear end # TODO: Bad design. def prepare(processed_source) @cops.each { |cop| cop.processed_source = processed_source } end # There are cops/forces that require their own custom processing. # If they define the #investigate method, all input parameters passed # to the commissioner will be passed to the cop too in order to do # its own processing. def invoke_custom_processing(cops_or_forces, processed_source) cops_or_forces.each do |cop| next unless cop.respond_to?(:investigate) with_cop_error_handling(cop) do cop.investigate(processed_source) end end end # Allow blind rescues here, since we're absorbing and packaging or # re-raising exceptions that can be raised from within the individual # cops' `#investigate` methods. def with_cop_error_handling(cop, node = nil) yield rescue StandardError => e raise e if @options[:raise_error] if node line = node.first_line column = node.loc.column end error = CopError.new(e, line, column) @errors[cop] << error end end end end rubocop-0.52.1/lib/rubocop/cop/cop.rb000066400000000000000000000140561322072016200173570ustar00rootroot00000000000000# frozen_string_literal: true require 'uri' module RuboCop module Cop # A scaffold for concrete cops. # # The Cop class is meant to be extended. # # Cops track offenses and can autocorrect them on the fly. # # A commissioner object is responsible for traversing the AST and invoking # the specific callbacks on each cop. # If a cop needs to do its own processing of the AST or depends on # something else, it should define the `#investigate` method and do # the processing there. # # @example # # class CustomCop < Cop # def investigate(processed_source) # # Do custom processing # end # end class Cop extend RuboCop::AST::Sexp extend NodePattern::Macros include RuboCop::AST::Sexp include Util include IgnoredNode include AutocorrectLogic attr_reader :config, :offenses, :corrections attr_accessor :processed_source # TODO: Bad design. @registry = Registry.new class << self attr_reader :registry end def self.all registry.without_department(:Test).cops end def self.qualified_cop_name(name, origin) registry.qualified_cop_name(name, origin) end def self.non_rails registry.without_department(:Rails) end def self.inherited(subclass) registry.enlist(subclass) end def self.badge @badge ||= Badge.for(name) end def self.cop_name badge.to_s end def self.department badge.department end def self.lint? department == :Lint end # Returns true if the cop name or the cop namespace matches any of the # given names. def self.match?(given_names) return false unless given_names given_names.include?(cop_name) || given_names.include?(department.to_s) end # List of cops that should not try to autocorrect at the same # time as this cop # # @return [Array] # # @api public def self.autocorrect_incompatible_with [] end def initialize(config = nil, options = nil) @config = config || Config.new @options = options || { debug: false } @offenses = [] @corrections = [] @processed_source = nil end def join_force?(_force_class) false end def cop_config # Use department configuration as basis, but let individual cop # configuration override. @cop_config ||= @config.for_cop(self.class.department.to_s) .merge(@config.for_cop(self)) end def message(_node = nil) self.class::MSG end # rubocop:disable Metrics/CyclomaticComplexity def add_offense(node, location: :expression, message: nil, severity: nil) loc = find_location(node, location) return if duplicate_location?(loc) severity = custom_severity || severity || default_severity message ||= message(node) message = annotate(message) status = enabled_line?(loc.line) ? correct(node) : :disabled @offenses << Offense.new(severity, loc, message, name, status) yield if block_given? && status != :disabled end # rubocop:enable Metrics/CyclomaticComplexity def find_location(node, loc) # Location can be provided as a symbol, e.g.: `:keyword` loc.is_a?(Symbol) ? node.loc.public_send(loc) : loc end def duplicate_location?(location) @offenses.any? { |o| o.location == location } end def correct(node) return :unsupported unless support_autocorrect? return :uncorrected unless autocorrect? correction = autocorrect(node) return :uncorrected unless correction @corrections << correction :corrected end def config_to_allow_offenses Formatter::DisabledConfigFormatter .config_to_allow_offenses[cop_name] ||= {} end def config_to_allow_offenses=(hash) Formatter::DisabledConfigFormatter.config_to_allow_offenses[cop_name] = hash end def target_ruby_version @config.target_ruby_version end def target_rails_version @config.target_rails_version end def parse(source, path = nil) ProcessedSource.new(source, target_ruby_version, path) end def cop_name @cop_name ||= self.class.cop_name end alias name cop_name def relevant_file?(file) file_name_matches_any?(file, 'Include', true) && !file_name_matches_any?(file, 'Exclude', false) end def excluded_file?(file) !relevant_file?(file) end private def annotate(message) RuboCop::Cop::MessageAnnotator.new( config, cop_config, @options ).annotate(message, name) end def file_name_matches_any?(file, parameter, default_result) patterns = cop_config[parameter] return default_result unless patterns path = nil patterns.any? do |pattern| # Try to match the absolute path, as Exclude properties are absolute. next true if match_path?(pattern, file) # Try with relative path. path ||= config.path_relative_to_config(file) match_path?(pattern, path) end end def enabled_line?(line_number) return true unless @processed_source @processed_source.comment_config.cop_enabled_at_line?(self, line_number) end def default_severity self.class.lint? ? :warning : :convention end def custom_severity severity = cop_config['Severity'] return unless severity if Severity::NAMES.include?(severity.to_sym) severity.to_sym else message = "Warning: Invalid severity '#{severity}'. " \ "Valid severities are #{Severity::NAMES.join(', ')}." warn(Rainbow(message).red) end end end end end rubocop-0.52.1/lib/rubocop/cop/corrector.rb000066400000000000000000000106271322072016200206000ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This class takes a source buffer and rewrite its source # based on the different correction rules supplied. # # Important! # The nodes modified by the corrections should be part of the # AST of the source_buffer. class Corrector # # @param source_buffer [Parser::Source::Buffer] # @param corrections [Array(#call)] # Array of Objects that respond to #call. They will receive the # corrector itself and should use its method to modify the source. # # @example # # class AndOrCorrector # def initialize(node) # @node = node # end # # def call(corrector) # replacement = (@node.type == :and ? '&&' : '||') # corrector.replace(@node.loc.operator, replacement) # end # end # # corrections = [AndOrCorrector.new(node)] # corrector = Corrector.new(source_buffer, corrections) def initialize(source_buffer, corrections = []) @source_buffer = source_buffer @corrections = corrections @source_rewriter = Parser::Source::Rewriter.new(source_buffer) @diagnostics = [] # Don't print warnings to stderr if corrections conflict with each other @source_rewriter.diagnostics.consumer = lambda do |diagnostic| @diagnostics << diagnostic end end attr_reader :corrections, :diagnostics # Does the actual rewrite and returns string corresponding to # the rewritten source. # # @return [String] def rewrite # rubocop:disable Lint/HandleExceptions @corrections.each do |correction| begin @source_rewriter.transaction do correction.call(self) end rescue ::Parser::ClobberingError end end # rubocop:enable Lint/HandleExceptions @source_rewriter.process end # Removes the source range. # # @param [Parser::Source::Range] range def remove(range) @source_rewriter.remove(range) end # Inserts new code before the given source range. # # @param [Parser::Source::Range] range # @param [String] content def insert_before(range, content) @source_rewriter.insert_before(range, content) end # Inserts new code after the given source range. # # @param [Parser::Source::Range] range # @param [String] content def insert_after(range, content) @source_rewriter.insert_after(range, content) end # Replaces the code of the source range `range` with `content`. # # @param [Parser::Source::Range] range # @param [String] content def replace(range, content) @source_rewriter.replace(range, content) end # Removes `size` characters prior to the source range. # # @param [Parser::Source::Range] range # @param [Integer] size def remove_preceding(range, size) to_remove = Parser::Source::Range.new(range.source_buffer, range.begin_pos - size, range.begin_pos) @source_rewriter.remove(to_remove) end # Removes `size` characters from the beginning of the given range. # If `size` is greater than the size of `range`, the removed region can # overrun the end of `range`. # # @param [Parser::Source::Range] range # @param [Integer] size def remove_leading(range, size) to_remove = Parser::Source::Range.new(range.source_buffer, range.begin_pos, range.begin_pos + size) @source_rewriter.remove(to_remove) end # Removes `size` characters from the end of the given range. # If `size` is greater than the size of `range`, the removed region can # overrun the beginning of `range`. # # @param [Parser::Source::Range] range # @param [Integer] size def remove_trailing(range, size) to_remove = Parser::Source::Range.new(range.source_buffer, range.end_pos - size, range.end_pos) @source_rewriter.remove(to_remove) end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/000077500000000000000000000000001322072016200204305ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/correctors/alignment_corrector.rb000066400000000000000000000073771322072016200250330ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This class does auto-correction of nodes that should just be moved to # the left or to the right, amount being determined by the instance # variable column_delta. class AlignmentCorrector extend Util extend Alignment class << self attr_reader :processed_source def correct(processed_source, node, column_delta) return unless node @processed_source = processed_source expr = node.respond_to?(:loc) ? node.loc.expression : node return if block_comment_within?(expr) lambda do |corrector| each_line(expr) do |line_begin_pos| autocorrect_line(corrector, line_begin_pos, expr, column_delta, heredoc_ranges(node)) end end end def align_end(processed_source, node, align_to) @processed_source = processed_source whitespace = whitespace_range(node) return false unless whitespace.source.strip.empty? column = alignment_column(align_to) ->(corrector) { corrector.replace(whitespace, ' ' * column) } end private def autocorrect_line(corrector, line_begin_pos, expr, column_delta, heredoc_ranges) range = calculate_range(expr, line_begin_pos, column_delta) # We must not change indentation of heredoc strings. return if heredoc_ranges.any? { |h| within?(range, h) } if column_delta > 0 unless range.source == "\n" corrector.insert_before(range, ' ' * column_delta) end elsif range.source =~ /\A[ \t]+\z/ remove(range, corrector) end end def heredoc_ranges(node) return [] unless node.is_a?(Parser::AST::Node) node.each_node(:dstr) .select { |n| n.loc.respond_to?(:heredoc_body) } .map { |n| n.loc.heredoc_body.join(n.loc.heredoc_end) } end def block_comment_within?(expr) processed_source.comments.select(&:document?).any? do |c| within?(c.loc.expression, expr) end end def calculate_range(expr, line_begin_pos, column_delta) starts_with_space = expr.source_buffer.source[line_begin_pos] =~ / / pos_to_remove = if column_delta > 0 || starts_with_space line_begin_pos else line_begin_pos - column_delta.abs end range_between(pos_to_remove, pos_to_remove + column_delta.abs) end def remove(range, corrector) original_stderr = $stderr $stderr = StringIO.new # Avoid error messages on console corrector.remove(range) rescue RuntimeError range = range_between(range.begin_pos + 1, range.end_pos + 1) retry if range.source =~ /^ +$/ ensure $stderr = original_stderr end def each_line(expr) line_begin_pos = expr.begin_pos expr.source.each_line do |line| yield line_begin_pos line_begin_pos += line.length end end def begins_its_line?(range) (range.source_line =~ /\S/) == range.column end def whitespace_range(node) begin_pos = node.loc.end.begin_pos range_between(begin_pos - node.loc.end.column, begin_pos) end def alignment_column(align_to) if !align_to 0 elsif align_to.respond_to?(:loc) align_to.source_range.column else align_to.column end end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/condition_corrector.rb000066400000000000000000000013171322072016200250270ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This class does condition auto-correction class ConditionCorrector class << self def correct_negative_condition(node) condition = negated_condition(node) lambda do |corrector| corrector.replace(node.loc.keyword, node.inverse_keyword) corrector.replace(condition.source_range, condition.children.first.source) end end private def negated_condition(node) condition = node.condition condition = condition.children.first while condition.begin_type? condition end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/empty_line_corrector.rb000066400000000000000000000011761322072016200252110ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This class does empty line auto-correction class EmptyLineCorrector class << self def correct(node) offense_style, range = node lambda do |corrector| case offense_style when :no_empty_lines then corrector.remove(range) when :empty_lines then corrector.insert_before(range, "\n") end end end def insert_before(node) ->(corrector) { corrector.insert_before(node.source_range, "\n") } end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb000066400000000000000000000040231322072016200277100ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # Autocorrection logic for the closing brace of a literal either # on the same line as the last contained elements, or a new line. class MultilineLiteralBraceCorrector extend MultilineLiteralBraceLayout extend Util class << self attr_reader :processed_source # rubocop:disable Metrics/MethodLength def correct(processed_source, node) @processed_source = processed_source if closing_brace_on_same_line?(node) lambda do |corrector| corrector.insert_before(node.loc.end, "\n".freeze) end else # When a comment immediately before the closing brace gets in the # way of an easy correction, the offense is reported but not auto- # corrected. The user must handle the delicate decision of where to # put the comment. return if new_line_needed_before_closing_brace?(node) lambda do |corrector| corrector.remove(range_with_surrounding_space(range: node.loc.end, side: :left)) corrector.insert_after( last_element_range_with_trailing_comma(node), node.loc.end.source ) end end end # rubocop:enable Metrics/MethodLength private def last_element_range_with_trailing_comma(node) trailing_comma_range = last_element_trailing_comma_range(node) if trailing_comma_range children(node).last.source_range.join(trailing_comma_range) else children(node).last.source_range end end def last_element_trailing_comma_range(node) range = range_with_surrounding_space( range: children(node).last.source_range, side: :right ).end.resize(1) range.source == ',' ? range : nil end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/ordered_gem_corrector.rb000066400000000000000000000025031322072016200253130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects gem dependency order class OrderedGemCorrector extend OrderedGemNode class << self attr_reader :processed_source, :comments_as_separators def correct(processed_source, node, previous_declaration, comments_as_separators) @processed_source = processed_source @comments_as_separators = comments_as_separators current_range = declaration_with_comment(node) previous_range = declaration_with_comment(previous_declaration) lambda do |corrector| swap_range(corrector, current_range, previous_range) end end private def declaration_with_comment(node) buffer = processed_source.buffer begin_pos = get_source_range(node, comments_as_separators).begin_pos end_line = buffer.line_for_position(node.loc.expression.end_pos) end_pos = buffer.line_range(end_line).end_pos Parser::Source::Range.new(buffer, begin_pos, end_pos) end def swap_range(corrector, range1, range2) src1 = range1.source src2 = range2.source corrector.replace(range1, src2) corrector.replace(range2, src1) end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/parentheses_corrector.rb000066400000000000000000000013671322072016200253670ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects parentheses class ParenthesesCorrector class << self def correct(node) lambda do |corrector| corrector.remove(node.loc.begin) corrector.remove(node.loc.end) if ternary_condition?(node) && next_char_is_question_mark?(node) corrector.insert_after(node.loc.end, ' ') end end end private def ternary_condition?(node) node.parent && node.parent.if_type? && node.parent.ternary? end def next_char_is_question_mark?(node) node.loc.last_column == node.parent.loc.question.column end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/punctuation_corrector.rb000066400000000000000000000012551322072016200254130ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects punctuation class PunctuationCorrector class << self def remove_space(space_before) ->(corrector) { corrector.remove(space_before) } end def add_space(token) ->(corrector) { corrector.replace(token.pos, token.pos.source + ' ') } end def swap_comma(range) return unless range lambda do |corrector| case range.source when ',' then corrector.remove(range) else corrector.insert_after(range, ',') end end end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/space_corrector.rb000066400000000000000000000020221322072016200241260ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects whitespace class SpaceCorrector extend SurroundingSpace class << self attr_reader :processed_source def remove_space(processed_source, corrector, left_token, right_token) @processed_source = processed_source if left_token.space_after? range = side_space_range(range: left_token.pos, side: :right) corrector.remove(range) end return unless right_token.space_before? range = side_space_range(range: right_token.pos, side: :left) corrector.remove(range) end def add_space(processed_source, corrector, left_token, right_token) @processed_source = processed_source unless left_token.space_after? corrector.insert_after(left_token.pos, ' ') end return if right_token.space_before? corrector.insert_before(right_token.pos, ' ') end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/string_literal_corrector.rb000066400000000000000000000010761322072016200260650ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects string literals class StringLiteralCorrector extend Util class << self def correct(node, style) return if node.dstr_type? lambda do |corrector| str = node.str_content if style == :single_quotes corrector.replace(node.source_range, to_string_literal(str)) else corrector.replace(node.source_range, str.inspect) end end end end end end end rubocop-0.52.1/lib/rubocop/cop/correctors/unused_arg_corrector.rb000066400000000000000000000014771322072016200252040ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # This auto-corrects unused arguments. class UnusedArgCorrector extend Util class << self attr_reader :processed_source def correct(processed_source, node) return if %i[kwarg kwoptarg].include?(node.type) @processed_source = processed_source if node.blockarg_type? lambda do |corrector| range = range_with_surrounding_space(range: node.source_range, side: :left) range = range_with_surrounding_comma(range, :left) corrector.remove(range) end else ->(corrector) { corrector.insert_before(node.loc.name, '_') } end end end end end end rubocop-0.52.1/lib/rubocop/cop/force.rb000066400000000000000000000013711322072016200176700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # A scaffold for concrete forces. class Force attr_reader :cops def self.all @all ||= [] end def self.inherited(subclass) all << subclass end def self.force_name name.split('::').last end def initialize(cops) @cops = cops end def name self.class.force_name end def run_hook(method_name, *args) cops.each do |cop| next unless cop.respond_to?(method_name) cop.send(method_name, *args) end end def investigate(_processed_source) # Do custom processing and invoke #run_hook at arbitrary timing. end end end end rubocop-0.52.1/lib/rubocop/cop/gemspec/000077500000000000000000000000001322072016200176665ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/gemspec/duplicated_assignment.rb000066400000000000000000000062061322072016200245650ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Gemspec # An attribute assignment method calls should be listed only once # in a gemspec. # # Assigning to an attribute with the same name using `spec.foo =` will be # an unintended usage. On the other hand, duplication of methods such # as `spec.requirements`, `spec.add_runtime_dependency` and others are # permitted because it is the intended use of appending values. # # @example # # bad # Gem::Specification.new do |spec| # spec.name = 'rubocop' # spec.name = 'rubocop2' # end # # # good # Gem::Specification.new do |spec| # spec.name = 'rubocop' # end # # # good # Gem::Specification.new do |spec| # spec.requirements << 'libmagick, v6.0' # spec.requirements << 'A good graphics card' # end # # # good # Gem::Specification.new do |spec| # spec.add_runtime_dependency('parallel', '~> 1.10') # spec.add_runtime_dependency('parser', '>= 2.3.3.1', '< 3.0') # end class DuplicatedAssignment < Cop MSG = '`%s` method calls already given on line '\ '%d of the gemspec.'.freeze def_node_search :gem_specification, <<-PATTERN (block (send (const (const {cbase nil?} :Gem) :Specification) :new) (args (arg $_)) ...) PATTERN def_node_search :assignment_method_declarations, <<-PATTERN (send (lvar #match_block_variable_name?) #assignment_method? ...) PATTERN def investigate(processed_source) return unless processed_source.ast duplicated_assignment_method_nodes.each do |nodes| nodes[1..-1].each do |node| register_offense( node, node.method_name, nodes.first.first_line ) end end end private def match_block_variable_name?(receiver_name) gem_specification(processed_source.ast) do |block_variable_name| return block_variable_name == receiver_name end end def assignment_method?(method_name) method_name.to_s.end_with?('=') end def duplicated_assignment_method_nodes assignment_method_declarations(processed_source.ast) .group_by(&:method_name) .values .select { |nodes| nodes.size > 1 } end def register_offense(node, assignment, line_of_first_occurrence) line_range = node.loc.column...node.loc.last_column offense_location = source_range(processed_source.buffer, node.first_line, line_range) message = format( MSG, assignment: assignment, line_of_first_occurrence: line_of_first_occurrence ) add_offense(node, location: offense_location, message: message) end end end end end rubocop-0.52.1/lib/rubocop/cop/gemspec/ordered_dependencies.rb000066400000000000000000000060341322072016200243500ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Gemspec # Dependencies in the gemspec should be alphabetically sorted. # # @example # # bad # spec.add_dependency 'rubocop' # spec.add_dependency 'rspec' # # # good # spec.add_dependency 'rspec' # spec.add_dependency 'rubocop' # # # good # spec.add_dependency 'rubocop' # # spec.add_dependency 'rspec' # # # bad # spec.add_development_dependency 'rubocop' # spec.add_development_dependency 'rspec' # # # good # spec.add_development_dependency 'rspec' # spec.add_development_dependency 'rubocop' # # # good # spec.add_development_dependency 'rubocop' # # spec.add_development_dependency 'rspec' # # # bad # spec.add_runtime_dependency 'rubocop' # spec.add_runtime_dependency 'rspec' # # # good # spec.add_runtime_dependency 'rspec' # spec.add_runtime_dependency 'rubocop' # # # good # spec.add_runtime_dependency 'rubocop' # # spec.add_runtime_dependency 'rspec' # # # good only if TreatCommentsAsGroupSeparators is true # # For code quality # spec.add_dependency 'rubocop' # # For tests # spec.add_dependency 'rspec' class OrderedDependencies < Cop include ConfigurableEnforcedStyle include OrderedGemNode MSG = 'Dependencies should be sorted in an alphabetical order within ' \ 'their section of the gemspec. '\ 'Dependency `%s` should appear before `%s`.' .freeze def investigate(processed_source) return if processed_source.ast.nil? dependency_declarations(processed_source.ast) .each_cons(2) do |previous, current| next unless consecutive_lines(previous, current) next unless case_insensitive_out_of_order?( gem_name(current), gem_name(previous) ) unless get_dependency_name(previous) == get_dependency_name(current) next end register_offense(previous, current) end end def autocorrect(node) OrderedGemCorrector.correct( processed_source, node, previous_declaration(node), treat_comments_as_separators ) end private def previous_declaration(node) declarations = dependency_declarations(processed_source.ast) node_index = declarations.find_index(node) declarations.to_a[node_index - 1] end def get_dependency_name(node) node.method_name end def_node_search :dependency_declarations, <<-PATTERN (send (lvar _) {:add_dependency :add_runtime_dependency :add_development_dependency} ...) PATTERN end end end end rubocop-0.52.1/lib/rubocop/cop/gemspec/required_ruby_version.rb000066400000000000000000000051601322072016200246430ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Gemspec # Checks that `required_ruby_version` of gemspec and `TargetRubyVersion` # of .rubocop.yml are equal. # Thereby, RuboCop to perform static analysis working on the version # required by gemspec. # # @example # # When `TargetRubyVersion` of .rubocop.yml is `2.3`. # # # bad # Gem::Specification.new do |spec| # spec.required_ruby_version = '>= 2.2.0' # end # # # bad # Gem::Specification.new do |spec| # spec.required_ruby_version = '>= 2.4.0' # end # # # good # Gem::Specification.new do |spec| # spec.required_ruby_version = '>= 2.3.0' # end # # # good # Gem::Specification.new do |spec| # spec.required_ruby_version = '>= 2.3' # end # # # good # Gem::Specification.new do |spec| # spec.required_ruby_version = ['>= 2.3.0', '< 2.5.0'] # end class RequiredRubyVersion < Cop MSG = '`required_ruby_version` (%s, ' \ 'declared in %s) and `TargetRubyVersion` ' \ '(%s, declared in .rubocop.yml) ' \ 'should be equal.'.freeze def_node_search :required_ruby_version, <<-PATTERN (send _ :required_ruby_version= ${(str _) (array (str _))}) PATTERN def investigate(processed_source) required_ruby_version(processed_source.ast) do |version| ruby_version = extract_ruby_version(version) return if ruby_version == target_ruby_version.to_s add_offense( processed_source.ast, location: version.loc.expression, message: message(ruby_version, target_ruby_version) ) end end private def extract_ruby_version(required_ruby_version) if required_ruby_version.array_type? required_ruby_version = required_ruby_version.children.detect do |v| v.str_content =~ /[>=]/ end end required_ruby_version.str_content.match(/(\d\.\d)/)[1] end def message(required_ruby_version, target_ruby_version) file_path = processed_source.buffer.name format( MSG, required_ruby_version: required_ruby_version, gemspec_filename: File.basename(file_path), target_ruby_version: target_ruby_version ) end end end end end rubocop-0.52.1/lib/rubocop/cop/generator.rb000066400000000000000000000126541322072016200205660ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # Source and spec generator for new cops # # This generator will take a cop name and generate a source file # and spec file when given a valid qualified cop name. class Generator SOURCE_TEMPLATE = <<-RUBY.strip_indent # frozen_string_literal: true # TODO: when finished, run `rake generate_cops_documentation` to update the docs module RuboCop module Cop module %s # TODO: Write cop description and example of bad / good code. # # @example # # bad # bad_method() # # # bad # bad_method(args) # # # good # good_method() # # # good # good_method(args) class %s < Cop # TODO: Implement the cop into here. # # In many cases, you can use a node matcher for matching node pattern. # See. https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/node_pattern.rb # # For example MSG = 'Use `#good_method` instead of `#bad_method`.'.freeze def_node_matcher :bad_method?, <<-PATTERN (send nil? :bad_method ...) PATTERN def on_send(node) return unless bad_method?(node) add_offense(node) end end end end end RUBY SPEC_TEMPLATE = <<-SPEC.strip_indent # frozen_string_literal: true RSpec.describe RuboCop::Cop::%s::%s do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } # TODO: Write test code # # For example it 'registers an offense when using `#bad_method`' do expect_offense(<<-RUBY.strip_indent) bad_method ^^^^^^^^^^ Use `#good_method` instead of `#bad_method`. RUBY end it 'does not register an offense when using `#good_method`' do expect_no_offenses(<<-RUBY.strip_indent) good_method RUBY end end SPEC def initialize(name, output: $stdout) @badge = Badge.parse(name) @output = output return if badge.qualified? raise ArgumentError, 'Specify a cop name with Department/Name style' end def write_source write_unless_file_exists(source_path, generated_source) end def write_spec write_unless_file_exists(spec_path, generated_spec) end def inject_require(root_file_path: 'lib/rubocop.rb') RequireFileInjector.new( source_path: source_path, root_file_path: root_file_path ).inject end def inject_config(config_file_path: 'config/enabled.yml') config = File.readlines(config_file_path) content = <<-YAML.strip_indent #{badge}: Description: 'TODO: Write a description of the cop.' Enabled: true YAML target_line = config.find.with_index(1) do |line, index| next if line =~ /^[\s#]/ break index - 1 if badge.to_s < line end config.insert(target_line, content) File.write(config_file_path, config.join) output.puts <<-MESSAGE.strip_indent [modify] A configuration for the cop is added into #{config_file_path}. If you want to disable the cop by default, move the added config to config/disabled.yml MESSAGE end def todo <<-TODO.strip_indent Do 3 steps: 1. Add an entry to the "New features" section in CHANGELOG.md, e.g. "Add new `#{badge}` cop. ([@your_id][])" 2. Modify the description of #{badge} in config/enabled.yml 3. Implement your new cop in the generated file! TODO end private attr_reader :badge, :output def write_unless_file_exists(path, contents) if File.exist?(path) warn "rake new_cop: #{path} already exists!" exit! end dir = File.dirname(path) FileUtils.mkdir_p(dir) unless File.exist?(dir) File.write(path, contents) output.puts "[create] #{path}" end def generated_source generate(SOURCE_TEMPLATE) end def generated_spec generate(SPEC_TEMPLATE) end def generate(template) format(template, department: badge.department, cop_name: badge.cop_name) end def spec_path File.join( 'spec', 'rubocop', 'cop', snake_case(badge.department.to_s), "#{snake_case(badge.cop_name.to_s)}_spec.rb" ) end def source_path File.join( 'lib', 'rubocop', 'cop', snake_case(badge.department.to_s), "#{snake_case(badge.cop_name.to_s)}.rb" ) end def snake_case(camel_case_string) return 'rspec' if camel_case_string == 'RSpec' camel_case_string .gsub(/([^A-Z])([A-Z]+)/, '\1_\2') .gsub(/([A-Z])([A-Z][^A-Z\d]+)/, '\1_\2') .downcase end end end end rubocop-0.52.1/lib/rubocop/cop/generator/000077500000000000000000000000001322072016200202315ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/generator/require_file_injector.rb000066400000000000000000000045461322072016200251370ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop class Generator # A class that injects a require directive into the root RuboCop file. # It looks for other directives that require files in the same (cop) # namespace and injects the provided one in alpha class RequireFileInjector REQUIRE_PATH = /require_relative ['"](.+)['"]/ def initialize(source_path:, root_file_path:, output: $stdout) @source_path = Pathname(source_path) @root_file_path = Pathname(root_file_path) @require_entries = File.readlines(root_file_path) @output = output end def inject return if require_exists? || !target_line File.write(root_file_path, updated_directives) require = injectable_require_directive.chomp output.puts "[modify] #{root_file_path} - `#{require}` was injected." end private attr_reader :require_entries, :root_file_path, :source_path, :output def require_exists? require_entries.any? do |entry| entry == injectable_require_directive end end def updated_directives require_entries.insert(target_line, injectable_require_directive).join end def target_line @target_line ||= begin in_the_same_department = false inject_parts = require_path_fragments(injectable_require_directive) require_entries.find.with_index do |entry, index| current_entry_parts = require_path_fragments(entry) if inject_parts[0..-2] == current_entry_parts[0..-2] in_the_same_department = true break index if inject_parts.last < current_entry_parts.last elsif in_the_same_department break index end end end end def require_path_fragments(require_directove) path = require_directove.match(REQUIRE_PATH) path ? path.captures.first.split('/') : [] end def injectable_require_directive "require_relative '#{require_path}'\n" end def require_path path = source_path.relative_path_from(root_file_path.dirname) path.to_s.sub('.rb', '') end end end end end rubocop-0.52.1/lib/rubocop/cop/ignored_node.rb000066400000000000000000000017111322072016200212240ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop # Handles adding and checking ignored nodes. module IgnoredNode def ignore_node(node) ignored_nodes << node end def part_of_ignored_node?(node) ignored_nodes.map(&:loc).any? do |ignored_loc| if ignored_loc.expression.begin_pos > node.source_range.begin_pos next false end ignored_end_pos = if ignored_loc.respond_to?(:heredoc_body) ignored_loc.heredoc_end.end_pos else ignored_loc.expression.end_pos end ignored_end_pos >= node.source_range.end_pos end end def ignored_node?(node) # Same object found in array? ignored_nodes.any? { |n| n.equal?(node) } end private def ignored_nodes @ignored_nodes ||= [] end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs.rb000066400000000000000000000006101322072016200220740ustar00rootroot00000000000000# frozen_string_literal: true require_relative 'internal_affairs/node_destructuring' require_relative 'internal_affairs/node_type_predicate' require_relative 'internal_affairs/offense_location_keyword' require_relative 'internal_affairs/redundant_message_argument' require_relative 'internal_affairs/redundant_location_argument' require_relative 'internal_affairs/useless_message_assertion' rubocop-0.52.1/lib/rubocop/cop/internal_affairs/000077500000000000000000000000001322072016200215525ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/internal_affairs/node_destructuring.rb000066400000000000000000000022751322072016200260140ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks that node destructuring is done either using the node # extensions or using a splat. # # @example Using splat expansion # # # bad # receiver, method_name, arguments = send_node.children # # # good # receiver, method_name, arguments = *send_node # # @example Using node extensions # # # bad # _receiver, method_name, _arguments = send_node.children # # # good # method_name = send_node.method_name class NodeDestructuring < Cop MSG = 'Use the methods provided with the node extensions, or ' \ 'destructure the node using `*`.'.freeze def_node_matcher :node_children_destructuring?, <<-PATTERN (masgn (mlhs ...) (send (send nil? [#node_suffix? _]) :children)) PATTERN def on_masgn(node) node_children_destructuring?(node) do add_offense(node) end end private def node_suffix?(method_name) method_name.to_s.end_with?('node') end end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs/node_type_predicate.rb000066400000000000000000000023131322072016200261040ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks that node types are checked using the predicate helpers. # # @example # # # bad # node.type == :send # # # good # node.send_type? # class NodeTypePredicate < Cop MSG = 'Use `#%s_type?` to check node type.'.freeze def_node_matcher :node_type_check, <<-PATTERN (send (send $_ :type) :== (sym $_)) PATTERN def on_send(node) node_type_check(node) do |_receiver, node_type| return unless Parser::Meta::NODE_TYPES.include?(node_type) add_offense(node, message: format(MSG, type: node_type)) end end def autocorrect(node) receiver, node_type = node_type_check(node) range = Parser::Source::Range.new(node.source_range.source_buffer, receiver.loc.expression.end_pos + 1, node.loc.expression.end_pos) lambda do |corrector| corrector.replace(range, "#{node_type}_type?") end end end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb000066400000000000000000000031001322072016200271520ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks for potential uses of the location keywords which can be used as # shortcut arguments to `#add_offense`. # # @example # # # bad # add_offense(node, location: node.loc.selector) # # # good # add_offense(node, location: :selector) class OffenseLocationKeyword < Cop MSG = 'Use `:%s` as the location argument to ' \ '`#add_offense`.'.freeze def on_send(node) node_type_check(node) do |node_arg, kwargs| find_offending_argument(node_arg, kwargs) do |location, keyword| add_offense(location, message: format(MSG, keyword: keyword)) end end end def autocorrect(node) (*, keyword) = offending_location_argument(node.parent) ->(corrector) { corrector.replace(node.source_range, ":#{keyword}") } end private def_node_matcher :node_type_check, <<-PATTERN (send nil? :add_offense $_node $hash) PATTERN def_node_matcher :offending_location_argument, <<-PATTERN (pair (sym :location) $(send (send $_node :loc) $_keyword)) PATTERN def find_offending_argument(searched_node, kwargs) kwargs.pairs.each do |pair| offending_location_argument(pair) do |location, node, keyword| yield(location, keyword) if searched_node == node end end end end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb000066400000000000000000000030621322072016200276560ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks for redundant `location` argument to `#add_offense`. `location` # argument has a default value of `:expression` and this method will # automatically use it. # # @example # # # bad # add_offense(node, location: :expression) # # # good # add_offense(node) # add_offense(node, location: :selector) # class RedundantLocationArgument < Cop MSG = 'Redundant location argument to `#add_offense`.'.freeze def_node_matcher :add_offense_kwargs, <<-PATTERN (send nil? :add_offense _ $hash) PATTERN def_node_matcher :redundant_location_argument?, <<-PATTERN (pair (sym :location) (sym :expression)) PATTERN def on_send(node) redundant_location_argument(node) { |argument| add_offense(argument) } end def autocorrect(node) range = offending_range(node) ->(corrector) { corrector.remove(range) } end private def redundant_location_argument(node) add_offense_kwargs(node) do |kwargs| result = kwargs.pairs.find { |arg| redundant_location_argument?(arg) } yield result if result end end def offending_range(node) with_space = range_with_surrounding_space(range: node.loc.expression) range_with_surrounding_comma(with_space, :left) end end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb000066400000000000000000000040051322072016200274700ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks for redundant message arguments to `#add_offense`. This method # will automatically use `#message` or `MSG` (in that order of priority) # if they are defined. # # @example # # # bad # add_offense(node, message: MSG) # add_offense(node, message: message) # add_offense(node, message: message(node)) # # # good # add_offense(node) # add_offense(node, message: CUSTOM_MSG) # add_offense(node, message: message(other_node)) # class RedundantMessageArgument < Cop MSG = 'Redundant message argument to `#add_offense`.'.freeze def_node_matcher :node_type_check, <<-PATTERN (send nil? :add_offense $_node $hash) PATTERN def_node_matcher :redundant_message_argument, <<-PATTERN (pair (sym :message) ${(const nil? :MSG) (send nil? :message) (send nil? :message _)}) PATTERN def_node_matcher :message_method_call, '(send nil? :message $_node)' def on_send(node) node_type_check(node) do |node_arg, kwargs| find_offending_argument(node_arg, kwargs) do |pair| add_offense(pair) end end end def autocorrect(node) range = offending_range(node) ->(corrector) { corrector.remove(range) } end private def offending_range(node) with_space = range_with_surrounding_space(range: node.loc.expression) range_with_surrounding_comma(with_space, :left) end def find_offending_argument(searched_node, kwargs) kwargs.pairs.each do |pair| redundant_message_argument(pair) do |message_argument| node = message_method_call(message_argument) yield pair if !node || node == searched_node end end end end end end end rubocop-0.52.1/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb000066400000000000000000000026241322072016200273610ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module InternalAffairs # Checks that cops are not tested using `described_class::MSG`. # # @example # # # bad # expect(cop.messages).to eq([described_class::MSG]) # # # good # expect(cop.messages).to eq(['Do not write bad code like that.']) # class UselessMessageAssertion < Cop MSG = 'Do not specify cop behavior using `described_class::MSG`.'.freeze def_node_search :described_class_msg, <<-PATTERN (const (send nil? :described_class) :MSG) PATTERN def_node_matcher :rspec_expectation_on_msg?, <<-PATTERN (send (send nil? :expect #contains_described_class_msg?) :to ...) PATTERN def investigate(_processed_source) assertions_using_described_class_msg.each do |node| add_offense(node) end end private def contains_described_class_msg?(node) described_class_msg(node).any? end def assertions_using_described_class_msg described_class_msg(processed_source.ast).reject do |node| node.ancestors.any?(&method(:rspec_expectation_on_msg?)) end end # Only process spec files def relevant_file?(file) file.end_with?('_spec.rb') end end end end end rubocop-0.52.1/lib/rubocop/cop/layout/000077500000000000000000000000001322072016200175605ustar00rootroot00000000000000rubocop-0.52.1/lib/rubocop/cop/layout/access_modifier_indentation.rb000066400000000000000000000054661322072016200256330ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Layout # Modifiers should be indented as deep as method definitions, or as deep # as the class/module keyword, depending on configuration. # # @example EnforcedStyle: indent (default) # # bad # class Plumbus # private # def smooth; end # end # # # good # class Plumbus # private # def smooth; end # end # # @example EnforcedStyle: outdent # # bad # class Plumbus # private # def smooth; end # end # # # good # class Plumbus # private # def smooth; end # end class AccessModifierIndentation < Cop include Alignment include ConfigurableEnforcedStyle MSG = '%

 

app/controllers/application_controller.rb - 2 offenses

Line #1convention: Style/Documentation: Missing top-level class documentation comment.
class ApplicationController < ActionController::Base
Line #6convention: Style/AsciiComments: Use only ascii symbols in comments.
  # Test encoding issues by using curly quotes”

 

app/controllers/books_controller.rb - 11 offenses

Line #1convention: Style/Documentation: Missing top-level class documentation comment.
class BooksController < ApplicationController
Line #2convention: Style/SymbolArray: Use %i or %I for an array of symbols.
  before_action :set_book, only: [:show, :edit, :update, :destroy]
Line #12convention: Style/EmptyMethod: Put empty method definitions on a single line.
  def show ...
Line #21convention: Style/EmptyMethod: Put empty method definitions on a single line.
  def edit ...
Line #31convention: Metrics/LineLength: Line is too long. [83/80]
        format.html { redirect_to @book, notice: 'Book was successfully created.' }
Line #45convention: Metrics/LineLength: Line is too long. [83/80]
        format.html { redirect_to @book, notice: 'Book was successfully updated.' }
Line #59convention: Metrics/LineLength: Line is too long. [87/80]
      format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
Line #64convention: Layout/EmptyLinesAroundAccessModifier: Keep a blank line before and after private.
  private
Line #66convention: Layout/IndentationConsistency: Inconsistent indentation detected.
    def set_book ...
Line #70convention: Metrics/LineLength: Line is too long. [88/80]
    # Never trust parameters from the scary internet, only allow the white list through.
Line #71convention: Layout/IndentationConsistency: Inconsistent indentation detected.
    def book_params ...

 

app/models/book.rb - 6 offenses

Line #1convention: Style/Documentation: Missing top-level class documentation comment.
class Book < ActiveRecord::Base
Line #2convention: Naming/MethodName: Use snake_case for method names.
  def someMethod
Line #3warning: Lint/UselessAssignment: Useless assignment to variable - foo.
    foo = bar = baz
Line #3warning: Lint/UselessAssignment: Useless assignment to variable - bar.
    foo = bar = baz
Line #4convention: Style/RescueModifier: Avoid using rescue in its modifier form.
    Regexp.new(/\A<p>(.*)<\/p>\Z/m).match(full_document)[1] rescue full_document
Line #4convention: Style/RegexpLiteral: Use %r around regular expression.
    Regexp.new(/\A<p>(.*)<\/p>\Z/m).match(full_document)[1] rescue full_document
rubocop-0.52.1/spec/fixtures/html_formatter/project/000077500000000000000000000000001322072016200225435ustar00rootroot00000000000000rubocop-0.52.1/spec/fixtures/html_formatter/project/app/000077500000000000000000000000001322072016200233235ustar00rootroot00000000000000rubocop-0.52.1/spec/fixtures/html_formatter/project/app/controllers/000077500000000000000000000000001322072016200256715ustar00rootroot00000000000000rubocop-0.52.1/spec/fixtures/html_formatter/project/app/controllers/application_controller.rb000066400000000000000000000004021322072016200327600ustar00rootroot00000000000000class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception # “Test encoding issues by using curly quotes” end rubocop-0.52.1/spec/fixtures/html_formatter/project/app/controllers/books_controller.rb000066400000000000000000000033541322072016200316030ustar00rootroot00000000000000class BooksController < ApplicationController before_action :set_book, only: [:show, :edit, :update, :destroy] # GET /books # GET /books.json def index @books = Book.all end # GET /books/1 # GET /books/1.json def show end # GET /books/new def new @book = Book.new end # GET /books/1/edit def edit end # POST /books # POST /books.json def create @book = Book.new(book_params) respond_to do |format| if @book.save format.html { redirect_to @book, notice: 'Book was successfully created.' } format.json { render :show, status: :created, location: @book } else format.html { render :new } format.json { render json: @book.errors, status: :unprocessable_entity } end end end # PATCH/PUT /books/1 # PATCH/PUT /books/1.json def update respond_to do |format| if @book.update(book_params) format.html { redirect_to @book, notice: 'Book was successfully updated.' } format.json { render :show, status: :ok, location: @book } else format.html { render :edit } format.json { render json: @book.errors, status: :unprocessable_entity } end end end # DELETE /books/1 # DELETE /books/1.json def destroy @book.destroy respond_to do |format| format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' } format.json { head :no_content } end end private # Use callbacks to share common setup or constraints between actions. def set_book @book = Book.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def book_params params.require(:book).permit(:name) end end rubocop-0.52.1/spec/fixtures/html_formatter/project/app/models/000077500000000000000000000000001322072016200246065ustar00rootroot00000000000000rubocop-0.52.1/spec/fixtures/html_formatter/project/app/models/book.rb000066400000000000000000000002401322072016200260610ustar00rootroot00000000000000class Book < ActiveRecord::Base def someMethod foo = bar = baz Regexp.new(/\A

(.*)<\/p>\Z/m).match(full_document)[1] rescue full_document end end rubocop-0.52.1/spec/isolated_environment_spec.rb000066400000000000000000000014541322072016200217700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe 'isolated environment', :isolated_environment, type: :feature do include_context 'cli spec behavior' let(:cli) { RuboCop::CLI.new } # Configuration files above the work directory shall not disturb the # tests. This is especially important on Windows where the temporary # directory is under the user's home directory. On any platform we don't want # a .rubocop.yml file in the temporary directory to affect the outcome of # rspec. it 'is not affected by a config file above the work directory' do create_file('../.rubocop.yml', ['inherit_from: missing_file.yml']) create_file('ex.rb', ['# frozen_string_literal: true']) # A return value of 0 means that the erroneous config file was not read. expect(cli.run([])).to eq(0) end end rubocop-0.52.1/spec/project_spec.rb000066400000000000000000000126671322072016200172160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe 'RuboCop Project', type: :feature do let(:cop_names) do RuboCop::Cop::Cop .registry .without_department(:Test) .without_department(:InternalAffairs) .cops .map(&:cop_name) end shared_context 'configuration file' do |config_path| subject(:config) { RuboCop::ConfigLoader.load_file(config_path) } let(:configuration_keys) { config.keys } let(:raw_configuration) { config.to_h.values } end describe 'default configuration file' do include_context 'configuration file', 'config/default.yml' it 'has configuration for all cops' do expect(configuration_keys).to match_array(%w[AllCops Rails] + cop_names) end it 'has a nicely formatted description for all cops' do cop_names.each do |name| description = config[name]['Description'] expect(description.nil?).to be(false) expect(description).not_to include("\n") end end it 'has a SupportedStyles for all EnforcedStyle ' \ 'and EnforcedStyle is valid' do errors = [] cop_names.each do |name| enforced_styles = config[name] .select { |key, _| key.start_with?('Enforced') } enforced_styles.each_key do |style_name| supported_key = RuboCop::Cop::Util.to_supported_styles(style_name) valid = config[name][supported_key] errors.push("#{supported_key} is missing for #{name}") unless valid end end raise errors.join("\n") unless errors.empty? end end describe 'cop message' do let(:cops) { RuboCop::Cop::Cop.all } it 'end with a period or a question mark' do cops.each do |cop| begin msg = cop.const_get(:MSG) rescue NameError next end expect(msg).to match(/(?:[.?]|(?:\[.+\])|%s)$/) end end end describe 'config/disabled.yml' do include_context 'configuration file', 'config/disabled.yml' it 'disables all cops in the file' do expect(raw_configuration) .to all(match(hash_including('Enabled' => false))) end it 'sorts configuration keys alphabetically' do expect(configuration_keys).to eq configuration_keys.sort end end describe 'config/enabled.yml' do include_context 'configuration file', 'config/enabled.yml' it 'enables all cops in the file' do expect(raw_configuration) .to all(match(hash_including('Enabled' => true))) end it 'sorts configuration keys alphabetically' do expect(configuration_keys).to eq configuration_keys.sort end end describe 'changelog' do subject(:changelog) do path = File.join(File.dirname(__FILE__), '..', 'CHANGELOG.md') File.read(path) end it 'has link definitions for all implicit links' do implicit_link_names = changelog.scan(/\[([^\]]+)\]\[\]/).flatten.uniq implicit_link_names.each do |name| expect(changelog).to include("[#{name}]: http") end end describe 'entry' do subject(:entries) { lines.grep(/^\*/).map(&:chomp) } let(:lines) { changelog.each_line } it 'has a whitespace between the * and the body' do expect(entries).to all(match(/^\* \S/)) end context 'after version 0.14.0' do let(:lines) do changelog.each_line.take_while do |line| !line.start_with?('## 0.14.0') end end it 'has a link to the contributors at the end' do expect(entries).to all(match(/\(\[@\S+\]\[\](?:, \[@\S+\]\[\])*\)$/)) end end describe 'link to related issue' do let(:issues) do entries.map do |entry| entry.match(/\[(?[#\d]+)\]\((?[^\)]+)\)/) end.compact end it 'has an issue number prefixed with #' do issues.each do |issue| expect(issue[:number]).to match(/^#\d+$/) end end it 'has a valid URL' do issues.each do |issue| number = issue[:number].gsub(/\D/, '') pattern = %r{^https://github\.com/bbatsov/rubocop/(?:issues|pull)/#{number}$} # rubocop:disable Metrics/LineLength expect(issue[:url]).to match(pattern) end end it 'has a colon and a whitespace at the end' do entries_including_issue_link = entries.select do |entry| entry.match(/^\*\s*\[/) end expect(entries_including_issue_link).to all(include('): ')) end end describe 'body' do let(:bodies) do entries.map do |entry| entry .gsub(/`[^`]+`/, '``') .sub(/^\*\s*(?:\[.+?\):\s*)?/, '') .sub(/\s*\([^\)]+\)$/, '') end end it 'does not start with a lower case' do bodies.each do |body| expect(body).not_to match(/^[a-z]/) end end it 'ends with a punctuation' do expect(bodies).to all(match(/[\.\!]$/)) end end end end describe 'requiring all of `lib` with verbose warnings enabled' do it 'emits no warnings' do whitelisted = ->(line) { line =~ /warning: private attribute\?$/ } warnings = `ruby -Ilib -w -W2 lib/rubocop.rb 2>&1` .lines .grep(%r{/lib/rubocop}) # ignore warnings from dependencies .reject(&whitelisted) expect(warnings.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/000077500000000000000000000000001322072016200156465ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/ast/000077500000000000000000000000001322072016200164355ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/ast/and_node_spec.rb000066400000000000000000000057451322072016200215560ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::AndNode do let(:and_node) { parse_source(source).ast } describe '.new' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.is_a?(described_class)).to be(true) } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.is_a?(described_class)).to be(true) } end end describe '#logical_operator?' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.logical_operator?).to be(true) } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.logical_operator?).to be(false) } end end describe '#semantic_operator?' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.semantic_operator?).to be(false) } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.semantic_operator?).to be(true) } end end describe '#operator' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.operator).to eq('&&') } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.operator).to eq('and') } end end describe '#alternate_operator' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.alternate_operator).to eq('and') } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.alternate_operator).to eq('&&') } end end describe '#inverse_operator' do context 'with a logical and node' do let(:source) do ':foo && :bar' end it { expect(and_node.inverse_operator).to eq('||') } end context 'with a semantic and node' do let(:source) do ':foo and :bar' end it { expect(and_node.inverse_operator).to eq('or') } end end describe '#lhs' do context 'with a logical and node' do let(:source) do ':foo && 42' end it { expect(and_node.lhs.sym_type?).to be(true) } end context 'with a semantic and node' do let(:source) do ':foo and 42' end it { expect(and_node.lhs.sym_type?).to be(true) } end end describe '#rhs' do context 'with a logical and node' do let(:source) do ':foo && 42' end it { expect(and_node.rhs.int_type?).to be(true) } end context 'with a semantic and node' do let(:source) do ':foo and 42' end it { expect(and_node.rhs.int_type?).to be(true) } end end end rubocop-0.52.1/spec/rubocop/ast/args_node_spec.rb000066400000000000000000000035331322072016200217410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::ArgsNode do let(:args_node) { parse_source(source).ast.arguments } describe '.new' do context 'with a method definition' do let(:source) { 'def foo(x) end' } it { expect(args_node.is_a?(described_class)).to be(true) } end context 'with a block' do let(:source) { 'foo { |x| bar }' } it { expect(args_node.is_a?(described_class)).to be(true) } end context 'with a lambda literal' do let(:source) { '-> (x) { bar }' } it { expect(args_node.is_a?(described_class)).to be(true) } end end describe '#empty_and_without_delimiters?' do subject { args_node.empty_and_without_delimiters? } context 'with empty arguments' do context 'with a method definition' do let(:source) { 'def x; end' } it { is_expected.to be(true) } end context 'with a block' do let(:source) { 'x { }' } it { is_expected.to be(true) } end context 'with a lambda literal' do let(:source) { '-> { }' } it { is_expected.to be(true) } end end context 'with delimiters' do context 'with a method definition' do let(:source) { 'def x(); end' } it { is_expected.to be(false) } end context 'with a block' do let(:source) { 'x { || }' } it { is_expected.to be(false) } end context 'with a lambda literal' do let(:source) { '-> () { }' } it { is_expected.to be(false) } end end context 'with arguments' do context 'with a method definition' do let(:source) { 'def x a; end' } it { is_expected.to be(false) } end context 'with a lambda literal' do let(:source) { '-> a { }' } it { is_expected.to be(false) } end end end end rubocop-0.52.1/spec/rubocop/ast/array_node_spec.rb000066400000000000000000000050021322072016200221140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::ArrayNode do let(:array_node) { parse_source(source).ast } describe '.new' do let(:source) { '[]' } it { expect(array_node.is_a?(described_class)).to be(true) } end describe '#values' do context 'with an empty array' do let(:source) { '[]' } it { expect(array_node.values.empty?).to be(true) } end context 'with an array of literals' do let(:source) { '[1, 2, 3]' } it { expect(array_node.values.size).to eq(3) } it { expect(array_node.values).to all(be_literal) } end context 'with an array of variables' do let(:source) { '[foo, bar]' } it { expect(array_node.values.size).to eq(2) } it { expect(array_node.values).to all(be_send_type) } end end describe '#square_brackets?' do context 'with square brackets' do let(:source) { '[1, 2, 3]' } it { expect(array_node.square_brackets?).to be_truthy } end context 'with a percent literal' do let(:source) { '%w(foo bar)' } it { expect(array_node.square_brackets?).to be_falsey } end end describe '#percent_literal?' do context 'with square brackets' do let(:source) { '[1, 2, 3]' } it { expect(array_node.percent_literal?).to be_falsey } it { expect(array_node.percent_literal?(:string)).to be_falsey } it { expect(array_node.percent_literal?(:symbol)).to be_falsey } end context 'with a string percent literal' do let(:source) { '%w(foo bar)' } it { expect(array_node.percent_literal?).to be_truthy } it { expect(array_node.percent_literal?(:string)).to be_truthy } it { expect(array_node.percent_literal?(:symbol)).to be_falsey } end context 'with a symbol percent literal' do let(:source) { '%i(foo bar)' } it { expect(array_node.percent_literal?).to be_truthy } it { expect(array_node.percent_literal?(:string)).to be_falsey } it { expect(array_node.percent_literal?(:symbol)).to be_truthy } end end describe '#bracketed?' do context 'with square brackets' do let(:source) { '[1, 2, 3]' } it { expect(array_node.bracketed?).to be(true) } end context 'with a percent literal' do let(:source) { '%w(foo bar)' } it { expect(array_node.bracketed?).to be(true) } end context 'unbracketed' do let(:array_node) do parse_source('foo = 1, 2, 3').ast.to_a.last end it { expect(array_node.bracketed?).to be(nil) } end end end rubocop-0.52.1/spec/rubocop/ast/block_node_spec.rb000066400000000000000000000120731322072016200220760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::BlockNode do let(:block_node) { parse_source(source).ast } describe '.new' do let(:source) { 'foo { |q| bar(q) }' } it { expect(block_node.is_a?(described_class)).to be(true) } end describe '#arguments' do context 'with no arguments' do let(:source) { 'foo { bar }' } it { expect(block_node.arguments.empty?).to be(true) } end context 'with a single literal argument' do let(:source) { 'foo { |q| bar(q) }' } it { expect(block_node.arguments.size).to eq(1) } end context 'with a single splat argument' do let(:source) { 'foo { |*q| bar(q) }' } it { expect(block_node.arguments.size).to eq(1) } end context 'with multiple mixed arguments' do let(:source) { 'foo { |q, *z| bar(q, z) }' } it { expect(block_node.arguments.size).to eq(2) } end end describe '#arguments?' do context 'with no arguments' do let(:source) { 'foo { bar }' } it { expect(block_node.arguments?).to be_falsey } end context 'with a single argument' do let(:source) { 'foo { |q| bar(q) }' } it { expect(block_node.arguments?).to be_truthy } end context 'with a single splat argument' do let(:source) { 'foo { |*q| bar(q) }' } it { expect(block_node.arguments?).to be_truthy } end context 'with multiple mixed arguments' do let(:source) { 'foo { |q, *z| bar(q, z) }' } it { expect(block_node.arguments?).to be_truthy } end end describe '#braces?' do context 'when enclosed in braces' do let(:source) { 'foo { bar }' } it { expect(block_node.braces?).to be_truthy } end context 'when enclosed in do-end keywords' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.braces?).to be_falsey } end end describe '#keywords?' do context 'when enclosed in braces' do let(:source) { 'foo { bar }' } it { expect(block_node.keywords?).to be_falsey } end context 'when enclosed in do-end keywords' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.keywords?).to be_truthy } end end describe '#lambda?' do context 'when block belongs to a stabby lambda' do let(:source) { '-> { bar }' } it { expect(block_node.lambda?).to be_truthy } end context 'when block belongs to a method lambda' do let(:source) { 'lambda { bar }' } it { expect(block_node.lambda?).to be_truthy } end context 'when block belongs to a non-lambda method' do let(:source) { 'foo { bar }' } it { expect(block_node.lambda?).to be_falsey } end end describe '#delimiters' do context 'when enclosed in braces' do let(:source) { 'foo { bar }' } it { expect(block_node.delimiters).to eq(%w[{ }]) } end context 'when enclosed in do-end keywords' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.delimiters).to eq(%w[do end]) } end end describe '#opening_delimiter' do context 'when enclosed in braces' do let(:source) { 'foo { bar }' } it { expect(block_node.opening_delimiter).to eq('{') } end context 'when enclosed in do-end keywords' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.opening_delimiter).to eq('do') } end end describe '#closing_delimiter' do context 'when enclosed in braces' do let(:source) { 'foo { bar }' } it { expect(block_node.closing_delimiter).to eq('}') } end context 'when enclosed in do-end keywords' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.closing_delimiter).to eq('end') } end end describe '#single_line?' do context 'when block is on a single line' do let(:source) { 'foo { bar }' } it { expect(block_node.single_line?).to be_truthy } end context 'when block is on several lines' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.single_line?).to be_falsey } end end describe '#multiline?' do context 'when block is on a single line' do let(:source) { 'foo { bar }' } it { expect(block_node.multiline?).to be_falsey } end context 'when block is on several lines' do let(:source) do ['foo do', ' bar', 'end'].join("\n") end it { expect(block_node.multiline?).to be_truthy } end end describe '#void_context?' do context 'when block method is each' do let(:source) { 'each { bar }' } it { expect(block_node.void_context?).to be_truthy } end context 'when block method is not each' do let(:source) { 'map { bar }' } it { expect(block_node.void_context?).to be_falsey } end end end rubocop-0.52.1/spec/rubocop/ast/case_node_spec.rb000066400000000000000000000044561322072016200217250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::CaseNode do let(:case_node) { parse_source(source).ast } describe '.new' do let(:source) do ['case', 'when :foo then bar', 'end'].join("\n") end it { expect(case_node.is_a?(described_class)).to be(true) } end describe '#keyword' do let(:source) do ['case', 'when :foo then bar', 'end'].join("\n") end it { expect(case_node.keyword).to eq('case') } end describe '#when_branches' do let(:source) do ['case', 'when :foo then 1', 'when :bar then 2', 'when :baz then 3', 'end'].join("\n") end it { expect(case_node.when_branches.size).to eq(3) } it { expect(case_node.when_branches).to all(be_when_type) } end describe '#each_when' do let(:source) do ['case', 'when :foo then 1', 'when :bar then 2', 'when :baz then 3', 'end'].join("\n") end context 'when not passed a block' do it { expect(case_node.each_when.is_a?(Enumerator)).to be(true) } end context 'when passed a block' do it 'yields all the conditions' do expect { |b| case_node.each_when(&b) } .to yield_successive_args(*case_node.when_branches) end end end describe '#else?' do context 'without an else statement' do let(:source) do ['case', 'when :foo then :bar', 'end'].join("\n") end it { expect(case_node.else?).to be_falsey } end context 'with an else statement' do let(:source) do ['case', 'when :foo then :bar', 'else :baz', 'end'].join("\n") end it { expect(case_node.else?).to be_truthy } end end describe '#else_branch' do describe '#else?' do context 'without an else statement' do let(:source) do ['case', 'when :foo then :bar', 'end'].join("\n") end it { expect(case_node.else_branch.nil?).to be(true) } end context 'with an else statement' do let(:source) do ['case', 'when :foo then :bar', 'else :baz', 'end'].join("\n") end it { expect(case_node.else_branch.sym_type?).to be(true) } end end end end rubocop-0.52.1/spec/rubocop/ast/def_node_spec.rb000066400000000000000000000311051322072016200215370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::DefNode do let(:def_node) { parse_source(source).ast } describe '.new' do context 'with a def node' do let(:source) { 'def foo(bar); end' } it { expect(def_node.is_a?(described_class)).to be(true) } end context 'with a defs node' do let(:source) { 'def self.foo(bar); end' } it { expect(def_node.is_a?(described_class)).to be(true) } end end describe '#method_name' do context 'with a plain method' do let(:source) { 'def foo; end' } it { expect(def_node.method_name).to eq(:foo) } end context 'with a setter method' do let(:source) { 'def foo=(bar); end' } it { expect(def_node.method_name).to eq(:foo=) } end context 'with an operator method' do let(:source) { 'def ==(bar); end' } it { expect(def_node.method_name).to eq(:==) } end context 'with a unary method' do let(:source) { 'def -@; end' } it { expect(def_node.method_name).to eq(:-@) } end end describe '#method?' do context 'when message matches' do context 'when argument is a symbol' do let(:source) { 'bar(:baz)' } it { expect(def_node.method?(:bar)).to be_truthy } end context 'when argument is a string' do let(:source) { 'bar(:baz)' } it { expect(def_node.method?('bar')).to be_truthy } end end context 'when message does not match' do context 'when argument is a symbol' do let(:source) { 'bar(:baz)' } it { expect(def_node.method?(:foo)).to be_falsey } end context 'when argument is a string' do let(:source) { 'bar(:baz)' } it { expect(def_node.method?('foo')).to be_falsey } end end end describe '#arguments' do context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.arguments.empty?).to be(true) } end context 'with a single regular argument' do let(:source) { 'def foo(bar); end' } it { expect(def_node.arguments.size).to eq(1) } end context 'with a single rest argument' do let(:source) { 'def foo(*baz); end' } it { expect(def_node.arguments.size).to eq(1) } end context 'with multiple regular arguments' do let(:source) { 'def foo(bar, baz); end' } it { expect(def_node.arguments.size).to eq(2) } end context 'with multiple mixed arguments' do let(:source) { 'def foo(bar, *baz); end' } it { expect(def_node.arguments.size).to eq(2) } end end describe '#first_argument' do context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.first_argument.nil?).to be(true) } end context 'with a single regular argument' do let(:source) { 'def foo(bar); end' } it { expect(def_node.first_argument.arg_type?).to be(true) } end context 'with a single rest argument' do let(:source) { 'def foo(*bar); end' } it { expect(def_node.first_argument.restarg_type?).to be(true) } end context 'with a single keyword argument' do let(:source) { 'def foo(bar: :baz); end' } it { expect(def_node.first_argument.kwoptarg_type?).to be(true) } end context 'with multiple regular arguments' do let(:source) { 'def foo(bar, baz); end' } it { expect(def_node.first_argument.arg_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'def foo(bar, *baz); end' } it { expect(def_node.first_argument.arg_type?).to be(true) } end end describe '#last_argument' do context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.last_argument.nil?).to be(true) } end context 'with a single regular argument' do let(:source) { 'def foo(bar); end' } it { expect(def_node.last_argument.arg_type?).to be(true) } end context 'with a single rest argument' do let(:source) { 'def foo(*bar); end' } it { expect(def_node.last_argument.restarg_type?).to be(true) } end context 'with a single keyword argument' do let(:source) { 'def foo(bar: :baz); end' } it { expect(def_node.last_argument.kwoptarg_type?).to be(true) } end context 'with multiple regular arguments' do let(:source) { 'def foo(bar, baz); end' } it { expect(def_node.last_argument.arg_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'def foo(bar, *baz); end' } it { expect(def_node.last_argument.restarg_type?).to be(true) } end end describe '#arguments?' do context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.arguments?).to be_falsey } end context 'with a single regular argument' do let(:source) { 'def foo(bar); end' } it { expect(def_node.arguments?).to be_truthy } end context 'with a single rest argument' do let(:source) { 'def foo(*bar); end' } it { expect(def_node.arguments?).to be_truthy } end context 'with a single keyword argument' do let(:source) { 'def foo(bar: :baz); end' } it { expect(def_node.arguments?).to be_truthy } end context 'with multiple regular arguments' do let(:source) { 'def foo(bar, baz); end' } it { expect(def_node.arguments?).to be_truthy } end context 'with multiple mixed arguments' do let(:source) { 'def foo(bar, *baz); end' } it { expect(def_node.arguments?).to be_truthy } end end describe '#rest_argument?' do context 'with a rest argument' do let(:source) { 'def foo(*bar); end' } it { expect(def_node.rest_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.rest_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'def foo(bar); end' } it { expect(def_node.rest_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'def foo(bar, *baz); end' } it { expect(def_node.rest_argument?).to be_truthy } end end describe '#operator_method?' do context 'with a binary operator method' do let(:source) { 'def ==(bar); end' } it { expect(def_node.operator_method?).to be_truthy } end context 'with a unary operator method' do let(:source) { 'def -@; end' } it { expect(def_node.operator_method?).to be_truthy } end context 'with a setter method' do let(:source) { 'def foo=(bar); end' } it { expect(def_node.operator_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.operator_method?).to be_falsey } end end describe '#comparison_method?' do context 'with a comparison method' do let(:source) { 'def <=(bar); end' } it { expect(def_node.comparison_method?).to be_truthy } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.comparison_method?).to be_falsey } end end describe '#assignment_method?' do context 'with an assignment method' do let(:source) { 'def foo=(bar); end' } it { expect(def_node.assignment_method?).to be_truthy } end context 'with a bracket assignment method' do let(:source) { 'def []=(bar); end' } it { expect(def_node.assignment_method?).to be_truthy } end context 'with a comparison method' do let(:source) { 'def ==(bar); end' } it { expect(def_node.assignment_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.assignment_method?).to be_falsey } end end describe '#void_context?' do context 'with an initializer method' do let(:source) { 'def initialize(bar); end' } it { expect(def_node.void_context?).to be_truthy } end context 'with a regular assignment method' do let(:source) { 'def foo=(bar); end' } it { expect(def_node.void_context?).to be_truthy } end context 'with a bracket assignment method' do let(:source) { 'def []=(bar); end' } it { expect(def_node.void_context?).to be_truthy } end context 'with a comparison method' do let(:source) { 'def ==(bar); end' } it { expect(def_node.void_context?).to be_falsey } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.void_context?).to be_falsey } end end describe '#receiver' do context 'with an instance method definition' do let(:source) { 'def foo(bar); end' } it { expect(def_node.receiver.nil?).to be(true) } end context 'with a class method definition' do let(:source) { 'def self.foo(bar); end' } it { expect(def_node.receiver.self_type?).to be(true) } end context 'with a singleton method definition' do let(:source) { 'def Foo.bar(baz); end' } it { expect(def_node.receiver.const_type?).to be(true) } end end describe '#self_receiver?' do context 'with an instance method definition' do let(:source) { 'def foo(bar); end' } it { expect(def_node.self_receiver?).to be_falsey } end context 'with a class method definition' do let(:source) { 'def self.foo(bar); end' } it { expect(def_node.self_receiver?).to be_truthy } end context 'with a singleton method definition' do let(:source) { 'def Foo.bar(baz); end' } it { expect(def_node.self_receiver?).to be_falsey } end end describe '#const_receiver?' do context 'with an instance method definition' do let(:source) { 'def foo(bar); end' } it { expect(def_node.const_receiver?).to be_falsey } end context 'with a class method definition' do let(:source) { 'def self.foo(bar); end' } it { expect(def_node.const_receiver?).to be_falsey } end context 'with a singleton method definition' do let(:source) { 'def Foo.bar(baz); end' } it { expect(def_node.const_receiver?).to be_truthy } end end describe '#predicate_method?' do context 'with a predicate method' do let(:source) { 'def foo?(bar); end' } it { expect(def_node.predicate_method?).to be_truthy } end context 'with a bang method' do let(:source) { 'def foo!(bar); end' } it { expect(def_node.predicate_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.predicate_method?).to be_falsey } end end describe '#bang_method?' do context 'with a bang method' do let(:source) { 'def foo!(bar); end' } it { expect(def_node.bang_method?).to be_truthy } end context 'with a predicate method' do let(:source) { 'def foo?(bar); end' } it { expect(def_node.bang_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.bang_method?).to be_falsey } end end describe '#camel_case_method?' do context 'with a camel case method' do let(:source) { 'def Foo(bar); end' } it { expect(def_node.camel_case_method?).to be_truthy } end context 'with a regular method' do let(:source) { 'def foo(bar); end' } it { expect(def_node.camel_case_method?).to be_falsey } end end describe '#block_argument?' do context 'with a block argument' do let(:source) { 'def foo(&bar); end' } it { expect(def_node.block_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'def foo; end' } it { expect(def_node.block_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'def foo(bar); end' } it { expect(def_node.block_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'def foo(bar, &baz); end' } it { expect(def_node.block_argument?).to be_truthy } end end describe '#body' do context 'with no body' do let(:source) { 'def foo(bar); end' } it { expect(def_node.body.nil?).to be(true) } end context 'with a single expression body' do let(:source) { 'def foo(bar); baz; end' } it { expect(def_node.body.send_type?).to be(true) } end context 'with a multi-expression body' do let(:source) { 'def foo(bar); baz; qux; end' } it { expect(def_node.body.begin_type?).to be(true) } end end end rubocop-0.52.1/spec/rubocop/ast/ensure_node_spec.rb000066400000000000000000000007101322072016200223000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::EnsureNode do let(:ensure_node) { parse_source(source).ast.children.first } describe '.new' do let(:source) { 'begin; beginbody; ensure; ensurebody; end' } it { expect(ensure_node.is_a?(described_class)).to be(true) } end describe '#body' do let(:source) { 'begin; beginbody; ensure; :ensurebody; end' } it { expect(ensure_node.body.sym_type?).to be(true) } end end rubocop-0.52.1/spec/rubocop/ast/for_node_spec.rb000066400000000000000000000027071322072016200215750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::ForNode do let(:for_node) { parse_source(source).ast } describe '.new' do let(:source) { 'for foo in bar; baz; end' } it { expect(for_node.is_a?(described_class)).to be(true) } end describe '#keyword' do let(:source) { 'for foo in bar; baz; end' } it { expect(for_node.keyword).to eq('for') } end describe '#do?' do context 'with a do keyword' do let(:source) { 'for foo in bar do baz; end' } it { expect(for_node.do?).to be_truthy } end context 'without a do keyword' do let(:source) { 'for foo in bar; baz; end' } it { expect(for_node.do?).to be_falsey } end end describe '#void_context?' do context 'with a do keyword' do let(:source) { 'for foo in bar do baz; end' } it { expect(for_node.void_context?).to be_truthy } end context 'without a do keyword' do let(:source) { 'for foo in bar; baz; end' } it { expect(for_node.void_context?).to be_truthy } end end describe '#variable' do let(:source) { 'for foo in :bar; :baz; end' } it { expect(for_node.variable.lvasgn_type?).to be(true) } end describe '#collection' do let(:source) { 'for foo in :bar; baz; end' } it { expect(for_node.collection.sym_type?).to be(true) } end describe '#body' do let(:source) { 'for foo in bar; :baz; end' } it { expect(for_node.body.sym_type?).to be(true) } end end rubocop-0.52.1/spec/rubocop/ast/hash_node_spec.rb000066400000000000000000000133201322072016200217230ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::HashNode do let(:hash_node) { parse_source(source).ast } describe '.new' do let(:source) { '{}' } it { expect(hash_node.is_a?(described_class)).to be(true) } end describe '#pairs' do context 'with an empty hash' do let(:source) { '{}' } it { expect(hash_node.pairs.empty?).to be(true) } end context 'with a hash of literals' do let(:source) { '{ a: 1, b: 2, c: 3 }' } it { expect(hash_node.pairs.size).to eq(3) } it { expect(hash_node.pairs).to all(be_pair_type) } end context 'with a hash of variables' do let(:source) { '{ a: foo, b: bar }' } it { expect(hash_node.pairs.size).to eq(2) } it { expect(hash_node.pairs).to all(be_pair_type) } end end describe '#empty?' do context 'with an empty hash' do let(:source) { '{}' } it { expect(hash_node.empty?).to be(true) } end context 'with a hash containing pairs' do let(:source) { '{ a: 1, b: 2 }' } it { expect(hash_node.empty?).to be(false) } end context 'with a hash containing a keyword splat' do let(:source) { '{ **foo }' } it { expect(hash_node.empty?).to be(false) } end end describe '#keys' do context 'with an empty hash' do let(:source) { '{}' } it { expect(hash_node.keys.empty?).to be(true) } end context 'with a hash with symbol keys' do let(:source) { '{ a: 1, b: 2, c: 3 }' } it { expect(hash_node.keys.size).to eq(3) } it { expect(hash_node.keys).to all(be_sym_type) } end context 'with a hash with string keys' do let(:source) { "{ 'a' => foo,'b' => bar }" } it { expect(hash_node.keys.size).to eq(2) } it { expect(hash_node.keys).to all(be_str_type) } end end describe '#each_key' do let(:source) { '{ a: 1, b: 2, c: 3 }' } context 'when not passed a block' do it { expect(hash_node.each_key.is_a?(Enumerator)).to be(true) } end context 'when passed a block' do let(:expected) do [ hash_node.pairs[0].key, hash_node.pairs[1].key, hash_node.pairs[2].key ] end it 'yields all the pairs' do expect { |b| hash_node.each_key(&b) } .to yield_successive_args(*expected) end end end describe '#values' do context 'with an empty hash' do let(:source) { '{}' } it { expect(hash_node.values.empty?).to be(true) } end context 'with a hash with literal values' do let(:source) { '{ a: 1, b: 2, c: 3 }' } it { expect(hash_node.values.size).to eq(3) } it { expect(hash_node.values).to all(be_literal) } end context 'with a hash with string keys' do let(:source) { '{ a: foo, b: bar }' } it { expect(hash_node.values.size).to eq(2) } it { expect(hash_node.values).to all(be_send_type) } end end describe '#each_value' do let(:source) { '{ a: 1, b: 2, c: 3 }' } context 'when not passed a block' do it { expect(hash_node.each_value.is_a?(Enumerator)).to be(true) } end context 'when passed a block' do let(:expected) do [ hash_node.pairs[0].value, hash_node.pairs[1].value, hash_node.pairs[2].value ] end it 'yields all the pairs' do expect { |b| hash_node.each_value(&b) } .to yield_successive_args(*expected) end end end describe '#each_pair' do let(:source) { '{ a: 1, b: 2, c: 3 }' } context 'when not passed a block' do it { expect(hash_node.each_pair.is_a?(Enumerator)).to be(true) } end context 'when passed a block' do let(:expected) do [ [*hash_node.pairs[0]], [*hash_node.pairs[1]], [*hash_node.pairs[2]] ] end it 'yields all the pairs' do expect { |b| hash_node.each_pair(&b) } .to yield_successive_args(*expected) end end end describe '#pairs_on_same_line?' do context 'with all pairs on the same line' do let(:source) { '{ a: 1, b: 2 }' } it { expect(hash_node.pairs_on_same_line?).to be_truthy } end context 'with no pairs on the same line' do let(:source) do ['{ a: 1,', ' b: 2 }'].join("\n") end it { expect(hash_node.pairs_on_same_line?).to be_falsey } end context 'with some pairs on the same line' do let(:source) do ['{ a: 1,', ' b: 2, c: 3 }'].join("\n") end it { expect(hash_node.pairs_on_same_line?).to be_truthy } end end describe '#mixed_delimiters?' do context 'when all pairs are using a colon delimiter' do let(:source) { '{ a: 1, b: 2 }' } it { expect(hash_node.mixed_delimiters?).to be_falsey } end context 'when all pairs are using a hash rocket delimiter' do let(:source) { '{ :a => 1, :b => 2 }' } it { expect(hash_node.mixed_delimiters?).to be_falsey } end context 'when pairs are using different delimiters' do let(:source) { '{ :a => 1, b: 2 }' } it { expect(hash_node.mixed_delimiters?).to be_truthy } end end describe '#braces?' do context 'with braces' do let(:source) { '{ a: 1, b: 2 }' } it { expect(hash_node.braces?).to be_truthy } end context 'as an argument with no braces' do let(:source) { 'foo(:bar, a: 1, b: 2)' } let(:hash_argument) { hash_node.children.last } it { expect(hash_argument.braces?).to be_falsey } end context 'as an argument with braces' do let(:source) { 'foo(:bar, { a: 1, b: 2 })' } let(:hash_argument) { hash_node.children.last } it { expect(hash_argument.braces?).to be_truthy } end end end rubocop-0.52.1/spec/rubocop/ast/if_node_spec.rb000066400000000000000000000230071322072016200214010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::IfNode do let(:if_node) { parse_source(source).ast } describe '.new' do context 'with a regular if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.is_a?(described_class)).to be(true) } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.is_a?(described_class)).to be(true) } end context 'with a modifier statement' do let(:source) { ':foo if bar?' } it { expect(if_node.is_a?(described_class)).to be(true) } end end describe '#keyword' do context 'with an if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.keyword).to eq('if') } end context 'with an unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.keyword).to eq('unless') } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.keyword).to eq('') } end end describe '#inverse_keyword?' do context 'with an if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.inverse_keyword).to eq('unless') } end context 'with an unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.inverse_keyword).to eq('if') } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.inverse_keyword).to eq('') } end end describe '#if?' do context 'with an if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.if?).to be_truthy } end context 'with an unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.if?).to be_falsey } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.if?).to be_falsey } end end describe '#unless?' do context 'with an if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.unless?).to be_falsey } end context 'with an unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.unless?).to be_truthy } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.unless?).to be_falsey } end end describe '#ternary?' do context 'with an if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.ternary?).to be_falsey } end context 'with an unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.ternary?).to be_falsey } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.ternary?).to be_truthy } end end describe '#elsif?' do context 'with an elsif statement' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'end'].join("\n") end let(:elsif_node) { if_node.else_branch } it { expect(elsif_node.elsif?).to be_truthy } end context 'with an if statement comtaining an elsif' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'end'].join("\n") end it { expect(if_node.elsif?).to be_falsey } end context 'without an elsif statement' do let(:source) do ['if foo?', ' 1', 'end'].join("\n") end it { expect(if_node.elsif?).to be_falsey } end end describe '#else?' do context 'with an elsif statement' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'end'].join("\n") end # Note: This is a legacy behavior. it { expect(if_node.else?).to be_truthy } end context 'without an else statement' do let(:source) do ['if foo?', ' 1', 'else', ' 2', 'end'].join("\n") end it { expect(if_node.elsif?).to be_falsey } end end describe '#modifier_form?' do context 'with a non-modifier if statement' do let(:source) { 'if foo?; :bar; end' } it { expect(if_node.modifier_form?).to be_falsey } end context 'with a non-modifier unless statement' do let(:source) { 'unless foo?; :bar; end' } it { expect(if_node.modifier_form?).to be_falsey } end context 'with a ternary operator' do let(:source) { 'foo? ? :bar : :baz' } it { expect(if_node.modifier_form?).to be_falsey } end context 'with a modifier if statement' do let(:source) { ':bar if foo?' } it { expect(if_node.modifier_form?).to be_truthy } end context 'with a modifier unless statement' do let(:source) { ':bar unless foo?' } it { expect(if_node.modifier_form?).to be_truthy } end end describe '#nested_conditional?' do context 'with no nested conditionals' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'else', ' 3', 'end'].join("\n") end it { expect(if_node.nested_conditional?).to be_falsey } end context 'with nested conditionals in if clause' do let(:source) do ['if foo?', ' if baz; 4; end', 'elsif bar?', ' 2', 'else', ' 3', 'end'].join("\n") end it { expect(if_node.nested_conditional?).to be_truthy } end context 'with nested conditionals in elsif clause' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' if baz; 4; end', 'else', ' 3', 'end'].join("\n") end it { expect(if_node.nested_conditional?).to be_truthy } end context 'with nested conditionals in else clause' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'else', ' if baz; 4; end', 'end'].join("\n") end it { expect(if_node.nested_conditional?).to be_truthy } end context 'with nested ternary operators' do context 'when nested in the truthy branch' do let(:source) { 'foo? ? bar? ? 1 : 2 : 3' } it { expect(if_node.nested_conditional?).to be_truthy } end context 'when nested in the falsey branch' do let(:source) { 'foo? ? 3 : bar? ? 1 : 2' } it { expect(if_node.nested_conditional?).to be_truthy } end end end describe '#elsif_conditional?' do context 'with one elsif conditional' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'else', ' 3', 'end'].join("\n") end it { expect(if_node.elsif_conditional?).to be_truthy } end context 'with multiple elsif conditionals' do let(:source) do ['if foo?', ' 1', 'elsif bar?', ' 2', 'elsif baz?', ' 3', 'else', ' 4', 'end'].join("\n") end it { expect(if_node.elsif_conditional?).to be_truthy } end context 'with nested conditionals in if clause' do let(:source) do ['if foo?', ' if baz; 1; end', 'else', ' 2', 'end'].join("\n") end it { expect(if_node.elsif_conditional?).to be_falsey } end context 'with nested conditionals in else clause' do let(:source) do ['if foo?', ' 1', 'else', ' if baz; 2; end', 'end'].join("\n") end it { expect(if_node.elsif_conditional?).to be_falsey } end context 'with nested ternary operators' do context 'when nested in the truthy branch' do let(:source) { 'foo? ? bar? ? 1 : 2 : 3' } it { expect(if_node.elsif_conditional?).to be_falsey } end context 'when nested in the falsey branch' do let(:source) { 'foo? ? 3 : bar? ? 1 : 2' } it { expect(if_node.elsif_conditional?).to be_falsey } end end end describe '#if_branch' do context 'with an if statement' do let(:source) do ['if foo?', ' :foo', 'else', ' 42', 'end'].join("\n") end it { expect(if_node.if_branch.sym_type?).to be(true) } end context 'with an unless statement' do let(:source) do ['unless foo?', ' :foo', 'else', ' 42', 'end'].join("\n") end it { expect(if_node.if_branch.sym_type?).to be(true) } end context 'with a ternary operator' do let(:source) { 'foo? ? :foo : 42' } it { expect(if_node.if_branch.sym_type?).to be(true) } end end describe '#else_branch' do context 'with an if statement' do let(:source) do ['if foo?', ' :foo', 'else', ' 42', 'end'].join("\n") end it { expect(if_node.else_branch.int_type?).to be(true) } end context 'with an unless statement' do let(:source) do ['unless foo?', ' :foo', 'else', ' 42', 'end'].join("\n") end it { expect(if_node.else_branch.int_type?).to be(true) } end context 'with a ternary operator' do let(:source) { 'foo? ? :foo : 42' } it { expect(if_node.else_branch.int_type?).to be(true) } end end end rubocop-0.52.1/spec/rubocop/ast/keyword_splat_node_spec.rb000066400000000000000000000214741322072016200237000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::KeywordSplatNode do let(:kwsplat_node) { parse_source(source).ast.children.last } describe '.new' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.is_a?(described_class)).to be(true) } end describe '#hash_rocket?' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.hash_rocket?).to be_falsey } end describe '#colon?' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.colon?).to be_falsey } end describe '#key' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.key).to eq(kwsplat_node) } end describe '#value' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.value).to eq(kwsplat_node) } end describe '#operator' do let(:source) { '{ a: 1, **foo }' } it { expect(kwsplat_node.operator).to eq('**') } end describe '#same_line?' do let(:first_pair) { parse_source(source).ast.children[0] } let(:second_pair) { parse_source(source).ast.children[1] } context 'when both pairs are on the same line' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } end context 'when a multiline pair shares the same line' do let(:source) do ['{', ' a: (', ' ), **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } it { expect(second_pair.same_line?(first_pair)).to be_truthy } end context 'when pairs are on separate lines' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_falsey } end end describe '#key_delta' do let(:pair_node) { parse_source(source).ast.children[0] } let(:kwsplat_node) { parse_source(source).ast.children[1] } context 'with alignment set to :left' do context 'when using colon delimiters' do context 'when keyword splat is aligned' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(2) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(-2) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(0) } end end context 'when using hash rocket delimiters' do context 'when keyword splat is aligned' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(2) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(-2) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a => 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node)).to eq(0) } end end end context 'with alignment set to :right' do context 'when using colon delimiters' do context 'when keyword splat is aligned' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end end context 'when using hash rocket delimiters' do context 'when keyword splat is aligned' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a => 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.key_delta(pair_node, :right)).to eq(0) } end end end end describe '#value_delta' do let(:pair_node) { parse_source(source).ast.children[0] } let(:kwsplat_node) { parse_source(source).ast.children[1] } context 'when using colon delimiters' do context 'when keyword splat is left aligned' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end end context 'when using hash rocket delimiters' do context 'when keyword splat is left aligned' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is ahead' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is behind' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end context 'when keyword splat is on the same line' do let(:source) do ['{', ' a => 1, **foo', '}'].join("\n") end it { expect(kwsplat_node.value_delta(pair_node)).to eq(0) } end end end end rubocop-0.52.1/spec/rubocop/ast/node_spec.rb000066400000000000000000000233321322072016200207240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::Node do describe '#asgn_method_call?' do it 'does not match ==' do parsed = parse_source('Object.new == value') expect(parsed.ast.asgn_method_call?).to be(false) end it 'does not match !=' do parsed = parse_source('Object.new != value') expect(parsed.ast.asgn_method_call?).to be(false) end it 'does not match <=' do parsed = parse_source('Object.new <= value') expect(parsed.ast.asgn_method_call?).to be(false) end it 'does not match >=' do parsed = parse_source('Object.new >= value') expect(parsed.ast.asgn_method_call?).to be(false) end it 'does not match ===' do parsed = parse_source('Object.new === value') expect(parsed.ast.asgn_method_call?).to be(false) end it 'matches =' do parsed = parse_source('Object.new = value') expect(parsed.ast.asgn_method_call?).to be(true) end end describe '#value_used?' do let(:node) { RuboCop::ProcessedSource.new(src, ruby_version).ast } before do module RuboCop module AST class Node # Let's make our predicate matchers read better def used? value_used? end end end end end context 'at the top level' do let(:src) { 'expr' } it 'is false' do expect(node.used?).to be(false) end end context 'within a method call node' do let(:src) { 'obj.method(arg1, arg2, arg3)' } it 'is always true' do expect(node.child_nodes).to all(be_used) end end context 'at the end of a block' do let(:src) { 'obj.method { blah; expr }' } it 'is always true' do expect(node.children.last.used?).to be(true) end end context 'within a class definition node' do let(:src) { 'class C < Super; def a; 1; end; self; end' } it 'is always true' do expect(node.child_nodes).to all(be_used) end end context 'within a module definition node' do let(:src) { 'module M; def method; end; 1; end' } it 'is always true' do expect(node.child_nodes).to all(be_used) end end context 'within a singleton class node' do let(:src) { 'class << obj; 1; 2; end' } it 'is always true' do expect(node.child_nodes).to all(be_used) end end context 'within an if...else..end node' do context 'nested in a method call' do let(:src) { 'obj.method(if a then b else c end)' } it 'is always true' do if_node = node.children[2] expect(if_node.child_nodes).to all(be_used) end end context 'at the top level' do let(:src) { 'if a then b else c end' } it 'is true only for the condition' do condition, true_branch, false_branch = *node expect(condition.used?).to be(true) expect(true_branch.used?).to be(false) expect(false_branch.used?).to be(false) end end end context 'within an array literal' do context 'assigned to an ivar' do let(:src) { '@var = [a, b, c]' } it 'is always true' do ary_node = node.children[1] expect(ary_node.child_nodes).to all(be_used) end end context 'at the top level' do let(:src) { '[a, b, c]' } it 'is always false' do expect(node.child_nodes.map(&:used?)).to all(be false) end end end context 'within a while node' do let(:src) { 'while a; b; end' } it 'is true only for the condition' do condition, body = *node expect(condition.used?).to be(true) expect(body.used?).to be(false) end end end describe '#recursive_basic_literal?' do let(:node) { RuboCop::ProcessedSource.new(src, ruby_version).ast } shared_examples :literal do |source| let(:src) { source } it "returns true for `#{source}`" do expect(node.recursive_literal?).to be(true) end end it_behaves_like :literal, '!true' it_behaves_like :literal, '"#{2}"' it_behaves_like :literal, '(1)' it_behaves_like :literal, '(false && true)' it_behaves_like :literal, '(false <=> true)' it_behaves_like :literal, '(false or true)' it_behaves_like :literal, '[1, 2, 3]' it_behaves_like :literal, '{ :a => 1, :b => 2 }' it_behaves_like :literal, '{ a: 1, b: 2 }' it_behaves_like :literal, '/./' it_behaves_like :literal, '%r{abx}ixo' it_behaves_like :literal, '1.0' it_behaves_like :literal, '1' it_behaves_like :literal, 'false' it_behaves_like :literal, 'nil' it_behaves_like :literal, "'str'" shared_examples :non_literal do |source| let(:src) { source } it "returns false for `#{source}`" do expect(node.recursive_literal?).to be(false) end end it_behaves_like :non_literal, '(x && false)' it_behaves_like :non_literal, '(x == false)' it_behaves_like :non_literal, '(x or false)' it_behaves_like :non_literal, '[some_method_call]' it_behaves_like :non_literal, '{ :sym => some_method_call }' it_behaves_like :non_literal, '{ some_method_call => :sym }' it_behaves_like :non_literal, '/.#{some_method_call}/' it_behaves_like :non_literal, '%r{abx#{foo}}ixo' it_behaves_like :non_literal, 'some_method_call' it_behaves_like :non_literal, 'some_method_call(x, y)' end describe '#pure?' do let(:node) { RuboCop::ProcessedSource.new(src, ruby_version).ast } context 'for a method call' do let(:src) { 'obj.method(arg1, arg2)' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for an integer literal' do let(:src) { '100' } it 'returns true' do expect(node.pure?).to be(true) end end context 'for an array literal' do context 'with only literal children' do let(:src) { '[1..100, false, :symbol, "string", 1.0]' } it 'returns true' do expect(node.pure?).to be(true) end end context 'which contains a method call' do let(:src) { '[1, 2, 3, 3 + 4]' } it 'returns false' do expect(node.pure?).to be(false) end end end context 'for a hash literal' do context 'with only literal children' do let(:src) { '{range: 1..100, bool: false, str: "string", float: 1.0}' } it 'returns true' do expect(node.pure?).to be(true) end end context 'which contains a method call' do let(:src) { '{a: 1, b: 2, c: Kernel.exit}' } it 'returns false' do expect(node.pure?).to be(false) end end end context 'for a nested if' do context 'where the innermost descendants are local vars and literals' do let(:src) do ['lvar1, lvar2 = method1, method2', 'if $global', ' if @initialized', ' [lvar1, lvar2, true]', ' else', ' :symbol', ' end', 'else', ' lvar1', 'end'].join("\n") end it 'returns true' do if_node = node.children[1] expect(if_node.type).to be :if expect(if_node.pure?).to be(true) end end context 'where one branch contains a method call' do let(:src) { 'if $DEBUG then puts "hello" else nil end' } it 'returns false' do expect(node.pure?).to be(false) end end context 'where one branch contains an assignment statement' do let(:src) { 'if @a then 1 else $global = "str" end' } it 'returns false' do expect(node.pure?).to be(false) end end end context 'for an ivar assignment' do let(:src) { '@var = 1' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for a gvar assignment' do let(:src) { '$var = 1' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for a cvar assignment' do let(:src) { '@@var = 1' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for an lvar assignment' do let(:src) { 'var = 1' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for a class definition' do let(:src) { 'class C < Super; def method; end end' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for a module definition' do let(:src) { 'module M; def method; end end' } it 'returns false' do expect(node.pure?).to be(false) end end context 'for a regexp' do let(:opts) { '' } let(:body) { '' } let(:src) { "/#{body}/#{opts}" } context 'with interpolated segments' do let(:body) { '#{x}' } it 'returns false' do expect(node.pure?).to be(false) end end context 'with no interpolation' do let(:src) { URI::DEFAULT_PARSER.make_regexp.inspect } it 'returns true' do expect(node.pure?).to be(true) end end context 'with options' do let(:opts) { 'oix' } it 'returns true' do expect(node.pure?).to be(true) end end end end describe '#sibling_index' do let(:node) { RuboCop::ProcessedSource.new(src, ruby_version).ast } let(:src) do [ 'def foo; end', 'def bar; end', 'def baz; end' ].join("\n") end it 'returns its sibling index' do (0..2).each do |n| expect(node.children[n].sibling_index).to eq(n) end end end end rubocop-0.52.1/spec/rubocop/ast/or_node_spec.rb000066400000000000000000000056721322072016200214330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::OrNode do let(:or_node) { parse_source(source).ast } describe '.new' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.is_a?(described_class)).to be(true) } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.is_a?(described_class)).to be(true) } end end describe '#logical_operator?' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.logical_operator?).to be(true) } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.logical_operator?).to be(false) } end end describe '#semantic_operator?' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.semantic_operator?).to be(false) } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.semantic_operator?).to be(true) } end end describe '#operator' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.operator).to eq('||') } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.operator).to eq('or') } end end describe '#alternate_operator' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.alternate_operator).to eq('or') } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.alternate_operator).to eq('||') } end end describe '#inverse_operator' do context 'with a logical or node' do let(:source) do ':foo || :bar' end it { expect(or_node.inverse_operator).to eq('&&') } end context 'with a semantic or node' do let(:source) do ':foo or :bar' end it { expect(or_node.inverse_operator).to eq('and') } end end describe '#lhs' do context 'with a logical or node' do let(:source) do ':foo || 42' end it { expect(or_node.lhs.sym_type?).to be(true) } end context 'with a semantic or node' do let(:source) do ':foo or 42' end it { expect(or_node.lhs.sym_type?).to be(true) } end end describe '#rhs' do context 'with a logical or node' do let(:source) do ':foo || 42' end it { expect(or_node.rhs.int_type?).to be(true) } end context 'with a semantic or node' do let(:source) do ':foo or 42' end it { expect(or_node.rhs.int_type?).to be(true) } end end end rubocop-0.52.1/spec/rubocop/ast/pair_node_spec.rb000066400000000000000000000440311322072016200217360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::PairNode do let(:pair_node) { parse_source(source).ast.children.first } describe '.new' do let(:source) { '{ a: 1 }' } it { expect(pair_node.is_a?(described_class)).to be(true) } end describe '#hash_rocket?' do context 'when using a hash rocket delimiter' do let(:source) { '{ a => 1 }' } it { expect(pair_node.hash_rocket?).to be_truthy } end context 'when using a colon delimiter' do let(:source) { '{ a: 1 }' } it { expect(pair_node.hash_rocket?).to be_falsey } end end describe '#colon?' do context 'when using a hash rocket delimiter' do let(:source) { '{ a => 1 }' } it { expect(pair_node.colon?).to be_falsey } end context 'when using a colon delimiter' do let(:source) { '{ a: 1 }' } it { expect(pair_node.colon?).to be_truthy } end end describe '#colon?' do context 'when using a hash rocket delimiter' do let(:source) { '{ a => 1 }' } it { expect(pair_node.colon?).to be_falsey } end context 'when using a colon delimiter' do let(:source) { '{ a: 1 }' } it { expect(pair_node.colon?).to be_truthy } end end describe '#delimiter' do context 'when using a hash rocket delimiter' do let(:source) { '{ a => 1 }' } it { expect(pair_node.delimiter).to eq('=>') } it { expect(pair_node.delimiter(true)).to eq(' => ') } end context 'when using a colon delimiter' do let(:source) { '{ a: 1 }' } it { expect(pair_node.delimiter).to eq(':') } it { expect(pair_node.delimiter(true)).to eq(': ') } end end describe '#inverse_delimiter' do context 'when using a hash rocket delimiter' do let(:source) { '{ a => 1 }' } it { expect(pair_node.inverse_delimiter).to eq(':') } it { expect(pair_node.inverse_delimiter(true)).to eq(': ') } end context 'when using a colon delimiter' do let(:source) { '{ a: 1 }' } it { expect(pair_node.inverse_delimiter).to eq('=>') } it { expect(pair_node.inverse_delimiter(true)).to eq(' => ') } end end describe '#key' do context 'when using a symbol key' do let(:source) { '{ a: 1 }' } it { expect(pair_node.key.sym_type?).to be(true) } end context 'when using a string key' do let(:source) { "{ 'a' => 1 }" } it { expect(pair_node.key.str_type?).to be(true) } end end describe '#value' do let(:source) { '{ a: 1 }' } it { expect(pair_node.value.int_type?).to be(true) } end describe '#same_line?' do let(:first_pair) { parse_source(source).ast.children[0] } let(:second_pair) { parse_source(source).ast.children[1] } context 'when both pairs are on the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1, b: 2', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } end context 'when both pair is a keyword splat' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } end end context 'when a multiline pair shares the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: (', ' ), b: 2', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } it { expect(second_pair.same_line?(first_pair)).to be_truthy } end context 'when last pair is a keyword splat' do let(:source) do ['{', ' a: (', ' ), **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_truthy } it { expect(second_pair.same_line?(first_pair)).to be_truthy } end end context 'when pairs are on separate lines' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_falsey } end context 'when last pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.same_line?(second_pair)).to be_falsey } end end end describe '#key_delta' do let(:first_pair) { parse_source(source).ast.children[0] } let(:second_pair) { parse_source(source).ast.children[1] } context 'with alignment set to :left' do context 'when using colon delimiters' do context 'when keys are aligned' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end end context 'when receiver key is behind' do context 'when both pairs are reail pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(-2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(-2) } end end context 'when receiver key is ahead' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(2) } end end context 'when both keys are on the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1, b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end end end context 'when using hash rocket delimiters' do context 'when keys are aligned' do context 'when both keys are explicit keys' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end context 'when second key is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end end context 'when receiver key is behind' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(-2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(-2) } end end context 'when receiver key is ahead' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(2) } end end context 'when both keys are on the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1, b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1, **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair)).to eq(0) } end end end end context 'with alignment set to :right' do context 'when using colon delimiters' do context 'when keys are aligned' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when receiver key is behind' do context 'when both pairs are reail pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(-2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when receiver key is ahead' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when both keys are on the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1, b: 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1, **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end end context 'when using hash rocket delimiters' do context 'when keys are aligned' do context 'when both keys are explicit keys' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end context 'when second key is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when receiver key is behind' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(-2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when receiver key is ahead' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(2) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end context 'when both keys are on the same line' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1, b => 2', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1, **foo', '}'].join("\n") end it { expect(first_pair.key_delta(second_pair, :right)).to eq(0) } end end end end end describe '#value_delta' do let(:first_pair) { parse_source(source).ast.children[0] } let(:second_pair) { parse_source(source).ast.children[1] } context 'when using colon delimiters' do context 'when values are aligned' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a: 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end end context 'when receiver value is behind' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(-2) } end context 'when receiver value is ahead' do let(:source) do ['{', ' a: 1,', ' b: 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(2) } end context 'when both pairs are on the same line' do let(:source) do ['{', ' a: 1, b: 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end end context 'when using hash rocket delimiters' do context 'when values are aligned' do context 'when both pairs are explicit pairs' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end context 'when second pair is a keyword splat' do let(:source) do ['{', ' a => 1,', ' **foo', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end end context 'when receiver value is behind' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(-2) } end context 'when receiver value is ahead' do let(:source) do ['{', ' a => 1,', ' b => 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(2) } end context 'when both pairs are on the same line' do let(:source) do ['{', ' a => 1, b => 2', '}'].join("\n") end it { expect(first_pair.value_delta(second_pair)).to eq(0) } end end end end rubocop-0.52.1/spec/rubocop/ast/regexp_node_spec.rb000066400000000000000000000044631322072016200223020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::RegexpNode do let(:regexp_node) { parse_source(source).ast } describe '.new' do let(:source) { '/re/' } it { expect(regexp_node.is_a?(described_class)).to be(true) } end describe '#to_regexp' do # rubocop:disable Security/Eval context 'with an empty regexp' do let(:source) { '//' } it { expect(regexp_node.to_regexp).to eq(eval(source)) } end context 'with a regexp without option' do let(:source) { '/.+/' } it { expect(regexp_node.to_regexp).to eq(eval(source)) } end context 'with an empty regexp with option' do let(:source) { '//ix' } it { expect(regexp_node.to_regexp).to eq(eval(source)) } end context 'with a regexp with option' do let(:source) { '/.+/imx' } it { expect(regexp_node.to_regexp).to eq(eval(source)) } end # rubocop:enable Security/Eval end describe '#regopt' do let(:regopt) { regexp_node.regopt } context 'with an empty regexp' do let(:source) { '//' } it { expect(regopt.regopt_type?).to be(true) } it { expect(regopt.children.empty?).to be(true) } end context 'with a regexp without option' do let(:source) { '/.+/' } it { expect(regopt.regopt_type?).to be(true) } it { expect(regopt.children.empty?).to be(true) } end context 'with an empty regexp with option' do let(:source) { '//ix' } it { expect(regopt.regopt_type?).to be(true) } it { expect(regopt.children).to eq(%i[i x]) } end context 'with a regexp with option' do let(:source) { '/.+/imx' } it { expect(regopt.regopt_type?).to be(true) } it { expect(regopt.children).to eq(%i[i m x]) } end end describe '#content' do let(:content) { regexp_node.content } context 'with an empty regexp' do let(:source) { '//' } it { expect(content).to eq('') } end context 'with a regexp without option' do let(:source) { '/.+/' } it { expect(content).to eq('.+') } end context 'with an empty regexp with option' do let(:source) { '//ix' } it { expect(content).to eq('') } end context 'with a regexp with option' do let(:source) { '/.+/imx' } it { expect(content).to eq('.+') } end end end rubocop-0.52.1/spec/rubocop/ast/resbody_node_spec.rb000066400000000000000000000010321322072016200224440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::ResbodyNode do let(:resbody_node) do begin_node = parse_source(source).ast rescue_node, = *begin_node rescue_node.children[1] end describe '.new' do let(:source) { 'begin; beginbody; rescue; rescuebody; end' } it { expect(resbody_node.is_a?(described_class)).to be(true) } end describe '#body' do let(:source) { 'begin; beginbody; rescue Error => ex; :rescuebody; end' } it { expect(resbody_node.body.sym_type?).to be(true) } end end rubocop-0.52.1/spec/rubocop/ast/send_node_spec.rb000066400000000000000000000546411322072016200217440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::SendNode do let(:send_node) { parse_source(source).ast } describe '.new' do context 'with a regular method send' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.is_a?(described_class)).to be(true) } end context 'with a safe navigation method send' do let(:ruby_version) { 2.3 } let(:source) { 'foo&.bar(:baz)' } it { expect(send_node.is_a?(described_class)).to be(true) } end end describe '#receiver' do context 'with no receiver' do let(:source) { 'bar(:baz)' } it { expect(send_node.receiver.nil?).to be(true) } end context 'with a literal receiver' do let(:source) { "'foo'.bar(:baz)" } it { expect(send_node.receiver.str_type?).to be(true) } end context 'with a variable receiver' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.receiver.send_type?).to be(true) } end end describe '#method_name' do context 'with a plain method' do let(:source) { 'bar(:baz)' } it { expect(send_node.method_name).to eq(:bar) } end context 'with a setter method' do let(:source) { 'foo.bar = :baz' } it { expect(send_node.method_name).to eq(:bar=) } end context 'with an operator method' do let(:source) { 'foo == bar' } it { expect(send_node.method_name).to eq(:==) } end context 'with an implicit call method' do let(:source) { 'foo.(:baz)' } it { expect(send_node.method_name).to eq(:call) } end end describe '#method?' do context 'when message matches' do context 'when argument is a symbol' do let(:source) { 'bar(:baz)' } it { expect(send_node.method?(:bar)).to be_truthy } end context 'when argument is a string' do let(:source) { 'bar(:baz)' } it { expect(send_node.method?('bar')).to be_truthy } end end context 'when message does not match' do context 'when argument is a symbol' do let(:source) { 'bar(:baz)' } it { expect(send_node.method?(:foo)).to be_falsey } end context 'when argument is a string' do let(:source) { 'bar(:baz)' } it { expect(send_node.method?('foo')).to be_falsey } end end end describe '#access_modifier?' do let(:send_node) { parse_source(source).ast.children[1] } context 'when node is a bare `module_function`' do let(:source) do ['module Foo', ' module_function', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_truthy } end context 'when node is a bare `private`' do let(:source) do ['module Foo', ' private', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_truthy } end context 'when node is a bare `protected`' do let(:source) do ['module Foo', ' protected', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_truthy } end context 'when node is a bare `public`' do let(:source) do ['module Foo', ' public', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_truthy } end context 'when node has an argument' do let(:source) do ['module Foo', ' private :foo', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_falsey } end context 'when node is not an access modifier' do let(:source) do ['module Foo', ' some_command', 'end'].join("\n") end it { expect(send_node.access_modifier?).to be_falsey } end end describe '#macro?' do context 'without a receiver' do context 'when parent is a class' do let(:send_node) { parse_source(source).ast.children[2].children[0] } let(:source) do ['class Foo', ' bar :baz', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a module' do let(:send_node) { parse_source(source).ast.children[1].children[0] } let(:source) do ['module Foo', ' bar :baz', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a class constructor' do let(:send_node) { parse_source(source).ast.children[2].children[0] } let(:source) do ['Module.new do', ' bar :baz', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a singleton class' do let(:send_node) { parse_source(source).ast.children[1].children[0] } let(:source) do ['class << self', ' bar :baz', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a block' do let(:send_node) { parse_source(source).ast.children[2].children[0] } let(:source) do ['concern :Auth do', ' bar :baz', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a keyword begin inside of an class' do let(:send_node) { parse_source(source).ast.children[2].children[0] } let(:source) do ['class Foo', ' begin', ' bar :qux', ' end', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'without a parent' do let(:source) { 'bar :baz' } it { expect(send_node.macro?).to be_truthy } end context 'when parent is a begin without a parent' do let(:send_node) { parse_source(source).ast.children[0] } let(:source) do ['begin', ' bar :qux', 'end'].join("\n") end it { expect(send_node.macro?).to be_truthy } end context 'when parent is a method definition' do let(:send_node) { parse_source(source).ast.children[2] } let(:source) do ['def foo', ' bar :baz', 'end'].join("\n") end it { expect(send_node.macro?).to be_falsey } end end context 'with a receiver' do context 'when parent is a class' do let(:send_node) { parse_source(source).ast.children[2] } let(:source) do ['class Foo', ' qux.bar :baz', 'end'].join("\n") end it { expect(send_node.macro?).to be_falsey } end context 'when parent is a module' do let(:send_node) { parse_source(source).ast.children[1] } let(:source) do ['module Foo', ' qux.bar :baz', 'end'].join("\n") end it { expect(send_node.macro?).to be_falsey } end end end describe '#command?' do context 'when argument is a symbol' do context 'with an explicit receiver' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.command?(:bar)).to be_falsey } end context 'with an implicit receiver' do let(:source) { 'bar(:baz)' } it { expect(send_node.command?(:bar)).to be_truthy } end end context 'when argument is a string' do context 'with an explicit receiver' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.command?('bar')).to be_falsey } end context 'with an implicit receiver' do let(:source) { 'bar(:baz)' } it { expect(send_node.command?('bar')).to be_truthy } end end end describe '#arguments' do context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.arguments.empty?).to be(true) } end context 'with a single literal argument' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.arguments.size).to eq(1) } end context 'with a single splat argument' do let(:source) { 'foo.bar(*baz)' } it { expect(send_node.arguments.size).to eq(1) } end context 'with multiple literal arguments' do let(:source) { 'foo.bar(:baz, :qux)' } it { expect(send_node.arguments.size).to eq(2) } end context 'with multiple mixed arguments' do let(:source) { 'foo.bar(:baz, *qux)' } it { expect(send_node.arguments.size).to eq(2) } end end describe '#first_argument' do context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.first_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.first_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'foo.bar(*baz)' } it { expect(send_node.first_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'foo.bar(:baz, :qux)' } it { expect(send_node.first_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'foo.bar(:baz, *qux)' } it { expect(send_node.first_argument.sym_type?).to be(true) } end end describe '#last_argument' do context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.last_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.last_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'foo.bar(*baz)' } it { expect(send_node.last_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'foo.bar(:baz, :qux)' } it { expect(send_node.last_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'foo.bar(:baz, *qux)' } it { expect(send_node.last_argument.splat_type?).to be(true) } end end describe '#arguments?' do context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.arguments?).to be_falsey } end context 'with a single literal argument' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.arguments?).to be_truthy } end context 'with a single splat argument' do let(:source) { 'foo.bar(*baz)' } it { expect(send_node.arguments?).to be_truthy } end context 'with multiple literal arguments' do let(:source) { 'foo.bar(:baz, :qux)' } it { expect(send_node.arguments?).to be_truthy } end context 'with multiple mixed arguments' do let(:source) { 'foo.bar(:baz, *qux)' } it { expect(send_node.arguments?).to be_truthy } end end describe '#parenthesized?' do context 'with no arguments' do context 'when not using parentheses' do let(:source) { 'foo.bar' } it { expect(send_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'foo.bar()' } it { expect(send_node.parenthesized?).to be_truthy } end end context 'with arguments' do context 'when not using parentheses' do let(:source) { 'foo.bar :baz' } it { expect(send_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.parenthesized?).to be_truthy } end end end describe '#setter_method?' do context 'with a setter method' do let(:source) { 'foo.bar = :baz' } it { expect(send_node.setter_method?).to be_truthy } end context 'with an indexed setter method' do let(:source) { 'foo.bar[:baz] = :qux' } it { expect(send_node.setter_method?).to be_truthy } end context 'with an operator method' do let(:source) { 'foo.bar + 1' } it { expect(send_node.setter_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.setter_method?).to be_falsey } end end describe '#operator_method?' do context 'with a binary operator method' do let(:source) { 'foo.bar + :baz' } it { expect(send_node.operator_method?).to be_truthy } end context 'with a unary operator method' do let(:source) { '!foo.bar' } it { expect(send_node.operator_method?).to be_truthy } end context 'with a setter method' do let(:source) { 'foo.bar = :baz' } it { expect(send_node.operator_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.operator_method?).to be_falsey } end end describe '#comparison_method?' do context 'with a comparison method' do let(:source) { 'foo.bar >= :baz' } it { expect(send_node.comparison_method?).to be_truthy } end context 'with a regular method' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.comparison_method?).to be_falsey } end context 'with a negation method' do let(:source) { '!foo' } it { expect(send_node.comparison_method?).to be_falsey } end end describe '#assignment_method?' do context 'with an assignment method' do let(:source) { 'foo.bar = :baz' } it { expect(send_node.assignment_method?).to be_truthy } end context 'with a bracket assignment method' do let(:source) { 'foo.bar[:baz] = :qux' } it { expect(send_node.assignment_method?).to be_truthy } end context 'with a comparison method' do let(:source) { 'foo.bar == :qux' } it { expect(send_node.assignment_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.assignment_method?).to be_falsey } end end describe '#dot?' do context 'with a dot' do let(:source) { 'foo.+ 1' } it { expect(send_node.dot?).to be_truthy } end context 'without a dot' do let(:source) { 'foo + 1' } it { expect(send_node.dot?).to be_falsey } end context 'with a double colon' do let(:source) { 'Foo::bar' } it { expect(send_node.dot?).to be_falsey } end context 'with a unary method' do let(:source) { '!foo.bar' } it { expect(send_node.dot?).to be_falsey } end end describe '#double_colon?' do context 'with a double colon' do let(:source) { 'Foo::bar' } it { expect(send_node.double_colon?).to be_truthy } end context 'with a dot' do let(:source) { 'foo.+ 1' } it { expect(send_node.double_colon?).to be_falsey } end context 'without a dot' do let(:source) { 'foo + 1' } it { expect(send_node.double_colon?).to be_falsey } end context 'with a unary method' do let(:source) { '!foo.bar' } it { expect(send_node.double_colon?).to be_falsey } end end describe '#self_receiver?' do context 'with a self receiver' do let(:source) { 'self.bar' } it { expect(send_node.self_receiver?).to be_truthy } end context 'with a non-self receiver' do let(:source) { 'foo.bar' } it { expect(send_node.self_receiver?).to be_falsey } end context 'with an implicit receiver' do let(:source) { 'bar' } it { expect(send_node.self_receiver?).to be_falsey } end end describe '#const_receiver?' do context 'with a self receiver' do let(:source) { 'self.bar' } it { expect(send_node.const_receiver?).to be_falsey } end context 'with a non-constant receiver' do let(:source) { 'foo.bar' } it { expect(send_node.const_receiver?).to be_falsey } end context 'with a constant receiver' do let(:source) { 'Foo.bar' } it { expect(send_node.const_receiver?).to be_truthy } end end describe '#implicit_call?' do context 'with an implicit call method' do let(:source) { 'foo.(:bar)' } it { expect(send_node.implicit_call?).to be_truthy } end context 'with an explicit call method' do let(:source) { 'foo.call(:bar)' } it { expect(send_node.implicit_call?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar' } it { expect(send_node.implicit_call?).to be_falsey } end end describe '#predicate_method?' do context 'with a predicate method' do let(:source) { 'foo.bar?' } it { expect(send_node.predicate_method?).to be_truthy } end context 'with a bang method' do let(:source) { 'foo.bar!' } it { expect(send_node.predicate_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar' } it { expect(send_node.predicate_method?).to be_falsey } end end describe '#bang_method?' do context 'with a bang method' do let(:source) { 'foo.bar!' } it { expect(send_node.bang_method?).to be_truthy } end context 'with a predicate method' do let(:source) { 'foo.bar?' } it { expect(send_node.bang_method?).to be_falsey } end context 'with a regular method' do let(:source) { 'foo.bar' } it { expect(send_node.bang_method?).to be_falsey } end end describe '#camel_case_method?' do context 'with a camel case method' do let(:source) { 'Integer(1.0)' } it { expect(send_node.camel_case_method?).to be_truthy } end context 'with a regular method' do let(:source) { 'integer(1.0)' } it { expect(send_node.camel_case_method?).to be_falsey } end end describe '#block_argument?' do context 'with a block argument' do let(:source) { 'foo.bar(&baz)' } it { expect(send_node.block_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.block_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.block_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'foo.bar(:baz, &qux)' } it { expect(send_node.block_argument?).to be_truthy } end end describe '#block_literal?' do context 'with a block literal' do let(:send_node) { parse_source(source).ast.children[0] } let(:source) { 'foo.bar { |q| baz(q) }' } it { expect(send_node.block_literal?).to be_truthy } end context 'with a block argument' do let(:source) { 'foo.bar(&baz)' } it { expect(send_node.block_literal?).to be_falsey } end context 'with no block' do let(:source) { 'foo.bar' } it { expect(send_node.block_literal?).to be_falsey } end end describe '#block_node' do context 'with a block literal' do let(:send_node) { parse_source(source).ast.children[0] } let(:source) { 'foo.bar { |q| baz(q) }' } it { expect(send_node.block_node.block_type?).to be(true) } end context 'with a block argument' do let(:source) { 'foo.bar(&baz)' } it { expect(send_node.block_node.nil?).to be(true) } end context 'with no block' do let(:source) { 'foo.bar' } it { expect(send_node.block_node.nil?).to be(true) } end end describe '#splat_argument?' do context 'with a splat argument' do let(:source) { 'foo.bar(*baz)' } it { expect(send_node.splat_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'foo.bar' } it { expect(send_node.splat_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'foo.bar(:baz)' } it { expect(send_node.splat_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'foo.bar(:baz, *qux)' } it { expect(send_node.splat_argument?).to be_truthy } end end describe '#def_modifier?' do context 'with a prefixed def modifier' do let(:source) { 'foo def bar; end' } it { expect(send_node.def_modifier?).to be_truthy } end context 'with several prefixed def modifiers' do let(:source) { 'foo bar def baz; end' } it { expect(send_node.def_modifier?).to be_truthy } end end describe '#negation_method?' do context 'with keyword `not`' do let(:source) { 'not foo' } it { expect(send_node.negation_method?).to be_truthy } end context 'with a bang method' do let(:source) { '!foo' } it { expect(send_node.negation_method?).to be_truthy } end context 'with a non-negated method' do let(:source) { 'foo.bar' } it { expect(send_node.negation_method?).to be_falsey } end end describe '#lambda?' do context 'with a lambda method' do let(:source) { 'lambda { |foo| bar(foo) }' } let(:send_node) { parse_source(source).ast.send_node } it { expect(send_node.lambda?).to be_truthy } end context 'with a stabby lambda method' do let(:source) { '-> (foo) { do_something(foo) }' } let(:send_node) { parse_source(source).ast.send_node } it { expect(send_node.lambda?).to be_truthy } end context 'with a non-lambda method' do let(:source) { 'foo.bar' } it { expect(send_node.lambda?).to be_falsey } end end describe '#stabby_lambda?' do context 'with a stabby lambda' do let(:send_node) { parse_source(source).ast.send_node } let(:source) { '-> (foo) { do_something(foo) }' } it { expect(send_node.stabby_lambda?).to be(true) } end context 'with a lambda method' do let(:send_node) { parse_source(source).ast.send_node } let(:source) { 'lambda { |foo| bar(foo) }' } it { expect(send_node.stabby_lambda?).to be(false) } end context 'with a non-lambda method' do let(:source) { 'foo.bar' } it { expect(send_node.lambda?).to be_falsey } end # Regression test https://github.com/bbatsov/rubocop/pull/5194 context 'with `a.() {}` style method' do let(:send_node) { parse_source(source).ast.send_node } let(:source) { 'a.() {}' } it { expect(send_node.lambda?).to be_falsey } end end end rubocop-0.52.1/spec/rubocop/ast/str_node_spec.rb000066400000000000000000000023261322072016200216140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::StrNode do let(:str_node) { parse_source(source).ast } describe '.new' do context 'with a normal string' do let(:source) { "'foo'" } it { expect(str_node.is_a?(described_class)).to be(true) } end context 'with a string with interpolation' do let(:source) { '"#{foo}"' } it { expect(str_node.is_a?(described_class)).to be(true) } end context 'with a heredoc' do let(:source) do <<-RUBY.strip_indent <<-CODE foo bar CODE RUBY end it { expect(str_node.is_a?(described_class)).to be(true) } end end describe '#heredoc?' do context 'with a normal string' do let(:source) { "'foo'" } it { expect(str_node.heredoc?).to be(false) } end context 'with a string with interpolation' do let(:source) { '"#{foo}"' } it { expect(str_node.heredoc?).to be(false) } end context 'with a heredoc' do let(:source) do <<-RUBY.strip_indent <<-CODE foo bar CODE RUBY end it { expect(str_node.heredoc?).to be(true) } end end end rubocop-0.52.1/spec/rubocop/ast/super_node_spec.rb000066400000000000000000000233371322072016200221470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::SuperNode do let(:super_node) { parse_source(source).ast } describe '.new' do context 'with a super node' do let(:source) { 'super(:baz)' } it { expect(super_node.is_a?(described_class)).to be(true) } end context 'with a zsuper node' do let(:source) { 'super' } it { expect(super_node.is_a?(described_class)).to be(true) } end end describe '#receiver' do let(:source) { 'super(foo)' } it { expect(super_node.receiver.nil?).to be(true) } end describe '#method_name' do let(:source) { 'super(foo)' } it { expect(super_node.method_name).to eq(:super) } end describe '#method?' do context 'when message matches' do context 'when argument is a symbol' do let(:source) { 'super(:baz)' } it { expect(super_node.method?(:super)).to be_truthy } end context 'when argument is a string' do let(:source) { 'super(:baz)' } it { expect(super_node.method?('super')).to be_truthy } end end context 'when message does not match' do context 'when argument is a symbol' do let(:source) { 'super(:baz)' } it { expect(super_node.method?(:foo)).to be_falsey } end context 'when argument is a string' do let(:source) { 'super(:baz)' } it { expect(super_node.method?('foo')).to be_falsey } end end end describe '#macro?' do let(:super_node) { parse_source(source).ast.children[2] } let(:source) do ['def initialize', ' super(foo)', 'end'].join("\n") end it { expect(super_node.macro?).to be_falsey } end describe '#command?' do context 'when argument is a symbol' do let(:source) { 'super(foo)' } it { expect(super_node.command?(:super)).to be_truthy } end context 'when argument is a string' do let(:source) { 'super(foo)' } it { expect(super_node.command?('super')).to be_truthy } end end describe '#setter_method?' do let(:source) { 'super(foo)' } it { expect(super_node.setter_method?).to be_falsey } end describe '#operator_method?' do let(:source) { 'super(foo)' } it { expect(super_node.operator_method?).to be_falsey } end describe '#comparison_method?' do let(:source) { 'super(foo)' } it { expect(super_node.comparison_method?).to be_falsey } end describe '#assignment_method?' do let(:source) { 'super(foo)' } it { expect(super_node.assignment_method?).to be_falsey } end describe '#dot?' do let(:source) { 'super(foo)' } it { expect(super_node.dot?).to be_falsey } end describe '#double_colon?' do let(:source) { 'super(foo)' } it { expect(super_node.double_colon?).to be_falsey } end describe '#self_receiver?' do let(:source) { 'super(foo)' } it { expect(super_node.self_receiver?).to be_falsey } end describe '#const_receiver?' do let(:source) { 'super(foo)' } it { expect(super_node.const_receiver?).to be_falsey } end describe '#implicit_call?' do let(:source) { 'super(foo)' } it { expect(super_node.implicit_call?).to be_falsey } end describe '#predicate_method?' do let(:source) { 'super(foo)' } it { expect(super_node.predicate_method?).to be_falsey } end describe '#bang_method?' do let(:source) { 'super(foo)' } it { expect(super_node.bang_method?).to be_falsey } end describe '#camel_case_method?' do let(:source) { 'super(foo)' } it { expect(super_node.camel_case_method?).to be_falsey } end describe '#parenthesized?' do context 'with no arguments' do context 'when not using parentheses' do let(:source) { 'super' } it { expect(super_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'foo.bar()' } it { expect(super_node.parenthesized?).to be_truthy } end end context 'with arguments' do context 'when not using parentheses' do let(:source) { 'foo.bar :baz' } it { expect(super_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'foo.bar(:baz)' } it { expect(super_node.parenthesized?).to be_truthy } end end end describe '#block_argument?' do context 'with a block argument' do let(:source) { 'super(&baz)' } it { expect(super_node.block_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.block_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'super(:baz)' } it { expect(super_node.block_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'super(:baz, &qux)' } it { expect(super_node.block_argument?).to be_truthy } end end describe '#block_literal?' do context 'with a block literal' do let(:super_node) { parse_source(source).ast.children[0] } let(:source) { 'super { |q| baz(q) }' } it { expect(super_node.block_literal?).to be_truthy } end context 'with a block argument' do let(:source) { 'super(&baz)' } it { expect(super_node.block_literal?).to be_falsey } end context 'with no block' do let(:source) { 'super' } it { expect(super_node.block_literal?).to be_falsey } end end describe '#block_node' do context 'with a block literal' do let(:super_node) { parse_source(source).ast.children[0] } let(:source) { 'super { |q| baz(q) }' } it { expect(super_node.block_node.block_type?).to be(true) } end context 'with a block argument' do let(:source) { 'super(&baz)' } it { expect(super_node.block_node.nil?).to be(true) } end context 'with no block' do let(:source) { 'super' } it { expect(super_node.block_node.nil?).to be(true) } end end describe '#arguments' do context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.arguments.empty?).to be(true) } end context 'with a single literal argument' do let(:source) { 'super(:baz)' } it { expect(super_node.arguments.size).to eq(1) } end context 'with a single splat argument' do let(:source) { 'super(*baz)' } it { expect(super_node.arguments.size).to eq(1) } end context 'with multiple literal arguments' do let(:source) { 'super(:baz, :qux)' } it { expect(super_node.arguments.size).to eq(2) } end context 'with multiple mixed arguments' do let(:source) { 'super(:baz, *qux)' } it { expect(super_node.arguments.size).to eq(2) } end end describe '#first_argument' do context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.first_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'super(:baz)' } it { expect(super_node.first_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'super(*baz)' } it { expect(super_node.first_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'super(:baz, :qux)' } it { expect(super_node.first_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'superr(:baz, *qux)' } it { expect(super_node.first_argument.sym_type?).to be(true) } end end describe '#last_argument' do context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.last_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'super(:baz)' } it { expect(super_node.last_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'super(*baz)' } it { expect(super_node.last_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'super(:baz, :qux)' } it { expect(super_node.last_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'super(:baz, *qux)' } it { expect(super_node.last_argument.splat_type?).to be(true) } end end describe '#arguments?' do context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.arguments?).to be_falsey } end context 'with a single literal argument' do let(:source) { 'super(:baz)' } it { expect(super_node.arguments?).to be_truthy } end context 'with a single splat argument' do let(:source) { 'super(*baz)' } it { expect(super_node.arguments?).to be_truthy } end context 'with multiple literal arguments' do let(:source) { 'super(:baz, :qux)' } it { expect(super_node.arguments?).to be_truthy } end context 'with multiple mixed arguments' do let(:source) { 'super(:baz, *qux)' } it { expect(super_node.arguments?).to be_truthy } end end describe '#splat_argument?' do context 'with a splat argument' do let(:source) { 'super(*baz)' } it { expect(super_node.splat_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'super' } it { expect(super_node.splat_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'super(:baz)' } it { expect(super_node.splat_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'super(:baz, *qux)' } it { expect(super_node.splat_argument?).to be_truthy } end end end rubocop-0.52.1/spec/rubocop/ast/symbol_node_spec.rb000066400000000000000000000006531322072016200223120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::SymbolNode do let(:sym_node) { parse_source(source).ast } describe '.new' do context 'with a symbol node' do let(:source) do ':foo' end it { expect(sym_node.is_a?(described_class)).to be(true) } end end describe '#value' do let(:source) do ':foo' end it { expect(sym_node.value).to eq(:foo) } end end rubocop-0.52.1/spec/rubocop/ast/until_node_spec.rb000066400000000000000000000020511322072016200221320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::UntilNode do let(:until_node) { parse_source(source).ast } describe '.new' do context 'with a statement until' do let(:source) { 'until foo; bar; end' } it { expect(until_node.is_a?(described_class)).to be(true) } end context 'with a modifier until' do let(:source) { 'begin foo; end until bar' } it { expect(until_node.is_a?(described_class)).to be(true) } end end describe '#keyword' do let(:source) { 'until foo; bar; end' } it { expect(until_node.keyword).to eq('until') } end describe '#inverse_keyword' do let(:source) { 'until foo; bar; end' } it { expect(until_node.inverse_keyword).to eq('while') } end describe '#do?' do context 'with a do keyword' do let(:source) { 'until foo do; bar; end' } it { expect(until_node.do?).to be_truthy } end context 'without a do keyword' do let(:source) { 'until foo; bar; end' } it { expect(until_node.do?).to be_falsey } end end end rubocop-0.52.1/spec/rubocop/ast/when_node_spec.rb000066400000000000000000000052521322072016200217460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::WhenNode do let(:when_node) { parse_source(source).ast.children[1] } describe '.new' do let(:source) do ['case', 'when :foo then bar', 'end'].join("\n") end it { expect(when_node.is_a?(described_class)).to be(true) } end describe '#conditions' do context 'with a single condition' do let(:source) do ['case', 'when :foo then bar', 'end'].join("\n") end it { expect(when_node.conditions.size).to eq(1) } it { expect(when_node.conditions).to all(be_literal) } end context 'with a multiple conditions' do let(:source) do ['case', 'when :foo, :bar, :baz then bar', 'end'].join("\n") end it { expect(when_node.conditions.size).to eq(3) } it { expect(when_node.conditions).to all(be_literal) } end end describe '#each_condition' do let(:source) do ['case', 'when :foo, :bar, :baz then bar', 'end'].join("\n") end context 'when not passed a block' do it { expect(when_node.each_condition.is_a?(Enumerator)).to be(true) } end context 'when passed a block' do it 'yields all the conditions' do expect { |b| when_node.each_condition(&b) } .to yield_successive_args(*when_node.conditions) end end end describe '#then?' do context 'with a then keyword' do let(:source) do ['case', 'when :foo then bar', 'end'].join("\n") end it { expect(when_node.then?).to be_truthy } end context 'without a then keyword' do let(:source) do ['case', 'when :foo', ' bar', 'end'].join("\n") end it { expect(when_node.then?).to be_falsey } end end describe '#body' do context 'with a then keyword' do let(:source) do ['case', 'when :foo then :bar', 'end'].join("\n") end it { expect(when_node.body.sym_type?).to be(true) } end context 'without a then keyword' do let(:source) do ['case', 'when :foo', ' [:bar, :baz]', 'end'].join("\n") end it { expect(when_node.body.array_type?).to be(true) } end end describe '#branch_index' do let(:source) do ['case', 'when :foo then 1', 'when :bar then 2', 'when :baz then 3', 'end'].join("\n") end let(:whens) { parse_source(source).ast.children[1...-1] } it { expect(whens[0].branch_index).to eq(0) } it { expect(whens[1].branch_index).to eq(1) } it { expect(whens[2].branch_index).to eq(2) } end end rubocop-0.52.1/spec/rubocop/ast/while_node_spec.rb000066400000000000000000000020511322072016200221070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::WhileNode do let(:while_node) { parse_source(source).ast } describe '.new' do context 'with a statement while' do let(:source) { 'while foo; bar; end' } it { expect(while_node.is_a?(described_class)).to be(true) } end context 'with a modifier while' do let(:source) { 'begin foo; end while bar' } it { expect(while_node.is_a?(described_class)).to be(true) } end end describe '#keyword' do let(:source) { 'while foo; bar; end' } it { expect(while_node.keyword).to eq('while') } end describe '#inverse_keyword' do let(:source) { 'while foo; bar; end' } it { expect(while_node.inverse_keyword).to eq('until') } end describe '#do?' do context 'with a do keyword' do let(:source) { 'while foo do; bar; end' } it { expect(while_node.do?).to be_truthy } end context 'without a do keyword' do let(:source) { 'while foo; bar; end' } it { expect(while_node.do?).to be_falsey } end end end rubocop-0.52.1/spec/rubocop/ast/yield_node_spec.rb000066400000000000000000000203761322072016200221170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::AST::YieldNode do let(:yield_node) { parse_source(source).ast } describe '.new' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.is_a?(described_class)).to be(true) } end describe '#receiver' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.receiver.nil?).to be(true) } end describe '#method_name' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.method_name).to eq(:yield) } end describe '#method?' do context 'when message matches' do context 'when argument is a symbol' do let(:source) { 'yield :foo' } it { expect(yield_node.method?(:yield)).to be_truthy } end context 'when argument is a string' do let(:source) { 'yield :foo' } it { expect(yield_node.method?('yield')).to be_truthy } end end context 'when message does not match' do context 'when argument is a symbol' do let(:source) { 'yield :bar' } it { expect(yield_node.method?(:foo)).to be_falsey } end context 'when argument is a string' do let(:source) { 'yield :bar' } it { expect(yield_node.method?('foo')).to be_falsey } end end end describe '#macro?' do let(:yield_node) { parse_source(source).ast.children[2] } let(:source) do ['def give_me_bar', ' yield :bar', 'end'].join("\n") end it { expect(yield_node.macro?).to be_falsey } end describe '#command?' do context 'when argument is a symbol' do let(:source) { 'yield :bar' } it { expect(yield_node.command?(:yield)).to be_truthy } end context 'when argument is a string' do let(:source) { 'yield :bar' } it { expect(yield_node.command?('yield')).to be_truthy } end end describe '#arguments' do context 'with no arguments' do let(:source) { 'yield' } it { expect(yield_node.arguments.empty?).to be(true) } end context 'with a single literal argument' do let(:source) { 'yield :foo' } it { expect(yield_node.arguments.size).to eq(1) } end context 'with a single splat argument' do let(:source) { 'yield *foo' } it { expect(yield_node.arguments.size).to eq(1) } end context 'with multiple literal arguments' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.arguments.size).to eq(2) } end context 'with multiple mixed arguments' do let(:source) { 'yield :foo, *bar' } it { expect(yield_node.arguments.size).to eq(2) } end end describe '#first_argument' do context 'with no arguments' do let(:source) { 'yield' } it { expect(yield_node.first_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'yield :foo' } it { expect(yield_node.first_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'yield *foo' } it { expect(yield_node.first_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.first_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'yield :foo, *bar' } it { expect(yield_node.first_argument.sym_type?).to be(true) } end end describe '#last_argument' do context 'with no arguments' do let(:source) { 'yield' } it { expect(yield_node.last_argument.nil?).to be(true) } end context 'with a single literal argument' do let(:source) { 'yield :foo' } it { expect(yield_node.last_argument.sym_type?).to be(true) } end context 'with a single splat argument' do let(:source) { 'yield *foo' } it { expect(yield_node.last_argument.splat_type?).to be(true) } end context 'with multiple literal arguments' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.last_argument.sym_type?).to be(true) } end context 'with multiple mixed arguments' do let(:source) { 'yield :foo, *bar' } it { expect(yield_node.last_argument.splat_type?).to be(true) } end end describe '#arguments?' do context 'with no arguments' do let(:source) { 'yield' } it { expect(yield_node.arguments?).to be_falsey } end context 'with a single literal argument' do let(:source) { 'yield :foo' } it { expect(yield_node.arguments?).to be_truthy } end context 'with a single splat argument' do let(:source) { 'yield *foo' } it { expect(yield_node.arguments?).to be_truthy } end context 'with multiple literal arguments' do let(:source) { 'yield :foo, :bar' } it { expect(yield_node.arguments?).to be_truthy } end context 'with multiple mixed arguments' do let(:source) { 'yield :foo, *bar' } it { expect(yield_node.arguments?).to be_truthy } end end describe '#parenthesized?' do context 'with no arguments' do context 'when not using parentheses' do let(:source) { 'yield' } it { expect(yield_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'yield()' } it { expect(yield_node.parenthesized?).to be_truthy } end end context 'with arguments' do context 'when not using parentheses' do let(:source) { 'yield :foo' } it { expect(yield_node.parenthesized?).to be_falsey } end context 'when using parentheses' do let(:source) { 'yield(:foo)' } it { expect(yield_node.parenthesized?).to be_truthy } end end end describe '#setter_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.setter_method?).to be_falsey } end describe '#operator_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.operator_method?).to be_falsey } end describe '#comparison_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.comparison_method?).to be_falsey } end describe '#assignment_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.assignment_method?).to be_falsey } end describe '#dot?' do let(:source) { 'yield :foo' } it { expect(yield_node.dot?).to be_falsey } end describe '#double_colon?' do let(:source) { 'yield :foo' } it { expect(yield_node.double_colon?).to be_falsey } end describe '#self_receiver?' do let(:source) { 'yield :foo' } it { expect(yield_node.self_receiver?).to be_falsey } end describe '#const_receiver?' do let(:source) { 'yield :foo' } it { expect(yield_node.const_receiver?).to be_falsey } end describe '#implicit_call?' do let(:source) { 'yield :foo' } it { expect(yield_node.implicit_call?).to be_falsey } end describe '#predicate_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.predicate_method?).to be_falsey } end describe '#bang_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.bang_method?).to be_falsey } end describe '#camel_case_method?' do let(:source) { 'yield :foo' } it { expect(yield_node.camel_case_method?).to be_falsey } end describe '#block_argument?' do let(:source) { 'yield :foo' } it { expect(yield_node.block_argument?).to be_falsey } end describe '#block_literal?' do let(:source) { 'yield :foo' } it { expect(yield_node.block_literal?).to be_falsey } end describe '#block_node' do let(:source) { 'yield :foo' } it { expect(yield_node.block_node.nil?).to be(true) } end describe '#splat_argument?' do context 'with a splat argument' do let(:source) { 'yield *foo' } it { expect(yield_node.splat_argument?).to be_truthy } end context 'with no arguments' do let(:source) { 'yield' } it { expect(yield_node.splat_argument?).to be_falsey } end context 'with regular arguments' do let(:source) { 'yield :foo' } it { expect(yield_node.splat_argument?).to be_falsey } end context 'with mixed arguments' do let(:source) { 'yield :foo, *bar' } it { expect(yield_node.splat_argument?).to be_truthy } end end end rubocop-0.52.1/spec/rubocop/cli/000077500000000000000000000000001322072016200164155ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cli/cli_auto_gen_config_spec.rb000066400000000000000000000650441322072016200237420ustar00rootroot00000000000000# frozen_string_literal: true require 'timeout' RSpec.describe RuboCop::CLI, :isolated_environment do include_context 'cli spec behavior' subject(:cli) { described_class.new } describe '--auto-gen-config' do before do RuboCop::Formatter::DisabledConfigFormatter .config_to_allow_offenses = {} end shared_examples 'LineLength handling' do |ctx, initial_dotfile, exp_dotfile| context ctx do # Since there is a line with length 99 in the inspected code, # Style/IfUnlessModifier will register an offense when # Metrics/LineLength:Max has been set to 99. With a lower # LineLength:Max there would be no IfUnlessModifier offense. it "bases other cops' configuration on the code base's current " \ 'maximum line length' do if initial_dotfile initial_config = YAML.safe_load(initial_dotfile.join($RS)) || {} inherited_files = Array(initial_config['inherit_from']) (inherited_files - ['.rubocop.yml']).each { |f| create_file(f, '') } create_file('.rubocop.yml', initial_dotfile) create_file('.rubocop_todo.yml', ['']) end create_file('example.rb', <<-RUBY.strip_indent) def f #{' #' * 33} if #{'a' * 80} return y end z end RUBY expect(cli.run(['--auto-gen-config'])).to eq(1) expect(IO.readlines('.rubocop_todo.yml') .drop_while { |line| line.start_with?('#') }.join) .to eq(<<-YAML.strip_indent) # Offense count: 1 # Cop supports --auto-correct. Style/IfUnlessModifier: Exclude: - 'example.rb' # Offense count: 2 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 99 YAML expect(IO.read('.rubocop.yml').strip).to eq(exp_dotfile.join($RS)) $stdout = StringIO.new expect(described_class.new.run([])).to eq(0) expect($stderr.string).to eq('') expect($stdout.string).to include('no offenses detected') end end end include_examples 'LineLength handling', 'when .rubocop.yml does not exist', nil, ['inherit_from: .rubocop_todo.yml'] include_examples 'LineLength handling', 'when .rubocop.yml is empty', [''], ['inherit_from: .rubocop_todo.yml'] include_examples 'LineLength handling', 'when .rubocop.yml inherits only from .rubocop_todo.yml', ['inherit_from: .rubocop_todo.yml'], ['inherit_from: .rubocop_todo.yml'] include_examples 'LineLength handling', 'when .rubocop.yml inherits only from .rubocop_todo.yml ' \ 'in an array', ['inherit_from:', ' - .rubocop_todo.yml'], ['inherit_from:', ' - .rubocop_todo.yml'] include_examples 'LineLength handling', 'when .rubocop.yml inherits from another file and ' \ '.rubocop_todo.yml', ['inherit_from:', ' - common.yml', ' - .rubocop_todo.yml'], ['inherit_from:', ' - common.yml', ' - .rubocop_todo.yml'] include_examples 'LineLength handling', 'when .rubocop.yml inherits from two other files', ['inherit_from:', ' - common1.yml', ' - common2.yml'], ['inherit_from:', ' - .rubocop_todo.yml', ' - common1.yml', ' - common2.yml'] include_examples 'LineLength handling', 'when .rubocop.yml inherits from another file', ['inherit_from: common.yml'], ['inherit_from:', ' - .rubocop_todo.yml', ' - common.yml'] include_examples 'LineLength handling', "when .rubocop.yml doesn't inherit", ['Style/For:', ' Enabled: false'], ['inherit_from: .rubocop_todo.yml', '', 'Style/For:', ' Enabled: false'] context 'with Metrics/LineLength:Max overridden' do before do create_file('.rubocop.yml', ['Metrics/LineLength:', " Max: #{line_length_max}"]) create_file('.rubocop_todo.yml', ['']) create_file('example.rb', <<-RUBY.strip_indent) def f #{' #' * 33} if #{'a' * 80} return y end z end RUBY end context 'when .rubocop.yml has Metrics/LineLength:Max less than code ' \ 'base max' do let(:line_length_max) { 90 } it "bases other cops' configuration on the overridden LineLength:Max" do expect(cli.run(['--auto-gen-config'])).to eq(1) expect($stdout.string).to include(<<-YAML.strip_indent) Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`. Phase 1 of 2: run Metrics/LineLength cop (skipped because the default Metrics/LineLength:Max is overridden) Phase 2 of 2: run all cops YAML # We generate a Metrics/LineLength:Max even though it's overridden in # .rubocop.yml. We want to show somewhere what the actual maximum is. # # Note that there is no Style/IfUnlessModifier offense registered due # to the Max:90 setting. expect(IO.readlines('.rubocop_todo.yml') .drop_while { |line| line.start_with?('#') }.join) .to eq(<<-YAML.strip_indent) # Offense count: 1 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Metrics/LineLength: Max: 99 YAML expect(IO.read('.rubocop.yml')).to eq(<<-YAML.strip_indent) inherit_from: .rubocop_todo.yml Metrics/LineLength: Max: 90 YAML $stdout = StringIO.new expect(described_class.new.run(%w[--format simple])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-OUTPUT.strip_indent) == example.rb == C: 2: 91: Metrics/LineLength: Line is too long. [99/90] 1 file inspected, 1 offense detected OUTPUT end end context 'when .rubocop.yml has Metrics/LineLength:Max more than code ' \ 'base max' do let(:line_length_max) { 150 } it "bases other cops' configuration on the overridden LineLength:Max" do expect(cli.run(['--auto-gen-config'])).to eq(1) expect($stdout.string).to include(<<-YAML.strip_indent) Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`. Phase 1 of 2: run Metrics/LineLength cop (skipped because the default Metrics/LineLength:Max is overridden) Phase 2 of 2: run all cops YAML # The code base max line length is 99, but the setting Max:150 # overrides that so no Metrics/LineLength:Max setting is generated in # .rubocop_todo.yml. expect(IO.readlines('.rubocop_todo.yml') .drop_while { |line| line.start_with?('#') }.join) .to eq(<<-YAML.strip_indent) # Offense count: 1 # Cop supports --auto-correct. Style/IfUnlessModifier: Exclude: - 'example.rb' YAML expect(IO.read('.rubocop.yml')).to eq(<<-YAML.strip_indent) inherit_from: .rubocop_todo.yml Metrics/LineLength: Max: 150 YAML $stdout = StringIO.new expect(described_class.new.run(%w[--format simple])).to eq(0) expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, no offenses detected OUTPUT end end end it 'overwrites an existing todo file' do create_file('example1.rb', ['x= 0 ', '#' * 85, 'y ', 'puts x']) create_file('.rubocop_todo.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: false YAML create_file('.rubocop.yml', ['inherit_from: .rubocop_todo.yml']) expect(cli.run(['--auto-gen-config'])).to eq(1) expect(IO.readlines('.rubocop_todo.yml')[8..-1].map(&:chomp)) .to eq(['# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: AllowForAlignment.', 'Layout/SpaceAroundOperators:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 2', '# Cop supports --auto-correct.', 'Layout/TrailingWhitespace:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 1', '# Configuration parameters: AllowHeredoc, AllowURI, ' \ 'URISchemes, IgnoreCopDirectives, IgnoredPatterns.', '# URISchemes: http, https', 'Metrics/LineLength:', ' Max: 85']) # Create new CLI instance to avoid using cached configuration. new_cli = described_class.new expect(new_cli.run(['example1.rb'])).to eq(0) end it 'honors rubocop:disable comments' do create_file('example1.rb', ['#' * 81, '# rubocop:disable LineLength', '#' * 85, 'y ', 'puts 123456', '# rubocop:enable LineLength']) create_file('.rubocop.yml', ['inherit_from: .rubocop_todo.yml']) create_file('.rubocop_todo.yml', ['']) expect(cli.run(['--auto-gen-config'])).to eq(1) expect(IO.readlines('.rubocop_todo.yml')[8..-1].join) .to eq(['# Offense count: 1', '# Cop supports --auto-correct.', 'Layout/TrailingWhitespace:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: Strict.', 'Style/NumericLiterals:', ' MinDigits: 7', '', '# Offense count: 1', '# Configuration parameters: AllowHeredoc, AllowURI, ' \ 'URISchemes, IgnoreCopDirectives, IgnoredPatterns.', '# URISchemes: http, https', 'Metrics/LineLength:', ' Max: 81', ''].join("\n")) end it 'can generate a todo list' do create_file('example1.rb', ['$x= 0 ', '#' * 90, '#' * 85, 'y ', 'puts x']) create_file('example2.rb', <<-RUBY.strip_indent) # frozen_string_literal: true \tx = 0 puts x class A def a; end end RUBY # Make ConfigLoader reload the default configuration so that its # absolute Exclude paths will point into this example's work directory. RuboCop::ConfigLoader.default_configuration = nil expect(cli.run(['--auto-gen-config'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to include('Created .rubocop_todo.yml.') expected = ['# This configuration was generated by', '# `rubocop --auto-gen-config`', /# on .* using RuboCop version .*/, '# 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', '# Cop supports --auto-correct.', 'Layout/CommentIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 2', '# Cop supports --auto-correct.', '# Configuration parameters: EnforcedStyle.', '# SupportedStyles: normal, rails', 'Layout/IndentationConsistency:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: AllowForAlignment.', 'Layout/SpaceAroundOperators:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth.', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 2', '# Cop supports --auto-correct.', 'Layout/TrailingWhitespace:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 1', 'Style/Documentation:', ' Exclude:', " - 'spec/**/*'", # Copied from default configuration " - 'test/**/*'", # Copied from default configuration " - 'example2.rb'", '', '# Offense count: 1', '# Configuration parameters: AllowedVariables.', 'Style/GlobalVars:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 2', '# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, ' \ 'IgnoreCopDirectives, IgnoredPatterns.', '# URISchemes: http, https', 'Metrics/LineLength:', ' Max: 90'] actual = IO.read('.rubocop_todo.yml').split($RS) expected.each_with_index do |line, ix| if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end end expect(actual.size).to eq(expected.size) end it 'can generate Exclude properties with a given limit' do create_file('example1.rb', ['$x= 0 ', '#' * 90, '#' * 85, 'y ', 'puts x']) create_file('example2.rb', ['# frozen_string_literal: true', '', '#' * 85, "\tx = 0", 'puts x ']) expect(cli.run(['--auto-gen-config', '--exclude-limit', '1'])).to eq(1) expected = ['# This configuration was generated by', '# `rubocop --auto-gen-config --exclude-limit 1`', /# on .* using RuboCop version .*/, '# 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', '# Cop supports --auto-correct.', 'Layout/CommentIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: EnforcedStyle.', '# SupportedStyles: normal, rails', 'Layout/IndentationConsistency:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: AllowForAlignment.', 'Layout/SpaceAroundOperators:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth.', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 3', '# Cop supports --auto-correct.', 'Layout/TrailingWhitespace:', ' Enabled: false', # Offenses in 2 files, limit is 1, so no Exclude '', '# Offense count: 1', '# Configuration parameters: AllowedVariables.', 'Style/GlobalVars:', ' Exclude:', " - 'example1.rb'", '', '# Offense count: 3', '# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, ' \ 'IgnoreCopDirectives, IgnoredPatterns.', '# URISchemes: http, https', 'Metrics/LineLength:', ' Max: 90'] actual = IO.read('.rubocop_todo.yml').split($RS) expected.each_with_index do |line, ix| if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end end expect(actual.size).to eq(expected.size) end it 'does not generate configuration for the Syntax cop' do create_file('example1.rb', <<-RUBY.strip_indent) # frozen_string_literal: true x = < # Syntax error puts x RUBY create_file('example2.rb', <<-RUBY.strip_indent) # frozen_string_literal: true \tx = 0 puts x RUBY expect(cli.run(['--auto-gen-config'])).to eq(1) expect($stderr.string).to eq('') expected = ['# This configuration was generated by', '# `rubocop --auto-gen-config`', /# on .* using RuboCop version .*/, '# 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', '# Cop supports --auto-correct.', 'Layout/CommentIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: EnforcedStyle.', '# SupportedStyles: normal, rails', 'Layout/IndentationConsistency:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Offense count: 1', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth.', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'"] actual = IO.read('.rubocop_todo.yml').split($RS) expect(actual.length).to eq(expected.length) expected.each_with_index do |line, ix| if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end end expect(actual.size).to eq(expected.size) end it 'generates a todo list that removes the reports' do create_file('example.rb', 'y.gsub!(/abc\/xyz/, x)') expect(cli.run(%w[--format emacs])).to eq(1) expect($stdout.string).to eq( "#{abs('example.rb')}:1:9: C: Style/RegexpLiteral: Use `%r` " \ "around regular expression.\n" ) expect(cli.run(['--auto-gen-config'])).to eq(1) expected = ['# This configuration was generated by', '# `rubocop --auto-gen-config`', /# on .* using RuboCop version .*/, '# 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', '# Cop supports --auto-correct.', '# Configuration parameters: EnforcedStyle, AllowInnerSlashes.', '# SupportedStyles: slashes, percent_r, mixed', 'Style/RegexpLiteral:', ' Exclude:', " - 'example.rb'"] actual = IO.read('.rubocop_todo.yml').split($RS) expected.each_with_index do |line, ix| if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end end expect(actual.size).to eq(expected.size) $stdout = StringIO.new result = cli.run(%w[--config .rubocop_todo.yml --format emacs]) expect($stdout.string).to eq('') expect(result).to eq(0) end it 'does not include offense counts when --no-offense-counts is used' do create_file('example1.rb', ['$x= 0 ', '#' * 90, '#' * 85, 'y ', 'puts x']) create_file('example2.rb', <<-RUBY.strip_indent) # frozen_string_literal: true \tx = 0 puts x class A def a; end end RUBY # Make ConfigLoader reload the default configuration so that its # absolute Exclude paths will point into this example's work directory. RuboCop::ConfigLoader.default_configuration = nil expect(cli.run(['--auto-gen-config', '--no-offense-counts'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to include('Created .rubocop_todo.yml.') expected = ['# This configuration was generated by', '# `rubocop --auto-gen-config --no-offense-counts`', /# on .* using RuboCop version .*/, '# 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.', '', '# Cop supports --auto-correct.', 'Layout/CommentIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Cop supports --auto-correct.', '# Configuration parameters: EnforcedStyle.', '# SupportedStyles: normal, rails', 'Layout/IndentationConsistency:', ' Exclude:', " - 'example2.rb'", '', '# Cop supports --auto-correct.', 'Layout/InitialIndentation:', ' Exclude:', " - 'example2.rb'", '', '# Cop supports --auto-correct.', '# Configuration parameters: AllowForAlignment.', 'Layout/SpaceAroundOperators:', ' Exclude:', " - 'example1.rb'", '', '# Cop supports --auto-correct.', '# Configuration parameters: IndentationWidth.', 'Layout/Tab:', ' Exclude:', " - 'example2.rb'", '', '# Cop supports --auto-correct.', 'Layout/TrailingWhitespace:', ' Exclude:', " - 'example1.rb'", '', 'Style/Documentation:', ' Exclude:', " - 'spec/**/*'", # Copied from default configuration " - 'test/**/*'", # Copied from default configuration " - 'example2.rb'", '', '# Configuration parameters: AllowedVariables.', 'Style/GlobalVars:', ' Exclude:', " - 'example1.rb'", '', '# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, ' \ 'IgnoreCopDirectives, IgnoredPatterns.', '# URISchemes: http, https', 'Metrics/LineLength:', ' Max: 90'] actual = IO.read('.rubocop_todo.yml').split($RS) expected.each_with_index do |line, ix| if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end end expect(actual.size).to eq(expected.size) end describe 'when different styles appear in different files' do before do create_file('example1.rb', ['$!']) create_file('example2.rb', ['$!']) create_file('example3.rb', ['$ERROR_INFO']) end it 'disables cop if --exclude-limit is exceeded' do expect(cli.run(['--auto-gen-config', '--exclude-limit', '1'])).to eq(1) expect(IO.readlines('.rubocop_todo.yml')[8..-1].join) .to eq(<<-YAML.strip_indent) # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: use_perl_names, use_english_names Style/SpecialGlobalVars: Enabled: false YAML end it 'generates Exclude list if --exclude-limit is not exceeded' do create_file('example4.rb', ['$!']) expect(cli.run(['--auto-gen-config', '--exclude-limit', '10'])).to eq(1) expect(IO.readlines('.rubocop_todo.yml')[8..-1].join) .to eq(<<-YAML.strip_indent) # Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: use_perl_names, use_english_names Style/SpecialGlobalVars: Exclude: - 'example1.rb' - 'example2.rb' - 'example4.rb' YAML end end it 'can be called when there are no files to inspection' do expect(cli.run(['--auto-gen-config'])).to eq(0) end end end rubocop-0.52.1/spec/rubocop/cli/cli_autocorrect_spec.rb000066400000000000000000001130051322072016200231350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::CLI, :isolated_environment do include_context 'cli spec behavior' subject(:cli) { described_class.new } before do RuboCop::ConfigLoader.default_configuration = nil end it 'does not correct ExtraSpacing in a hash that would be changed back' do create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/AlignHash: EnforcedColonStyle: table YAML source = <<-RUBY.strip_indent hash = { alice: { age: 23, role: 'Director' }, bob: { age: 25, role: 'Consultant' } } RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(1) expect(IO.read('example.rb')).to eq(source) end it 'does not correct SpaceAroundOperators in a hash that would be ' \ 'changed back' do create_file('.rubocop.yml', <<-YAML.strip_indent) Style/HashSyntax: EnforcedStyle: hash_rockets Layout/AlignHash: EnforcedHashRocketStyle: table YAML source = <<-RUBY.strip_indent a = { 1=>2, a => b } hash = { :alice => { :age => 23, :role => 'Director' }, :bob => { :age => 25, :role => 'Consultant' } } RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(1) # 1=>2 is changed to 1 => 2. The rest is unchanged. # SpaceAroundOperators leaves it to AlignHash when the style is table. expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) a = { 1 => 2, a => b } hash = { :alice => { :age => 23, :role => 'Director' }, :bob => { :age => 25, :role => 'Consultant' } } RUBY end describe 'trailing comma cops' do let(:source) do <<-RUBY.strip_indent func({ @abc => 0, @xyz => 1 }) func( { abc: 0 } ) func( {}, { xyz: 1 } ) RUBY end let(:config) do { 'Style/TrailingCommaInArguments' => { 'EnforcedStyleForMultiline' => comma_style }, 'Style/TrailingCommaInLiteral' => { 'EnforcedStyleForMultiline' => comma_style }, 'Style/BracesAroundHashParameters' => braces_around_hash_parameters_config } end before do create_file('example.rb', source) create_file('.rubocop.yml', YAML.dump(config)) end shared_examples 'corrects offenses without producing a double comma' do it 'corrects TrailingCommaInLiteral and TrailingCommaInArguments ' \ 'without producing a double comma' do cli.run(['--auto-correct']) expect(IO.read('example.rb')) .to eq(expected_corrected_source) expect($stderr.string).to eq('') end end context 'when the style is `comma`' do let(:comma_style) do 'comma' end context 'and Style/BracesAroundHashParameters is disabled' do let(:braces_around_hash_parameters_config) do { 'Enabled' => false, 'AutoCorrect' => false, 'EnforcedStyle' => 'braces' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func({ @abc => 0, @xyz => 1, }) func( { abc: 0, }, ) func( {}, { xyz: 1, }, ) RUBY end include_examples 'corrects offenses without producing a double comma' end context 'and BracesAroundHashParameters style is `no_braces`' do let(:braces_around_hash_parameters_config) do { 'EnforcedStyle' => 'no_braces' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func( @abc => 0, @xyz => 1, ) func( abc: 0, ) func( {}, xyz: 1, ) RUBY end include_examples 'corrects offenses without producing a double comma' end context 'and BracesAroundHashParameters style is `context_dependent`' do let(:braces_around_hash_parameters_config) do { 'EnforcedStyle' => 'context_dependent' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func( @abc => 0, @xyz => 1, ) func( abc: 0, ) func( {}, { xyz: 1, }, ) RUBY end include_examples 'corrects offenses without producing a double comma' end end context 'when the style is `consistent_comma`' do let(:comma_style) do 'consistent_comma' end context 'and Style/BracesAroundHashParameters is disabled' do let(:braces_around_hash_parameters_config) do { 'Enabled' => false, 'AutoCorrect' => false, 'EnforcedStyle' => 'braces' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func({ @abc => 0, @xyz => 1, },) func( { abc: 0, }, ) func( {}, { xyz: 1, }, ) RUBY end include_examples 'corrects offenses without producing a double comma' end context 'and BracesAroundHashParameters style is `no_braces`' do let(:braces_around_hash_parameters_config) do { 'EnforcedStyle' => 'no_braces' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func( @abc => 0, @xyz => 1, ) func( abc: 0, ) func( {}, xyz: 1, ) RUBY end include_examples 'corrects offenses without producing a double comma' end context 'and BracesAroundHashParameters style is `context_dependent`' do let(:braces_around_hash_parameters_config) do { 'EnforcedStyle' => 'context_dependent' } end let(:expected_corrected_source) do <<-RUBY.strip_indent func( @abc => 0, @xyz => 1, ) func( abc: 0, ) func( {}, { xyz: 1, }, ) RUBY end include_examples 'corrects offenses without producing a double comma' end end end context 'space_inside_bracket cops' do let(:source) do <<-RUBY.strip_indent [ a[b], c[ d ], [1, 2] ] foo[[ 3, 4 ], [5, 6] ] RUBY end let(:config) do { 'Layout/SpaceInsideArrayLiteralBrackets' => { 'EnforcedStyle' => array_style }, 'Layout/SpaceInsideReferenceBrackets' => { 'EnforcedStyle' => reference_style } } end before do create_file('example.rb', source) create_file('.rubocop.yml', YAML.dump(config)) end shared_examples 'corrects offenses' do it 'corrects SpaceInsideArrayLiteralBrackets and ' \ 'SpaceInsideReferenceBrackets' do cli.run(['--auto-correct']) expect(IO.read('example.rb')) .to eq(corrected_source) expect($stderr.string).to eq('') end end context 'when array style is space & reference style is no space' do let(:array_style) { 'space' } let(:reference_style) { 'no_space' } let(:corrected_source) do <<-RUBY.strip_indent [ a[b], c[d], [ 1, 2 ] ] foo[[ 3, 4 ], [ 5, 6 ]] RUBY end include_examples 'corrects offenses' end context 'when array style is no_space & reference style is space' do let(:array_style) { 'no_space' } let(:reference_style) { 'space' } let(:corrected_source) do <<-RUBY.strip_indent [a[ b ], c[ d ], [1, 2]] foo[ [3, 4], [5, 6] ] RUBY end include_examples 'corrects offenses' end context 'when array style is compact & reference style is no_space' do let(:array_style) { 'compact' } let(:reference_style) { 'no_space' } let(:corrected_source) do <<-RUBY.strip_indent [ a[b], c[d], [ 1, 2 ]] foo[[ 3, 4 ], [ 5, 6 ]] RUBY end include_examples 'corrects offenses' end context 'when array style is compact & reference style is space' do let(:array_style) { 'compact' } let(:reference_style) { 'space' } let(:corrected_source) do <<-RUBY.strip_indent [ a[ b ], c[ d ], [ 1, 2 ]] foo[ [ 3, 4 ], [ 5, 6 ] ] RUBY end include_examples 'corrects offenses' end end it 'corrects IndentationWidth, RedundantBegin, and ' \ 'RescueEnsureAlignment offenses' do source = <<-RUBY.strip_indent def verify_section begin scroll_down_until_element_exists rescue StandardError scroll_down_until_element_exists end end RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(0) corrected = <<-RUBY.strip_indent def verify_section scroll_down_until_element_exists rescue StandardError scroll_down_until_element_exists end RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'corrects LineEndConcatenation offenses leaving the ' \ 'UnneededInterpolation offense unchanged' do # If we change string concatenation from plus to backslash, the string # literal that follows must remain a string literal. source = <<-'RUBY'.strip_indent puts 'foo' + "#{bar}" puts 'a' + 'b' "#{c}" RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(0) corrected = ["puts 'foo' \\", ' "#{bar}"', # Expressions that need correction from only one of these cops # are corrected as expected. "puts 'a' \\", " 'b'", 'c.to_s', ''].join("\n") expect(IO.read('example.rb')).to eq(corrected) end %i[line_count_based semantic braces_for_chaining].each do |style| context "when BlockDelimiters has #{style} style" do it 'corrects SpaceBeforeBlockBraces, SpaceInsideBlockBraces offenses' do source = <<-RUBY.strip_indent r = foo.map{|a| a.bar.to_s } foo.map{|a| a.bar.to_s }.baz RUBY create_file('example.rb', source) create_file('.rubocop.yml', <<-YAML.strip_indent) Style/BlockDelimiters: EnforcedStyle: #{style} YAML expect(cli.run(['--auto-correct'])).to eq(1) corrected = case style when :semantic <<-RUBY.strip_indent r = foo.map { |a| a.bar.to_s } foo.map { |a| a.bar.to_s }.baz RUBY when :braces_for_chaining <<-RUBY.strip_indent r = foo.map do |a| a.bar.to_s end foo.map { |a| a.bar.to_s }.baz RUBY when :line_count_based <<-RUBY.strip_indent r = foo.map do |a| a.bar.to_s end foo.map do |a| a.bar.to_s end.baz RUBY end expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(corrected) end end end it 'corrects InitialIndentation offenses' do source = <<-RUBY.strip_indent # comment 1 # comment 2 def func begin foo bar rescue StandardError baz end end RUBY create_file('example.rb', source) create_file('.rubocop.yml', <<-YAML.strip_indent) Lint/DefEndAlignment: AutoCorrect: true YAML expect(cli.run(['--auto-correct'])).to eq(0) corrected = <<-RUBY.strip_indent # comment 1 # comment 2 def func foo bar rescue StandardError baz end RUBY expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(corrected) end it 'corrects UnneededDisable offenses' do source = <<-RUBY.strip_indent class A # rubocop:disable Metrics/MethodLength def func x = foo # rubocop:disable Lint/UselessAssignment,Style/For # rubocop:disable all # rubocop:disable Style/ClassVars @@bar = "3" end end RUBY create_file('example.rb', source) expect(cli.run(%w[--auto-correct --format simple])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 1: Style/Documentation: Missing top-level class documentation comment. W: 2: 3: [Corrected] Lint/UnneededDisable: Unnecessary disabling of Metrics/MethodLength. W: 4: 54: [Corrected] Lint/UnneededDisable: Unnecessary disabling of Style/For. W: 6: 5: [Corrected] Lint/UnneededDisable: Unnecessary disabling of Style/ClassVars. 1 file inspected, 4 offenses detected, 3 offenses corrected RESULT corrected = <<-RUBY.strip_indent class A def func x = foo # rubocop:disable Lint/UselessAssignment # rubocop:disable all @@bar = "3" end end RUBY expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(corrected) end it 'corrects RedundantBegin offenses and fixes indentation etc' do source = <<-RUBY.strip_indent def func begin foo bar rescue baz end end def func; begin; x; y; rescue; z end end def method begin BlockA do |strategy| foo end BlockB do |portfolio| foo end rescue => e # some problem bar end end def method begin # comment 1 do_some_stuff rescue # comment 2 end # comment 3 end RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(1) corrected = <<-RUBY.strip_indent def func foo bar rescue StandardError baz end def func x; y; rescue StandardError; z end def method BlockA do |_strategy| foo end BlockB do |_portfolio| foo end rescue StandardError => e # some problem bar end def method # comment 1 do_some_stuff rescue StandardError # comment 2 # comment 3 end RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'corrects Tab and IndentationConsistency offenses' do source = <<-RUBY.strip_indent render_views describe 'GET index' do \t it 'returns http success' do \t end \tdescribe 'admin user' do before(:each) do \t end \tend end RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(0) corrected = <<-RUBY.strip_indent render_views describe 'GET index' do it 'returns http success' do end describe 'admin user' do before(:each) do end end end RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'corrects IndentationWidth and IndentationConsistency offenses' do source = <<-RUBY.strip_indent require 'spec_helper' describe ArticlesController do render_views describe "GET \'index\'" do it "returns http success" do end describe "admin user" do before(:each) do end end end end RUBY create_file('example.rb', source) expect(cli.run(['--auto-correct'])).to eq(0) corrected = <<-RUBY.strip_indent require 'spec_helper' describe ArticlesController do render_views describe \"GET 'index'\" do it 'returns http success' do end describe 'admin user' do before(:each) do end end end end RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'corrects SymbolProc and SpaceBeforeBlockBraces offenses' do source = ['foo.map{ |a| a.nil? }'] create_file('example.rb', source) expect(cli.run(['-D', '--auto-correct'])).to eq(0) corrected = "foo.map(&:nil?)\n" expect(IO.read('example.rb')).to eq(corrected) uncorrected = $stdout.string.split($RS).select do |line| line.include?('example.rb:') && !line.include?('[Corrected]') end expect(uncorrected.empty?).to be(true) # Hence exit code 0. end it 'corrects only IndentationWidth without crashing' do source = <<-RUBY.strip_indent foo = if bar something elsif baz other_thing else raise end RUBY create_file('example.rb', source) expect(cli.run(%w[--only IndentationWidth --auto-correct])).to eq(0) corrected = <<-RUBY.strip_indent foo = if bar something elsif baz other_thing else raise end RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'corrects complicated cases conservatively' do # Two cops make corrections here; Style/BracesAroundHashParameters, and # Style/AlignHash. Because they make minimal corrections relating only # to their specific areas, and stay away from cleaning up extra # whitespace in the process, the combined changes don't interfere with # each other and the result is semantically the same as the starting # point. source = <<-RUBY.strip_indent expect(subject[:address]).to eq({ street1: '1 Market', street2: '#200', city: 'Some Town', state: 'CA', postal_code: '99999-1111' }) RUBY create_file('example.rb', source) expect(cli.run(['-D', '--auto-correct'])).to eq(0) corrected = <<-RUBY.strip_indent expect(subject[:address]).to eq( street1: '1 Market', street2: '#200', city: 'Some Town', state: 'CA', postal_code: '99999-1111' ) RUBY expect(IO.read('example.rb')).to eq(corrected) end it 'honors Exclude settings in individual cops' do source = 'puts %x(ls)' create_file('example.rb', source) create_file('.rubocop.yml', <<-YAML.strip_indent) Style/CommandLiteral: Exclude: - example.rb YAML expect(cli.run(['--auto-correct'])).to eq(0) expect($stdout.string).to include('no offenses detected') expect(IO.read('example.rb')).to eq("#{source}\n") end it 'corrects code with indentation problems' do create_file('example.rb', <<-RUBY.strip_indent) module Bar class Goo def something first call do_other 'things' if other > 34 more_work end end end end module Foo class Bar stuff = [ { some: 'hash', }, { another: 'hash', with: 'more' }, ] end end RUBY expect(cli.run(['--auto-correct'])).to eq(1) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) module Bar class Goo def something first call do_other 'things' more_work if other > 34 end end end module Foo class Bar stuff = [ { some: 'hash' }, { another: 'hash', with: 'more' } ] end end RUBY end it 'can change block comments and indent them' do create_file('example.rb', <<-RUBY.strip_indent) module Foo class Bar =begin This is a nice long comment which spans a few lines =end def baz do_something end end end RUBY expect(cli.run(['--auto-correct'])).to eq(1) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) module Foo class Bar # This is a nice long # comment # which spans a few lines def baz do_something end end end RUBY end it 'can correct two problems with blocks' do # {} should be do..end and space is missing. create_file('example.rb', <<-RUBY.strip_indent) (1..10).each{ |i| puts i } RUBY expect(cli.run(['--auto-correct'])).to eq(0) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) (1..10).each do |i| puts i end RUBY end it 'can handle spaces when removing braces' do create_file('example.rb', ["assert_post_status_code 400, 's', {:type => 'bad'}"]) expect(cli.run(%w[--auto-correct --format emacs])).to eq(0) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) assert_post_status_code 400, 's', type: 'bad' RUBY e = abs('example.rb') # TODO: Don't report that a problem is corrected when it # actually went away due to another correction. expect($stdout.string).to eq(<<-RESULT.strip_indent) #{e}:1:35: C: [Corrected] Layout/SpaceInsideHashLiteralBraces: Space inside { missing. #{e}:1:35: C: [Corrected] Style/BracesAroundHashParameters: Redundant curly braces around a hash parameter. #{e}:1:36: C: [Corrected] Style/HashSyntax: Use the new Ruby 1.9 hash syntax. #{e}:1:50: C: [Corrected] Layout/SpaceInsideHashLiteralBraces: Space inside } missing. RESULT end # A case where two cops, EmptyLinesAroundBody and EmptyLines, try to # remove the same line in autocorrect. it 'can correct two empty lines at end of class body' do create_file('example.rb', <<-RUBY.strip_indent) class Test def f end end RUBY expect(cli.run(['--auto-correct'])).to eq(1) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) class Test def f; end end RUBY end # A case where WordArray's correction can be clobbered by # AccessModifierIndentation's correction. it 'can correct indentation and another thing' do create_file('example.rb', <<-RUBY.strip_indent) class Dsl private A = ["git", "path",] end RUBY expect(cli.run(%w[--auto-correct --format emacs])).to eq(1) expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) class Dsl private A = %w[git path].freeze end RUBY e = abs('example.rb') expect($stdout.string).to eq(<<-RESULT.strip_indent) #{e}:1:1: C: Style/Documentation: Missing top-level class documentation comment. #{e}:2:1: C: [Corrected] Layout/AccessModifierIndentation: Indent access modifiers like `private`. #{e}:2:1: C: [Corrected] Layout/EmptyLinesAroundAccessModifier: Keep a blank line after `private`. #{e}:2:3: W: Lint/UselessAccessModifier: Useless `private` access modifier. #{e}:3:7: C: [Corrected] Style/MutableConstant: Freeze mutable objects assigned to constants. #{e}:3:7: C: [Corrected] Style/WordArray: Use `%w` or `%W` for an array of words. #{e}:3:8: C: [Corrected] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. #{e}:3:15: C: [Corrected] Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. #{e}:3:21: C: [Corrected] Style/TrailingCommaInLiteral: Avoid comma after the last item of an array. #{e}:4:7: C: [Corrected] Style/WordArray: Use `%w` or `%W` for an array of words. RESULT end # A case where the same cop could try to correct an offense twice in one # place. it 'can correct empty line inside special form of nested modules' do create_file('example.rb', <<-RUBY.strip_indent) module A module B end end RUBY expect(cli.run(['--auto-correct'])).to eq(1) expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) module A module B end end RUBY uncorrected = $stdout.string.split($RS).select do |line| line.include?('example.rb:') && !line.include?('[Corrected]') end expect(uncorrected.empty?).to be(false) # Hence exit code 1. end it 'can correct single line methods' do create_file('example.rb', <<-RUBY.strip_indent) def func1; do_something end # comment def func2() do_1; do_2; end RUBY expect(cli.run(%w[--auto-correct --format offenses])).to eq(0) expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) # comment def func1 do_something end def func2 do_1 do_2 end RUBY expect($stdout.string).to eq(<<-RESULT.strip_indent) 6 Layout/TrailingWhitespace 3 Style/Semicolon 2 Style/SingleLineMethods 1 Layout/EmptyLineBetweenDefs 1 Style/DefWithParentheses -- 13 Total RESULT end # In this example, the auto-correction (changing "fail" to "raise") # creates a new problem (alignment of parameters), which is also # corrected automatically. it 'can correct a problems and the problem it creates' do create_file('example.rb', <<-RUBY.strip_indent) fail NotImplementedError, 'Method should be overridden in child classes' RUBY expect(cli.run(['--auto-correct'])).to eq(0) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) raise NotImplementedError, 'Method should be overridden in child classes' RUBY expect($stdout.string).to eq(<<-RESULT.strip_indent) Inspecting 1 file C Offenses: example.rb:1:1: C: [Corrected] Style/SignalException: Always use raise to signal exceptions. fail NotImplementedError, ^^^^ example.rb:2:6: C: [Corrected] Layout/AlignParameters: Align the parameters of a method call if they span more than one line. 'Method should be overridden in child classes' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1 file inspected, 2 offenses detected, 2 offenses corrected RESULT end # Thanks to repeated auto-correction, we can get rid of the trailing # spaces, and then the extra empty line. it 'can correct two problems in the same place' do create_file('example.rb', ['# Example class.', 'class Klass', ' ', ' def f; end', 'end']) expect(cli.run(['--auto-correct'])).to eq(0) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) # Example class. class Klass def f; end end RUBY expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-RESULT.strip_indent) Inspecting 1 file C Offenses: example.rb:3:1: C: [Corrected] Layout/EmptyLinesAroundClassBody: Extra empty line detected at class body beginning. example.rb:3:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 2 offenses detected, 2 offenses corrected RESULT end it 'can correct MethodDefParentheses and other offense' do create_file('example.rb', <<-RUBY.strip_indent) def primes limit 1.upto(limit).select { |i| i.even? } end RUBY expect(cli.run(%w[-D --auto-correct])).to eq(0) expect($stderr.string).to eq('') expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) def primes(limit) 1.upto(limit).select(&:even?) end RUBY expect($stdout.string) .to eq(['Inspecting 1 file', 'C', '', 'Offenses:', '', 'example.rb:1:12: C: [Corrected] ' \ 'Style/MethodDefParentheses: ' \ 'Use def with parentheses when there are parameters.', 'def primes limit', ' ^^^^^', 'example.rb:2:24: C: [Corrected] Style/SymbolProc: ' \ 'Pass &:even? as an argument to select instead of a block.', ' 1.upto(limit).select { |i| i.even? }', ' ^^^^^^^^^^^^^^^', '', '1 file inspected, 2 offenses detected, 2 offenses ' \ 'corrected', ''].join("\n")) end it 'can correct WordArray and SpaceAfterComma offenses' do create_file('example.rb', <<-RUBY.strip_indent) f(type: ['offline','offline_payment'], bar_colors: ['958c12','953579','ff5800','0085cc']) RUBY expect(cli.run(%w[-D --auto-correct --format o])).to eq(0) expect($stdout.string) .to eq(<<-RESULT.strip_indent) 4 Layout/SpaceAfterComma 2 Style/WordArray -- 6 Total RESULT expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) f(type: %w[offline offline_payment], bar_colors: %w[958c12 953579 ff5800 0085cc]) RUBY end it 'can correct SpaceAfterComma and HashSyntax offenses' do create_file('example.rb', "I18n.t('description',:property_name => property.name)") expect(cli.run(%w[-D --auto-correct --format emacs])).to eq(0) expect($stdout.string) .to eq(["#{abs('example.rb')}:1:21: C: [Corrected] " \ 'Layout/SpaceAfterComma: Space missing after comma.', "#{abs('example.rb')}:1:22: C: [Corrected] " \ 'Style/HashSyntax: Use the new Ruby 1.9 hash syntax.', ''].join("\n")) expect(IO.read('example.rb')) .to eq("I18n.t('description', property_name: property.name)\n") end it 'can correct HashSyntax and SpaceAroundOperators offenses' do create_file('example.rb', '{ :b=>1 }') expect(cli.run(%w[-D --auto-correct --format emacs])).to eq(0) expect(IO.read('example.rb')).to eq("{ b: 1 }\n") expect($stdout.string) .to eq(["#{abs('example.rb')}:1:3: C: [Corrected] " \ 'Style/HashSyntax: Use the new Ruby 1.9 hash syntax.', "#{abs('example.rb')}:1:5: C: [Corrected] " \ 'Layout/SpaceAroundOperators: Surrounding space missing for ' \ 'operator `=>`.', ''].join("\n")) end it 'can correct HashSyntax when --only is used' do create_file('example.rb', '{ :b=>1 }') expect(cli.run(%w[--auto-correct -f emacs --only Style/HashSyntax])).to eq(0) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq("{ b: 1 }\n") expect($stdout.string) .to eq("#{abs('example.rb')}:1:3: C: [Corrected] Style/HashSyntax: " \ "Use the new Ruby 1.9 hash syntax.\n") end it 'can correct TrailingBlankLines and TrailingWhitespace offenses' do create_file('example.rb', ['# frozen_string_literal: true', '', ' ', '', '']) expect(cli.run(%w[--auto-correct --format emacs])).to eq(0) expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) # frozen_string_literal: true RUBY expect($stdout.string).to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:2:1: C: [Corrected] Layout/TrailingBlankLines: 3 trailing blank lines detected. #{abs('example.rb')}:3:1: C: [Corrected] Layout/TrailingWhitespace: Trailing whitespace detected. RESULT end it 'can correct MethodCallWithoutArgsParentheses and EmptyLiteral offenses' do create_file('example.rb', 'Hash.new()') expect(cli.run(%w[--auto-correct --format emacs])).to eq(0) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq("{}\n") expect($stdout.string).to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:1:1: C: [Corrected] Style/EmptyLiteral: Use hash literal `{}` instead of `Hash.new`. #{abs('example.rb')}:1:9: C: [Corrected] Style/MethodCallWithoutArgsParentheses: Do not use parentheses for method calls with no arguments. RESULT end it 'can correct IndentHash offenses with separator style' do create_file('example.rb', <<-RUBY.strip_indent) CONVERSION_CORRESPONDENCE = { match_for_should: :match, match_for_should_not: :match_when_negated, failure_message_for_should: :failure_message, failure_message_for_should_not: :failure_message_when } RUBY create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/AlignHash: EnforcedColonStyle: separator YAML expect(cli.run(%w[--auto-correct])).to eq(0) expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) CONVERSION_CORRESPONDENCE = { match_for_should: :match, match_for_should_not: :match_when_negated, failure_message_for_should: :failure_message, failure_message_for_should_not: :failure_message_when }.freeze RUBY end it 'does not say [Corrected] if correction was avoided' do src = <<-RUBY.strip_indent func a do b end Signal.trap('TERM') { system(cmd); exit } def self.some_method(foo, bar: 1) log.debug(foo) end RUBY corrected = <<-RUBY.strip_indent func a do b end Signal.trap('TERM') { system(cmd); exit } def self.some_method(foo, bar: 1) log.debug(foo) end RUBY create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: TargetRubyVersion: 2.1 YAML create_file('example.rb', src) expect(cli.run(%w[-a -f simple])).to eq(1) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(corrected) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 8: Style/BlockDelimiters: Prefer {...} over do...end for single-line blocks. C: 2: 34: Style/Semicolon: Do not use semicolons to terminate expressions. W: 3: 27: Lint/UnusedMethodArgument: Unused method argument - bar. 1 file inspected, 3 offenses detected RESULT end it 'does not hang SpaceAfterPunctuation and SpaceInsideParens' do create_file('example.rb', 'some_method(a, )') Timeout.timeout(10) do expect(cli.run(%w[--auto-correct])).to eq(0) end expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq("some_method(a)\n") end it 'does not hang SpaceAfterPunctuation and ' \ 'SpaceInsideArrayLiteralBrackets' do create_file('example.rb', 'puts [1, ]') Timeout.timeout(10) do expect(cli.run(%w[--auto-correct])).to eq(0) end expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq("puts [1]\n") end it 'can be disabled for any cop in configuration' do create_file('example.rb', 'puts "Hello", 123456') create_file('.rubocop.yml', <<-YAML.strip_indent) Style/StringLiterals: AutoCorrect: false YAML expect(cli.run(%w[--auto-correct])).to eq(1) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq("puts \"Hello\", 123_456\n") end it 'handles different SpaceInsideBlockBraces and ' \ 'SpaceInsideHashLiteralBraces' do create_file('example.rb', <<-RUBY.strip_indent) {foo: bar, bar: baz,} foo.each {bar;} RUBY create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/SpaceInsideBlockBraces: EnforcedStyle: space Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: no_space Style/TrailingCommaInLiteral: EnforcedStyleForMultiline: consistent_comma YAML expect(cli.run(%w[--auto-correct])).to eq(1) expect($stderr.string).to eq('') expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) {foo: bar, bar: baz,} foo.each { bar; } RUBY end it 'corrects BracesAroundHashParameters offenses leaving the ' \ 'MultilineHashBraceLayout offense unchanged' do create_file('example.rb', <<-RUBY.strip_indent) def method_a do_something({ a: 1, }) end RUBY expect($stderr.string).to eq('') expect(cli.run(%w[--auto-correct])).to eq(0) expect(IO.read('example.rb')).to eq(<<-RUBY.strip_indent) def method_a do_something(a: 1) end RUBY end end rubocop-0.52.1/spec/rubocop/cli/cli_options_spec.rb000066400000000000000000001301451322072016200223020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::CLI, :isolated_environment do include_context 'cli spec behavior' subject(:cli) { described_class.new } before do RuboCop::ConfigLoader.default_configuration = nil end describe '--parallel' do if RuboCop::Platform.windows? context 'on Windows' do it 'prints a warning' do cli.run ['-P'] expect($stderr.string) .to include('Process.fork is not supported by this Ruby') end end else context 'combined with AllCops:UseCache:false' do before do create_file('.rubocop.yml', ['AllCops:', ' UseCache: false']) end it 'fails with an error message' do cli.run %w[-P] expect($stderr.string) .to include('-P/--parallel uses caching to speed up execution, ' \ 'so combining with AllCops: UseCache: false is not ' \ 'allowed.') end end context 'on Unix-like systems' do it 'prints a message if --debug is specified' do cli.run ['--parallel', '--debug'] expect($stdout.string).to match(/Running parallel inspection/) end it 'does not print a message if --debug is not specified' do cli.run ['--parallel'] expect($stdout.string).not_to match(/Running parallel inspection/) end end end end describe '--list-target-files' do context 'when there are no files' do it 'prints nothing with -L' do cli.run ['-L'] expect($stdout.string.empty?).to be(true) end it 'prints nothing with --list-target-files' do cli.run ['--list-target-files'] expect($stdout.string.empty?).to be(true) end end context 'when there are some files' do before do create_file('show.rabl2', 'object @user => :person') create_file('show.rabl', 'object @user => :person') create_file('app.rb', 'puts "hello world"') create_file('Gemfile', <<-RUBY.strip_indent) source "https://rubygems.org" gem "rubocop" RUBY create_file('lib/helper.rb', 'puts "helpful"') end context 'when there are no includes or excludes' do it 'prints known ruby files' do cli.run ['-L'] expect($stdout.string.split("\n")).to contain_exactly( 'app.rb', 'Gemfile', 'lib/helper.rb', 'show.rabl' ) end end context 'when there is an include and exclude' do before do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - Gemfile Include: - "**/*.rabl2" YAML end it 'prints the included files and not the excluded ones' do cli.run ['--list-target-files'] expect($stdout.string.split("\n")).to contain_exactly( 'app.rb', 'lib/helper.rb', 'show.rabl', 'show.rabl2' ) end end end end describe '--version' do it 'exits cleanly' do expect(cli.run(['-v'])).to eq(0) expect(cli.run(['--version'])).to eq(0) expect($stdout.string).to eq((RuboCop::Version::STRING + "\n") * 2) end end describe '--only' do context 'when one cop is given' do it 'runs just one cop' do # The disable comment should not be reported as unnecessary (even if # it is) since --only overrides configuration. create_file('example.rb', ['# rubocop:disable LineLength', 'if x== 0 ', "\ty", 'end']) # IfUnlessModifier depends on the configuration of LineLength. expect(cli.run(['--format', 'simple', '--only', 'Style/IfUnlessModifier', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(['== example.rb ==', 'C: 2: 1: Style/IfUnlessModifier: Favor modifier if ' \ 'usage when having a single-line body. Another good ' \ 'alternative is the usage of control flow &&/||.', '', '1 file inspected, 1 offense detected', ''].join("\n")) end it 'exits with error if an incorrect cop name is passed' do create_file('example.rb', ['if x== 0 ', "\ty", 'end']) expect(cli.run(['--only', 'Style/123'])).to eq(2) expect($stderr.string) .to include('Unrecognized cop or department: Style/123.') end it 'displays correction candidate if an incorrect cop name is given' do create_file('example.rb', ['x']) expect(cli.run(['--only', 'Style/BlockComment'])).to eq(2) expect($stderr.string) .to include('Unrecognized cop or department: Style/BlockComment.') expect($stderr.string) .to include('Did you mean? Style/BlockComments') end it 'exits with error if an empty string is given' do create_file('example.rb', 'x') expect(cli.run(['--only', ''])).to eq(2) expect($stderr.string).to include('Unrecognized cop or department: .') end %w[Syntax Lint/Syntax].each do |name| it "only checks syntax if #{name} is given" do create_file('example.rb', 'x ') expect(cli.run(['--only', name])).to eq(0) expect($stdout.string).to include('no offenses detected') end end %w[Lint/UnneededDisable UnneededDisable].each do |name| it "exits with error if cop name #{name} is passed" do create_file('example.rb', ['if x== 0 ', "\ty", 'end']) expect(cli.run(['--only', 'UnneededDisable'])).to eq(2) expect($stderr.string) .to include('Lint/UnneededDisable can not be used with --only.') end end it 'accepts cop names from plugins' do create_file('.rubocop.yml', <<-YAML.strip_indent) require: rubocop_ext Style/SomeCop: Description: Something Enabled: true YAML create_file('rubocop_ext.rb', <<-RUBY.strip_indent) module RuboCop module Cop module Style class SomeCop < Cop end end end end RUBY create_file('redirect.rb', '$stderr = STDOUT') rubocop = "#{RuboCop::ConfigLoader::RUBOCOP_HOME}/bin/rubocop" # Since we define a new cop class, we have to do this in a separate # process. Otherwise, the extra cop will affect other specs. output = `ruby -I . "#{rubocop}" --require redirect.rb --only Style/SomeCop` expect($CHILD_STATUS.success?).to be_truthy expect(output) .to eq(<<-RESULT.strip_indent) Inspecting 2 files .. 2 files inspected, no offenses detected RESULT end context 'without using namespace' do it 'runs just one cop' do create_file('example.rb', ['if x== 0 ', "\ty", 'end']) expect(cli.run(['--format', 'simple', '--display-cop-names', '--only', 'IfUnlessModifier', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(['== example.rb ==', 'C: 1: 1: Style/IfUnlessModifier: Favor modifier if ' \ 'usage when having a single-line body. Another good ' \ 'alternative is the usage of control flow &&/||.', '', '1 file inspected, 1 offense detected', ''].join("\n")) end end it 'enables the given cop' do create_file('example.rb', ['x = 0 ', # Disabling comments still apply. '# rubocop:disable Layout/TrailingWhitespace', 'y = 1 ']) create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/TrailingWhitespace: Enabled: false YAML expect(cli.run(['--format', 'simple', '--only', 'Layout/TrailingWhitespace', 'example.rb'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end end context 'when several cops are given' do it 'runs the given cops' do create_file('example.rb', ['if x== 100000000000000 ', "\ty", 'end']) expect(cli.run(['--format', 'simple', '--only', 'Style/IfUnlessModifier,Layout/Tab,' \ 'Layout/SpaceAroundOperators', 'example.rb'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 1: Style/IfUnlessModifier: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &&/||. C: 1: 5: Layout/SpaceAroundOperators: Surrounding space missing for operator ==. C: 2: 1: Layout/Tab: Tab detected. 1 file inspected, 3 offenses detected RESULT end context 'and --lint' do it 'runs the given cops plus all enabled lint cops' do create_file('example.rb', ['if x== 100000000000000 ', "\ty = 3", ' end']) create_file('.rubocop.yml', <<-YAML.strip_indent) Lint/EndAlignment: Enabled: false YAML expect(cli.run(['--format', 'simple', '--only', 'Layout/Tab,Layout/SpaceAroundOperators', '--lint', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 5: Layout/SpaceAroundOperators: Surrounding space missing for operator ==. C: 2: 1: Layout/Tab: Tab detected. W: 2: 2: Lint/UselessAssignment: Useless assignment to variable - y. 1 file inspected, 3 offenses detected RESULT end end end context 'when a namespace is given' do it 'runs all enabled cops in that namespace' do create_file('example.rb', ['if x== 100000000000000 ', ' ' + '#' * 100, "\ty", 'end']) expect(cli.run(%w[-f offenses --only Metrics example.rb])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Metrics/LineLength -- 1 Total RESULT end end context 'when three namespaces are given' do it 'runs all enabled cops in those namespaces' do create_file('example.rb', ['if x== 100000000000000 ', ' # ' + '-' * 98, "\ty", 'end']) create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/SpaceAroundOperators: Enabled: false YAML expect(cli.run(%w[-f o --only Metrics,Style,Layout example.rb])) .to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 Layout/CommentIndentation 1 Layout/IndentationWidth 1 Layout/Tab 1 Layout/TrailingWhitespace 1 Metrics/LineLength 1 Style/NumericLiterals -- 6 Total RESULT end end end describe '--except' do context 'when one name is given' do it 'exits with error if the cop name is incorrect' do create_file('example.rb', ['if x== 0 ', "\ty", 'end']) expect(cli.run(['--except', 'Style/123'])).to eq(2) expect($stderr.string) .to include('Unrecognized cop or department: Style/123.') end it 'exits with error if an empty string is given' do create_file('example.rb', 'x') expect(cli.run(['--except', ''])).to eq(2) expect($stderr.string).to include('Unrecognized cop or department: .') end it 'displays correction candidate if an incorrect cop name is given' do create_file('example.rb', 'x') expect(cli.run(['--except', 'Style/BlockComment'])).to eq(2) expect($stderr.string) .to include('Unrecognized cop or department: Style/BlockComment.') expect($stderr.string) .to include('Did you mean? Style/BlockComments') end %w[Syntax Lint/Syntax].each do |name| it "exits with error if #{name} is given" do create_file('example.rb', 'x ') expect(cli.run(['--except', name])).to eq(2) expect($stderr.string) .to include('Syntax checking can not be turned off.') end end end context 'when one cop plus one namespace are given' do it 'runs all cops except the given' do # The disable comment should not be reported as unnecessary (even if # it is) since --except overrides configuration. create_file('example.rb', ['# rubocop:disable LineLength', 'if x== 0 ', "\ty = 3", 'end']) expect(cli.run(['--format', 'offenses', '--except', 'Style/IfUnlessModifier,Lint', 'example.rb'])).to eq(1) # Note: No Lint/UselessAssignment offense. expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 Layout/IndentationWidth 1 Layout/SpaceAroundOperators 1 Layout/Tab 1 Layout/TrailingWhitespace 1 Style/NumericPredicate -- 5 Total RESULT end end context 'when one cop is given without namespace' do it 'disables the given cop' do create_file('example.rb', ['if x== 0 ', "\ty", 'end']) cli.run(['--format', 'offenses', '--except', 'IfUnlessModifier', 'example.rb']) with_option = $stdout.string $stdout = StringIO.new cli.run(['--format', 'offenses', 'example.rb']) without_option = $stdout.string expect(without_option.split($RS) - with_option.split($RS)) .to eq(['1 Style/IfUnlessModifier', '6 Total']) end end context 'when several cops are given' do %w[UnneededDisable Lint/UnneededDisable Lint].each do |cop_name| it "disables the given cops including #{cop_name}" do create_file('example.rb', ['if x== 100000000000000 ', "\ty", 'end # rubocop:disable all']) expect(cli.run(['--format', 'offenses', '--except', 'Style/IfUnlessModifier,Layout/Tab,' \ "Layout/SpaceAroundOperators,#{cop_name}", 'example.rb'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 Layout/IndentationWidth 1 Layout/TrailingWhitespace 1 Style/NumericLiterals -- 3 Total RESULT end end end end describe '--lint' do it 'runs only lint cops' do create_file('example.rb', ['if 0 ', "\ty", "\tz # rubocop:disable Layout/Tab", 'end']) # IfUnlessModifier depends on the configuration of LineLength. expect(cli.run(['--format', 'simple', '--lint', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == W: 1: 4: Lint/LiteralAsCondition: Literal 0 appeared as a condition. 1 file inspected, 1 offense detected RESULT end end describe '-d/--debug' do it 'shows config files' do create_file('example1.rb', "\tputs 0") expect(cli.run(['--debug', 'example1.rb'])).to eq(1) home = File.dirname(File.dirname(File.dirname(File.dirname(__FILE__)))) expect($stdout.string.lines.grep(/configuration/).map(&:chomp)) .to eq(["For #{abs('')}:" \ " configuration from #{home}/config/default.yml", "Inheriting configuration from #{home}/config/enabled.yml", "Inheriting configuration from #{home}/config/disabled.yml"]) end it 'shows cop names' do create_file('example1.rb', 'puts 0 ') file = abs('example1.rb') expect(cli.run(['--format', 'emacs', '--debug', 'example1.rb'])).to eq(1) expect($stdout.string.lines.to_a[-1]) .to eq("#{file}:1:7: C: Layout/TrailingWhitespace: Trailing " \ "whitespace detected.\n") end end describe '-D/--display-cop-names' do before do create_file('example1.rb', 'puts 0 # rubocop:disable NumericLiterals ') end let(:file) { abs('example1.rb') } it 'shows cop names' do expect(cli.run(['--format', 'emacs', '--display-cop-names', 'example1.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) #{file}:1:8: W: Lint/UnneededDisable: Unnecessary disabling of `Style/NumericLiterals`. #{file}:1:41: C: Layout/TrailingWhitespace: Trailing whitespace detected. RESULT end context '--no-display-cop-names' do it 'does not show cop names' do expect(cli.run(['--format', 'emacs', '--no-display-cop-names', 'example1.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) #{file}:1:8: W: Unnecessary disabling of `Style/NumericLiterals`. #{file}:1:41: C: Trailing whitespace detected. RESULT end end context 'DisplayCopNames: false in .rubocop.yml' do before do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: DisplayCopNames: false YAML end it 'shows cop names' do expect(cli.run(['--format', 'emacs', '--display-cop-names', 'example1.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) #{file}:1:8: W: Lint/UnneededDisable: Unnecessary disabling of `Style/NumericLiterals`. #{file}:1:41: C: Layout/TrailingWhitespace: Trailing whitespace detected. RESULT end context 'without --display-cop-names' do it 'does not show cop names' do expect(cli.run(['--format', 'emacs', 'example1.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) #{file}:1:8: W: Unnecessary disabling of `Style/NumericLiterals`. #{file}:1:41: C: Trailing whitespace detected. RESULT end end end end describe '-E/--extra-details' do it 'shows extra details' do create_file('example1.rb', 'puts 0 # rubocop:disable NumericLiterals ') create_file('.rubocop.yml', <<-YAML.strip_indent) TrailingWhitespace: Details: Trailing space is just sloppy. YAML file = abs('example1.rb') expect(cli.run(['--format', 'emacs', '--extra-details', 'example1.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) #{file}:1:8: W: Lint/UnneededDisable: Unnecessary disabling of `Style/NumericLiterals`. #{file}:1:41: C: Layout/TrailingWhitespace: Trailing whitespace detected. Trailing space is just sloppy. RESULT expect($stderr.string).to eq('') end end describe '-S/--display-style-guide' do it 'shows style guide entry' do create_file('example1.rb', 'puts 0 ') file = abs('example1.rb') url = 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' expect(cli.run(['--format', 'emacs', '--display-style-guide', 'example1.rb'])).to eq(1) expect($stdout.string.lines.to_a[-1]) .to eq("#{file}:1:7: C: Layout/TrailingWhitespace: " \ "Trailing whitespace detected. (#{url})\n") end it 'shows reference entry' do create_file('example1.rb', '[1, 2, 3].reverse.each { |e| puts e }') file = abs('example1.rb') url = 'https://github.com/JuanitoFatas/fast-ruby' \ '#enumerablereverseeach-vs-enumerablereverse_each-code' expect(cli.run(['--format', 'emacs', '--display-style-guide', 'example1.rb'])).to eq(1) output = "#{file}:1:11: C: Performance/ReverseEach: " \ "Use `reverse_each` instead of `reverse.each`. (#{url})" expect($stdout.string.lines.to_a[-1]) .to eq([output, ''].join("\n")) end it 'shows style guide and reference entries' do create_file('example1.rb', '$foo = 1') file = abs('example1.rb') style_guide_link = 'https://github.com/bbatsov/ruby-style-guide' \ '#instance-vars' reference_link = 'http://www.zenspider.com/Languages/Ruby/QuickRef.html' expect(cli.run(['--format', 'emacs', '--display-style-guide', 'example1.rb'])).to eq(1) output = "#{file}:1:1: C: Style/GlobalVars: " \ 'Do not introduce global variables. ' \ "(#{style_guide_link}, #{reference_link})" expect($stdout.string.lines.to_a[-1]) .to eq([output, ''].join("\n")) end end describe '--show-cops' do shared_examples(:prints_config) do it 'prints the current configuration' do out = stdout.lines.to_a printed_config = YAML.load(out.join) # rubocop:disable Security/YAMLLoad cop_names = (arguments[0] || '').split(',') cop_names.each do |cop_name| global_conf[cop_name].each do |key, value| printed_value = printed_config[cop_name][key] expect(printed_value).to eq(value) end end end end let(:cops) { RuboCop::Cop::Cop.all } let(:registry) { RuboCop::Cop::Cop.registry } let(:global_conf) do config_path = RuboCop::ConfigLoader.configuration_file_for(Dir.pwd.to_s) RuboCop::ConfigLoader.configuration_from_file(config_path) end let(:stdout) { $stdout.string } before do create_file('.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Max: 110 YAML # expect(cli.run(['--show-cops'] + arguments)).to eq(0) cli.run(['--show-cops'] + arguments) end context 'with no args' do let(:arguments) { [] } # Extracts the first line out of the description def short_description_of_cop(cop) desc = full_description_of_cop(cop) desc ? desc.lines.first.strip : '' end # Gets the full description of the cop or nil if no description is set. def full_description_of_cop(cop) cop_config = global_conf.for_cop(cop) cop_config['Description'] end it 'prints all available cops and their description' do cops.each do |cop| expect(stdout).to include cop.cop_name # Because of line breaks, we will only find the beginning. expect(stdout).to include short_description_of_cop(cop)[0..60] end end it 'prints all departments' do registry.departments.each do |department| expect(stdout).to include(department.to_s) end end it 'prints all cops in their right department listing' do lines = stdout.lines lines.slice_before(/Department /).each do |slice| departments = registry.departments.map(&:to_s) current = departments.delete(slice.shift[/Department '(?[^']+)'/, 'c']) # all cops in their department listing registry.with_department(current).each do |cop| expect(slice.any? { |l| l.include? cop.cop_name }).to be_truthy end # no cop in wrong department listing departments.each do |department| registry.with_department(department).each do |cop| expect(slice.any? { |l| l.include? cop.cop_name }).to be_falsey end end end end include_examples :prints_config end context 'with one cop given' do let(:arguments) { ['Layout/Tab'] } it 'prints that cop and nothing else' do expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', ' Description: No hard tabs.', /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true', ' IndentationWidth:'].join("\n") ) end include_examples :prints_config end context 'with two cops given' do let(:arguments) { ['Layout/Tab,Metrics/LineLength'] } include_examples :prints_config end context 'with one of the cops misspelled' do let(:arguments) { ['Layout/Tab,Lint/X123'] } it 'skips the unknown cop' do expect(stdout).to match( ['# Supports --auto-correct', 'Layout/Tab:', ' Description: No hard tabs.', /^ StyleGuide: ('|")#spaces-indentation('|")$/, ' Enabled: true'].join("\n") ) end end context 'with --force-default-config' do let(:arguments) { ['Metrics/LineLength', '--force-default-config'] } it 'prioritizes default config' do expect(YAML.safe_load(stdout)['Metrics/LineLength']['Max']).to eq(80) end end end describe '-f/--format' do let(:target_file) { 'example.rb' } before do create_file(target_file, '#' * 90) end describe 'builtin formatters' do context 'when simple format is specified' do it 'outputs with simple format' do cli.run(['--format', 'simple', 'example.rb']) expect($stdout.string) .to include(<<-RESULT.strip_indent) == #{target_file} == C: 1: 81: Metrics/LineLength: Line is too long. [90/80] RESULT end end %w[html json].each do |format| context "when #{format} format is specified" do context 'and offenses come from the cache' do context 'and a message has binary encoding' do let(:message_from_cache) do 'Cyclomatic complexity for 文 is too high. [8/6]' .dup .force_encoding('ASCII-8BIT') end let(:data_from_cache) do [ { 'severity' => 'convention', 'location' => { 'begin_pos' => 18, 'end_pos' => 21 }, 'message' => message_from_cache, 'cop_name' => 'Metrics/CyclomaticComplexity', 'status' => 'unsupported' } ] end it "outputs #{format.upcase} code without crashing" do create_file('example.rb', <<-RUBY.strip_indent) def 文 b if a b if a b if a b if a b if a b if a b if a end RUBY # Stub out the JSON.load call used by the cache mechanism, so # we can test what happens when an offense message has # ASCII-8BIT encoding and contains a non-7bit-ascii character. allow(JSON).to receive(:load).and_return(data_from_cache) 2.times do # The second run (and possibly the first) should hit the # cache. expect(cli.run(['--format', format, '--only', 'Metrics/CyclomaticComplexity'])) .to eq(1) end expect($stderr.string).to eq('') end end end end end context 'when clang format is specified' do it 'outputs with clang format' do create_file('example1.rb', ['x= 0 ', '#' * 85, 'y ', 'puts x']) create_file('example2.rb', <<-RUBY.strip_indent) # frozen_string_literal: true \tx def a puts end RUBY create_file('example3.rb', <<-RUBY.strip_indent) def badName if something test end end RUBY expect(cli.run(['--format', 'clang', 'example1.rb', 'example2.rb', 'example3.rb'])) .to eq(1) expect($stdout.string).to eq([ 'example1.rb:1:2: C: Layout/SpaceAroundOperators: ' \ 'Surrounding space missing for operator =.', 'x= 0 ', ' ^', 'example1.rb:1:5: C: Layout/TrailingWhitespace: ' \ 'Trailing whitespace detected.', 'x= 0 ', ' ^', 'example1.rb:2:81: C: Metrics/LineLength: ' \ 'Line is too long. [85/80]', '###################################################' \ '##################################', ' ' \ ' ^^^^^', 'example1.rb:3:2: C: Layout/TrailingWhitespace: ' \ 'Trailing whitespace detected.', 'y ', ' ^', 'example2.rb:1:1: C: Layout/CommentIndentation: ' \ 'Incorrect indentation detected (column 0 instead of 1).', '# frozen_string_literal: true', '^^^^^^^^^^^^^^^^^^^^^^^^^^^^^', 'example2.rb:3:1: C: Layout/Tab: Tab detected.', "\tx", '^', 'example2.rb:3:2: C: Layout/InitialIndentation: ' \ 'Indentation of first line in file detected.', "\tx", ' ^', 'example2.rb:4:1: C: Layout/IndentationConsistency: ' \ 'Inconsistent indentation detected.', 'def a ...', '^^^^^', 'example2.rb:5:1: C: Layout/IndentationWidth: ' \ 'Use 2 (not 3) spaces for indentation.', ' puts', '^^^', 'example3.rb:1:5: C: Naming/MethodName: ' \ 'Use snake_case for method names.', 'def badName', ' ^^^^^^^', 'example3.rb:2:3: C: Style/GuardClause: ' \ 'Use a guard clause instead of wrapping the code inside a ' \ 'conditional expression.', ' if something', ' ^^', 'example3.rb:2:3: C: Style/IfUnlessModifier: ' \ 'Favor modifier if usage when having a single-line body. ' \ 'Another good alternative is the usage of control flow &&/||.', ' if something', ' ^^', 'example3.rb:4:5: W: Lint/EndAlignment: ' \ 'end at 4, 4 is not aligned with if at 2, 2.', ' end', ' ^^^', '', '3 files inspected, 13 offenses detected', '' ].join("\n")) end end context 'when emacs format is specified' do it 'outputs with emacs format' do create_file('example1.rb', ['# frozen_string_literal: true', '', 'x= 0 ', 'y ', 'puts x']) create_file('example2.rb', <<-RUBY.strip_indent) # frozen_string_literal: true \tx = 0 puts x RUBY expect(cli.run(['--format', 'emacs', 'example1.rb', 'example2.rb'])).to eq(1) expected_output = <<-RESULT.strip_indent #{abs('example1.rb')}:3:2: C: Layout/SpaceAroundOperators: Surrounding space missing for operator `=`. #{abs('example1.rb')}:3:5: C: Layout/TrailingWhitespace: Trailing whitespace detected. #{abs('example1.rb')}:4:2: C: Layout/TrailingWhitespace: Trailing whitespace detected. #{abs('example2.rb')}:1:1: C: Layout/CommentIndentation: Incorrect indentation detected (column 0 instead of 1). #{abs('example2.rb')}:3:1: C: Layout/Tab: Tab detected. #{abs('example2.rb')}:3:2: C: Layout/InitialIndentation: Indentation of first line in file detected. #{abs('example2.rb')}:4:1: C: Layout/IndentationConsistency: Inconsistent indentation detected. RESULT expect($stdout.string).to eq(expected_output) end end context 'when unknown format name is specified' do it 'aborts with error message' do expect(cli.run(['--format', 'unknown', 'example.rb'])).to eq(2) expect($stderr.string) .to include('No formatter for "unknown"') end end context 'when ambiguous format name is specified' do it 'aborts with error message' do # Both 'files' and 'fuubar' start with an 'f'. expect(cli.run(['--format', 'f', 'example.rb'])).to eq(2) expect($stderr.string) .to include('Cannot determine formatter for "f"') end end end describe 'custom formatter' do let(:target_file) { abs('example.rb') } context 'when a class name is specified' do it 'uses the class as a formatter' do module MyTool class RuboCopFormatter < RuboCop::Formatter::BaseFormatter def started(all_files) output.puts "started: #{all_files.join(',')}" end def file_started(file, _options) output.puts "file_started: #{file}" end def file_finished(file, _offenses) output.puts "file_finished: #{file}" end def finished(processed_files) output.puts "finished: #{processed_files.join(',')}" end end end cli.run(['--format', 'MyTool::RuboCopFormatter', 'example.rb']) expect($stdout.string).to eq(<<-RESULT.strip_indent) started: #{target_file} file_started: #{target_file} file_finished: #{target_file} finished: #{target_file} RESULT end end context 'when unknown class name is specified' do it 'aborts with error message' do args = '--format UnknownFormatter example.rb' expect(cli.run(args.split)).to eq(2) expect($stderr.string).to include('UnknownFormatter') end end end it 'can be used multiple times' do cli.run(['--format', 'simple', '--format', 'emacs', 'example.rb']) expect($stdout.string).to include(<<-RESULT.strip_indent) == #{target_file} == C: 1: 81: Metrics/LineLength: Line is too long. [90/80] #{abs(target_file)}:1:81: C: Metrics/LineLength: Line is too long. [90/80] RESULT end end describe '-o/--out option' do let(:target_file) { 'example.rb' } before do create_file(target_file, '#' * 90) end it 'redirects output to the specified file' do cli.run(['--out', 'output.txt', target_file]) expect(File.read('output.txt')).to include('Line is too long.') end it 'is applied to the previously specified formatter' do cli.run(['--format', 'simple', '--format', 'emacs', '--out', 'emacs_output.txt', target_file]) expect($stdout.string).to eq(<<-RESULT.strip_indent) == #{target_file} == C: 1: 81: Metrics/LineLength: Line is too long. [90/80] 1 file inspected, 1 offense detected RESULT expect(File.read('emacs_output.txt')) .to eq(<<-RESULT.strip_indent) #{abs(target_file)}:1:81: C: Metrics/LineLength: Line is too long. [90/80] RESULT end end describe '--fail-level option' do let(:target_file) { 'example.rb' } before do create_file(target_file, <<-RUBY.strip_indent) def f x end RUBY end def expect_offense_detected(num) expect($stderr.string).to eq('') expect($stdout.string) .to include("1 file inspected, #{num} offense detected") end it 'fails when option is less than the severity level' do expect(cli.run(['--fail-level', 'refactor', target_file])).to eq(1) expect(cli.run(['--fail-level', 'autocorrect', target_file])).to eq(1) expect_offense_detected(1) end it 'fails when option is equal to the severity level' do expect(cli.run(['--fail-level', 'convention', target_file])).to eq(1) expect_offense_detected(1) end it 'succeeds when option is greater than the severity level' do expect(cli.run(['--fail-level', 'warning', target_file])).to eq(0) expect_offense_detected(1) end context 'with --auto-correct' do def expect_auto_corrected(num) expect_offense_detected(num) expect($stdout.string.lines.to_a.last) .to eq("1 file inspected, #{num} offense detected, " \ "#{num} offense corrected\n") end it 'fails when option is autocorrect and all offenses are ' \ 'autocorrected' do expect(cli.run(['--auto-correct', '--format', 'simple', '--fail-level', 'autocorrect', target_file])).to eq(1) expect_auto_corrected(1) end it 'fails when option is A and all offenses are autocorrected' do expect(cli.run(['--auto-correct', '--format', 'simple', '--fail-level', 'A', target_file])).to eq(1) expect_auto_corrected(1) end it 'succeeds when option is not given and all offenses are ' \ 'autocorrected' do expect(cli.run(['--auto-correct', '--format', 'simple', target_file])).to eq(0) expect_auto_corrected(1) end it 'succeeds when option is refactor and all offenses are ' \ 'autocorrected' do expect(cli.run(['--auto-correct', '--format', 'simple', '--fail-level', 'refactor', target_file])).to eq(0) expect_auto_corrected(1) end end end describe 'with --auto-correct and disabled offense' do let(:target_file) { 'example.rb' } it 'succeeds when there is only a disabled offense' do create_file(target_file, <<-RUBY.strip_indent) def f x # rubocop:disable Layout/IndentationWidth end RUBY expect(cli.run(['--auto-correct', '--format', 'simple', '--fail-level', 'autocorrect', target_file])).to eq(0) expect($stdout.string.lines.to_a.last) .to eq('1 file inspected, no offenses detected' \ "\n") end end describe '--force-exclusion' do context 'when explicitly excluded' do let(:target_file) { 'example.rb' } before do create_file(target_file, '#' * 90) create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - #{target_file} YAML end it 'excludes files specified in the configuration Exclude ' \ 'even if they are explicitly passed as arguments' do expect(cli.run(['--force-exclusion', target_file])).to eq(0) end end context 'with already excluded by default' do let(:target_file) { 'TODO.md' } before do create_file(target_file, '- one') end it 'excludes files excluded by default even if they are ' \ 'explicitly passed as arguments' do expect(cli.run(['--force-exclusion', target_file])).to eq(0) end end end describe '--stdin' do it 'causes source code to be read from stdin' do begin $stdin = StringIO.new('p $/') argv = ['--only=Style/SpecialGlobalVars', '--format=simple', '--stdin', 'fake.rb'] expect(cli.run(argv)).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == fake.rb == C: 1: 3: Style/SpecialGlobalVars: Prefer $INPUT_RECORD_SEPARATOR or $RS from the stdlib 'English' module (don't forget to require it) over $/. 1 file inspected, 1 offense detected RESULT ensure $stdin = STDIN end end it 'requires a file path' do begin $stdin = StringIO.new('p $/') argv = ['--only=Style/SpecialGlobalVars', '--format=simple', '--stdin'] expect(cli.run(argv)).to eq(2) expect($stderr.string).to include('missing argument: --stdin') ensure $stdin = STDIN end end it 'does not accept more than one file path' do begin $stdin = StringIO.new('p $/') argv = ['--only=Style/SpecialGlobalVars', '--format=simple', '--stdin', 'fake1.rb', 'fake2.rb'] expect(cli.run(argv)).to eq(2) expect($stderr.string).to include( '-s/--stdin requires exactly one path.' ) ensure $stdin = STDIN end end it 'prints corrected code to stdout if --autocorrect is used' do begin $stdin = StringIO.new('p $/') argv = ['--auto-correct', '--only=Style/SpecialGlobalVars', '--format=simple', '--stdin', 'fake.rb'] expect(cli.run(argv)).to eq(0) expect($stdout.string).to eq(<<-RESULT.strip_indent.chomp) == fake.rb == C: 1: 3: [Corrected] Style/SpecialGlobalVars: Prefer $INPUT_RECORD_SEPARATOR or $RS from the stdlib 'English' module (don't forget to require it) over $/. 1 file inspected, 1 offense detected, 1 offense corrected ==================== p $INPUT_RECORD_SEPARATOR RESULT ensure $stdin = STDIN end end it 'detects CR at end of line' do begin create_file('example.rb', "puts 'hello world'\r") # Make Style/EndOfLine give same output regardless of platform. create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/EndOfLine: EnforcedStyle: lf YAML File.open('example.rb') do |file| # We must use a File object to simulate the behavior of # STDIN, which is an IO object. StringIO won't do in this # case, as its read() method doesn't handle line endings the # same way IO#read() does. $stdin = file argv = ['--only=Layout/EndOfLine', '--format=simple', '--stdin', 'fake.rb'] expect(cli.run(argv)).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == fake.rb == C: 1: 1: Layout/EndOfLine: Carriage return character detected. 1 file inspected, 1 offense detected RESULT end ensure $stdin = STDIN end end end end rubocop-0.52.1/spec/rubocop/cli_spec.rb000066400000000000000000001564771322072016200200000ustar00rootroot00000000000000# frozen_string_literal: true require 'timeout' RSpec.describe RuboCop::CLI, :isolated_environment do include_context 'cli spec behavior' subject(:cli) { described_class.new } context 'when interrupted' do it 'returns 1' do allow_any_instance_of(RuboCop::Runner) .to receive(:aborting?).and_return(true) create_file('example.rb', '# encoding: utf-8') expect(cli.run(['example.rb'])).to eq(1) end end describe '#trap_interrupt' do let(:runner) { RuboCop::Runner.new({}, RuboCop::ConfigStore.new) } let(:interrupt_handlers) { [] } before do allow(Signal).to receive(:trap).with('INT') do |&block| interrupt_handlers << block end end def interrupt interrupt_handlers.each(&:call) end it 'adds a handler for SIGINT' do expect(interrupt_handlers.empty?).to be(true) cli.trap_interrupt(runner) expect(interrupt_handlers.size).to eq(1) end context 'with SIGINT once' do it 'aborts processing' do cli.trap_interrupt(runner) expect(runner).to receive(:abort) interrupt end it 'does not exit immediately' do cli.trap_interrupt(runner) expect_any_instance_of(Object).not_to receive(:exit) expect_any_instance_of(Object).not_to receive(:exit!) interrupt end end context 'with SIGINT twice' do it 'exits immediately' do cli.trap_interrupt(runner) expect_any_instance_of(Object).to receive(:exit!).with(1) interrupt interrupt end end end context 'when given a file/directory that is not under the current dir' do shared_examples 'checks Rakefile' do it 'checks a Rakefile but Style/FileName does not report' do create_file('Rakefile', 'x = 1') create_file('other/empty', '') Dir.chdir('other') do expect(cli.run(['--format', 'simple', checked_path])).to eq(1) end expect($stdout.string) .to eq(<<-RESULT.strip_indent) == #{abs('Rakefile')} == W: 1: 1: Lint/UselessAssignment: Useless assignment to variable - x. 1 file inspected, 1 offense detected RESULT end end context 'and the directory is absolute' do let(:checked_path) { abs('..') } include_examples 'checks Rakefile' end context 'and the directory is relative' do let(:checked_path) { '..' } include_examples 'checks Rakefile' end context 'and the Rakefile path is absolute' do let(:checked_path) { abs('../Rakefile') } include_examples 'checks Rakefile' end context 'and the Rakefile path is relative' do let(:checked_path) { '../Rakefile' } include_examples 'checks Rakefile' end end context 'when lines end with CR+LF' do it 'reports an offense' do create_file('example.rb', <<-RUBY.strip_indent) x = 0\r puts x\r RUBY # Make Style/EndOfLine give same output regardless of platform. create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/EndOfLine: EnforcedStyle: lf YAML result = cli.run(['--format', 'simple', 'example.rb']) expect(result).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 1: Layout/EndOfLine: Carriage return character detected. 1 file inspected, 1 offense detected RESULT end end context 'when checking a correct file' do it 'returns 0' do create_file('example.rb', ['x = 0', 'puts x']) expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(0) expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 file inspected, no offenses detected RESULT end context 'when super is used with a block' do it 'still returns 0' do create_file('example.rb', <<-RUBY.strip_indent) # frozen_string_literal: true # this is a class class Thing def super_with_block super { |response| } end def and_with_args super(arg1, arg2) { |response| } end end RUBY create_file('.rubocop.yml', <<-YAML.strip_indent) Lint/UnusedBlockArgument: IgnoreEmptyBlocks: true YAML expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(0) expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 file inspected, no offenses detected RESULT end end end it 'checks a given file with faults and returns 1' do create_file('example.rb', ['x = 0 ', 'puts x']) expect(cli.run(['--format', 'simple', 'example.rb'])).to eq(1) expect($stdout.string) .to eq <<-RESULT.strip_indent == example.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end it 'registers an offense for a syntax error' do create_file('example.rb', ['class Test', 'en']) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(["#{abs('example.rb')}:3:1: E: Lint/Syntax: unexpected " \ 'token $end (Using Ruby 2.1 parser; configure using ' \ '`TargetRubyVersion` parameter, under `AllCops`)', ''].join("\n")) end it 'registers an offense for Parser warnings' do create_file('example.rb', ['puts *test', 'if a then b else c end']) aggregate_failures('CLI output') do expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(["#{abs('example.rb')}:1:6: W: Lint/AmbiguousOperator: " \ 'Ambiguous splat operator. Parenthesize the method arguments ' \ "if it's surely a splat operator, or add a whitespace to the " \ 'right of the `*` if it should be a multiplication.', "#{abs('example.rb')}:2:1: C: Style/OneLineConditional: " \ 'Favor the ternary operator (`?:`) over `if/then/else/end` ' \ 'constructs.', ''].join("\n")) end end it 'can process a file with an invalid UTF-8 byte sequence' do create_file('example.rb', ["# #{'f9'.hex.chr}#{'29'.hex.chr}"]) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:1:1: F: Lint/Syntax: Invalid byte sequence in utf-8. RESULT end context 'when errors are raised while processing files due to bugs' do let(:errors) do ['An error occurred while Encoding cop was inspecting file.rb.'] end before do allow_any_instance_of(RuboCop::Runner) .to receive(:errors).and_return(errors) end it 'displays an error message to stderr' do cli.run([]) expect($stderr.string) .to include('1 error occurred:').and include(errors.first) end end describe 'rubocop:disable comment' do it 'can disable all cops in a code section' do src = ['# rubocop:disable all', '#' * 90, 'x(123456)', 'y("123")', 'def func', ' # rubocop: enable Metrics/LineLength,Style/StringLiterals', ' ' + '#' * 93, ' x(123456)', ' y("123")', 'end'] create_file('example.rb', src) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) # all cops were disabled, then 2 were enabled again, so we # should get 2 offenses reported. expect($stdout.string).to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:7:81: C: Metrics/LineLength: Line is too long. [95/80] #{abs('example.rb')}:9:5: C: Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. RESULT end context 'when --auto-correct is given' do it 'does not trigger UnneededDisable due to lines moving around' do src = ['a = 1 # rubocop:disable Lint/UselessAssignment'] create_file('example.rb', src) create_file('.rubocop.yml', <<-YAML.strip_indent) Style/FrozenStringLiteralComment: Enabled: true EnforcedStyle: always YAML expect(cli.run(['--format', 'offenses', '-a', 'example.rb'])).to eq(0) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Layout/EmptyLineAfterMagicComment 1 Style/FrozenStringLiteralComment -- 2 Total RESULT expect(IO.read('example.rb')) .to eq(<<-RUBY.strip_indent) # frozen_string_literal: true a = 1 # rubocop:disable Lint/UselessAssignment RUBY end end it 'can disable selected cops in a code section' do create_file('example.rb', ['# rubocop:disable Style/LineLength,' \ 'Style/NumericLiterals,Style/StringLiterals', '#' * 90, 'x(123456)', 'y("123")', 'def func', ' # rubocop: enable Metrics/LineLength, ' \ 'Style/StringLiterals', ' ' + '#' * 93, ' x(123456)', ' y("123")', ' # rubocop: enable Style/NumericLiterals', 'end']) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stderr.string) .to eq(['example.rb: Style/LineLength has the wrong ' \ 'namespace - should be Metrics', ''].join("\n")) # 3 cops were disabled, then 2 were enabled again, so we # should get 2 offenses reported. expect($stdout.string).to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:7:81: C: Metrics/LineLength: Line is too long. [95/80] #{abs('example.rb')}:9:5: C: Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. RESULT end it 'can disable all cops on a single line' do create_file('example.rb', 'y("123", 123456) # rubocop:disable all') expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0) expect($stdout.string.empty?).to be(true) end it 'can disable selected cops on a single line' do create_file('example.rb', ['a' * 90 + ' # rubocop:disable Metrics/LineLength', '#' * 95, 'y("123", 123456) # rubocop:disable Style/StringLiterals,' \ 'Style/NumericLiterals']) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:2:81: C: Metrics/LineLength: Line is too long. [95/80] RESULT end context 'without using namespace' do it 'can disable selected cops on a single line' do create_file('example.rb', ['a' * 90 + ' # rubocop:disable LineLength', '#' * 95, 'y("123") # rubocop:disable StringLiterals']) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:2:81: C: Metrics/LineLength: Line is too long. [95/80] RESULT end end context 'when not necessary' do it 'causes an offense to be reported' do create_file('example.rb', ['#' * 95, '# rubocop:disable all', 'a' * 10 + ' # rubocop:disable LineLength,ClassLength', 'y(123) # rubocop:disable all', '# rubocop:enable all']) expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:1:81: C: Metrics/LineLength: Line is too long. [95/80] #{abs('example.rb')}:2:1: W: Lint/UnneededDisable: Unnecessary disabling of all cops. #{abs('example.rb')}:3:12: W: Lint/UnneededDisable: Unnecessary disabling of `Metrics/ClassLength`, `Metrics/LineLength`. #{abs('example.rb')}:4:8: W: Lint/UnneededDisable: Unnecessary disabling of all cops. RESULT end context 'and there are no other offenses' do it 'exits with error code' do create_file('example.rb', 'a' * 10 + ' # rubocop:disable LineLength') expect(cli.run(['example.rb'])).to eq(1) end end shared_examples 'UnneededDisable not run' do |state, config| context "and UnneededDisable is #{state}" do it 'does not report UnneededDisable offenses' do create_file('example.rb', ['#' * 95, '# rubocop:disable all', 'a' * 10 + ' # rubocop:disable LineLength,ClassLength', 'y(123) # rubocop:disable all']) create_file('.rubocop.yml', config) expect(cli.run(['--format', 'emacs'])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string) .to eq(<<-RESULT.strip_indent) #{abs('example.rb')}:1:81: C: Metrics/LineLength: Line is too long. [95/80] RESULT end end end include_examples 'UnneededDisable not run', 'individually disabled', <<-YAML.strip_indent Lint/UnneededDisable: Enabled: false YAML include_examples 'UnneededDisable not run', 'individually excluded', <<-YAML.strip_indent Lint/UnneededDisable: Exclude: - example.rb YAML include_examples 'UnneededDisable not run', 'disabled through department', <<-YAML.strip_indent Lint: Enabled: false YAML end end it 'finds a file with no .rb extension but has a shebang line' do allow_any_instance_of(File::Stat) .to receive(:executable?).and_return(true) create_file('example', ['#!/usr/bin/env ruby', 'x = 0', 'puts x']) expect(cli.run(%w[--format simple])).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end it 'does not register any offenses for an empty file' do create_file('example.rb', '') expect(cli.run(%w[--format simple])).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end describe 'style guide only usage' do context 'via the cli option' do describe '--only-guide-cops' do it 'skips cops that have no link to a style guide' do create_file('example.rb', 'raise') create_file('.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true StyleGuide: ~ Max: 2 YAML expect(cli.run(['--format', 'simple', '--only-guide-cops', 'example.rb'])).to eq(0) end it 'runs cops for rules that link to a style guide' do create_file('example.rb', 'raise') create_file('.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true StyleGuide: "http://an.example/url" Max: 2 YAML expect(cli.run(['--format', 'simple', '--only-guide-cops', 'example.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 3: Metrics/LineLength: Line is too long. [5/2] 1 file inspected, 1 offense detected RESULT end it 'overrides configuration of AllCops/StyleGuideCopsOnly' do create_file('example.rb', 'raise') create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: StyleGuideCopsOnly: false Metrics/LineLength: Enabled: true StyleGuide: ~ Max: 2 YAML expect(cli.run(['--format', 'simple', '--only-guide-cops', 'example.rb'])).to eq(0) end end end context 'via the config' do before do create_file('example.rb', 'do_something or raise') create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: StyleGuideCopsOnly: #{guide_cops_only} DisabledByDefault: #{disabled_by_default} Metrics/LineLength: Enabled: true StyleGuide: ~ Max: 2 YAML end describe 'AllCops/StyleGuideCopsOnly' do let(:disabled_by_default) { 'false' } context 'when it is true' do let(:guide_cops_only) { 'true' } it 'skips cops that have no link to a style guide' do expect(cli.run(['--format', 'offenses', 'example.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Style/AndOr -- 1 Total RESULT end end context 'when it is false' do let(:guide_cops_only) { 'false' } it 'runs cops for rules regardless of any link to the style guide' do expect(cli.run(['--format', 'offenses', 'example.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Metrics/LineLength 1 Style/AndOr -- 2 Total RESULT end end end describe 'AllCops/DisabledByDefault' do let(:guide_cops_only) { 'false' } context 'when it is true' do let(:disabled_by_default) { 'true' } it 'runs only the cop configured in .rubocop.yml' do expect(cli.run(['--format', 'offenses', 'example.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Metrics/LineLength -- 1 Total RESULT end end context 'when it is false' do let(:disabled_by_default) { 'false' } it 'runs all cops that are enabled in default configuration' do expect(cli.run(['--format', 'offenses', 'example.rb'])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) 1 Metrics/LineLength 1 Style/AndOr -- 2 Total RESULT end end end end end describe 'rails cops' do before do RuboCop::ConfigLoader.default_configuration = nil end describe 'enabling/disabling' do it 'by default does not run rails cops' do create_file('app/models/example1.rb', 'read_attribute(:test)') expect(cli.run(['--format', 'simple', 'app/models/example1.rb'])) .to eq(0) end it 'with -R given runs rails cops' do create_file('app/models/example1.rb', 'read_attribute(:test)') expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb'])) .to eq(1) expect($stdout.string).to include('Prefer self[:attr]') end it 'with configuration option true in one dir runs rails cops there' do source = 'read_attribute(:test)' create_file('dir1/app/models/example1.rb', source) create_file('dir1/.rubocop.yml', <<-YAML.strip_indent) Rails: Enabled: true Rails/ReadWriteAttribute: Include: - app/models/**/*.rb YAML create_file('dir2/app/models/example2.rb', source) create_file('dir2/.rubocop.yml', <<-YAML.strip_indent) Rails: Enabled: false Rails/ReadWriteAttribute: Include: - app/models/**/*.rb YAML expect(cli.run(%w[--format simple dir1 dir2])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == dir1/app/models/example1.rb == C: 1: 1: Rails/ReadWriteAttribute: Prefer self[:attr] over read_attribute(:attr). 2 files inspected, 1 offense detected RESULT end it 'with configuration option false but -R given runs rails cops' do create_file('app/models/example1.rb', 'read_attribute(:test)') create_file('.rubocop.yml', <<-YAML.strip_indent) Rails: Enabled: false YAML expect(cli.run(['--format', 'simple', '-R', 'app/models/example1.rb'])) .to eq(1) expect($stdout.string).to include('Prefer self[:attr]') end context 'with obsolete RunRailsCops config option' do it 'prints a warning' do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: RunRailsCops: false YAML expect(cli.run([])).to eq(2) expect($stderr.string).to include('obsolete parameter RunRailsCops ' \ '(for AllCops) found') end end end describe 'including/excluding' do it 'honors Exclude settings in .rubocop_todo.yml one level up' do create_file('lib/example.rb', 'puts %x(ls)') create_file('.rubocop.yml', 'inherit_from: .rubocop_todo.yml') create_file('.rubocop_todo.yml', <<-YAML.strip_indent) Style/CommandLiteral: Exclude: - lib/example.rb YAML Dir.chdir('lib') { expect(cli.run([])).to eq(0) } expect($stdout.string).to include('no offenses detected') end it 'includes some directories by default' do source = ['read_attribute(:test)', "default_scope order: 'position'"] # Several rails cops include app/models by default. create_file('dir1/app/models/example1.rb', source) create_file('dir1/app/models/example2.rb', source) # No rails cops include app/views by default. create_file('dir1/app/views/example3.rb', source) # The .rubocop.yml file inherits from default.yml where the Include # config parameter is set for the rails cops. The paths are interpreted # as relative to dir1 because .rubocop.yml is placed there. create_file('dir1/.rubocop.yml', <<-YAML.strip_indent) Rails: Enabled: true Rails/ReadWriteAttribute: Exclude: - "**/example2.rb" YAML # No .rubocop.yml file in dir2 means that the paths from default.yml # are interpreted as relative to the current directory, so they don't # match. create_file('dir2/app/models/example4.rb', source) expect(cli.run(%w[--format simple dir1 dir2])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == dir1/app/models/example1.rb == C: 1: 1: Rails/ReadWriteAttribute: Prefer self[:attr] over read_attribute(:attr). 4 files inspected, 1 offense detected RESULT end end end describe 'cops can exclude files based on config' do it 'ignores excluded files' do create_file('example.rb', 'x = 0') create_file('regexp.rb', 'x = 0') create_file('exclude_glob.rb', ['#!/usr/bin/env ruby', 'x = 0']) create_file('dir/thing.rb', 'x = 0') create_file('.rubocop.yml', <<-'YAML'.strip_indent) Lint/UselessAssignment: Exclude: - example.rb - !ruby/regexp /regexp.rb\z/ - "exclude_*" - "dir/*" YAML allow_any_instance_of(File::Stat) .to receive(:executable?).and_return(true) expect(cli.run(%w[--format simple])).to eq(0) expect($stdout.string) .to eq(['', '4 files inspected, no offenses detected', ''].join("\n")) end end describe 'configuration from file' do before do RuboCop::ConfigLoader.default_configuration = nil end context 'when configured for rails style indentation' do it 'accepts rails style indentation' do create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/IndentationConsistency: EnforcedStyle: rails YAML create_file('example.rb', <<-RUBY.strip_indent) # A feline creature class Cat def meow puts('Meow!') end protected def can_we_be_friends?(another_cat) some_logic(another_cat) end private def meow_at_3am? rand < 0.8 end end RUBY result = cli.run(%w[--format simple]) expect($stderr.string).to eq('') expect(result).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end %w[class module].each do |parent| it "registers offense for normal indentation in #{parent}" do create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/IndentationConsistency: EnforcedStyle: rails YAML create_file('example.rb', <<-RUBY.strip_indent) # A feline creature #{parent} Cat def meow puts('Meow!') end protected def can_we_be_friends?(another_cat) some_logic(another_cat) end private def meow_at_3am? rand < 0.8 end def meow_at_4am? rand < 0.8 end end RUBY result = cli.run(%w[--format simple]) expect($stderr.string).to eq('') expect(result).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 10: 3: Layout/IndentationWidth: Use 2 (not 0) spaces for rails indentation. C: 16: 3: Layout/IndentationWidth: Use 2 (not 0) spaces for rails indentation. 1 file inspected, 2 offenses detected RESULT end end end context 'when obsolete MultiSpaceAllowedForOperators param is used' do it 'displays a warning' do create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/SpaceAroundOperators: MultiSpaceAllowedForOperators: - "=" YAML expect(cli.run([])).to eq(2) expect($stderr.string).to include('obsolete parameter ' \ 'MultiSpaceAllowedForOperators ' \ '(for Layout/SpaceAroundOperators)' \ ' found') end end context 'when MultilineMethodCallIndentation is used with aligned ' \ 'style and IndentationWidth parameter' do it 'fails with an error message' do create_file('example.rb', 'puts 1') create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/MultilineMethodCallIndentation: EnforcedStyle: aligned IndentationWidth: 1 YAML expect(cli.run(['example.rb'])).to eq(2) expect($stderr.string.strip).to eq( 'Error: The `Layout/MultilineMethodCallIndentation` cop only ' \ 'accepts an `IndentationWidth` configuration parameter when ' \ '`EnforcedStyle` is `indented`.' ) end end context 'when MultilineOperationIndentation is used with aligned ' \ 'style and IndentationWidth parameter' do it 'fails with an error message' do create_file('example.rb', 'puts 1') create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/MultilineOperationIndentation: EnforcedStyle: aligned IndentationWidth: 1 YAML expect(cli.run(['example.rb'])).to eq(2) expect($stderr.string.strip).to eq( 'Error: The `Layout/MultilineOperationIndentation` cop only accepts' \ ' an `IndentationWidth` configuration parameter when ' \ '`EnforcedStyle` is `indented`.' ) end end it 'allows the default configuration file as the -c argument' do create_file('example.rb', ['x = 0', 'puts x']) create_file('.rubocop.yml', []) expect(cli.run(%w[--format simple -c .rubocop.yml])).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end context 'when --force-default-config option is specified' do shared_examples 'ignores config file' do it 'ignores config file' do create_file('example.rb', ['x = 0 ', 'puts x']) create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/TrailingWhitespace: Enabled: false YAML expect(cli.run(args)).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end end context 'when no config file specified' do let(:args) { %w[--format simple --force-default-config] } include_examples 'ignores config file' end context 'when config file specified with -c' do let(:args) do %w[--format simple --force-default-config -c .rubocop.yml] end include_examples 'ignores config file' end end it 'displays cop names if DisplayCopNames is false' do source = ['x = 0 ', 'puts x'] create_file('example1.rb', source) # DisplayCopNames: false inherited from config/default.yml create_file('.rubocop.yml', []) create_file('dir/example2.rb', source) create_file('dir/.rubocop.yml', <<-YAML.strip_indent) AllCops: DisplayCopNames: false YAML expect(cli.run(%w[--format simple])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. == dir/example2.rb == C: 1: 6: Trailing whitespace detected. 2 files inspected, 2 offenses detected RESULT end it 'displays style guide URLs if DisplayStyleGuide is true' do source = ['x = 0 ', 'puts x'] create_file('example1.rb', source) # DisplayCopNames: false inherited from config/default.yml create_file('.rubocop.yml', []) create_file('dir/example2.rb', source) create_file('dir/.rubocop.yml', <<-YAML.strip_indent) AllCops: DisplayStyleGuide: true YAML url = 'https://github.com/bbatsov/ruby-style-guide#no-trailing-whitespace' expect(cli.run(%w[--format simple])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. == dir/example2.rb == C: 1: 6: Layout/TrailingWhitespace: Trailing whitespace detected. (#{url}) 2 files inspected, 2 offenses detected RESULT end it 'uses the DefaultFormatter if another formatter is not specified' do source = ['x = 0 ', 'puts x'] create_file('example1.rb', source) create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: DefaultFormatter: offenses YAML expect(cli.run([])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) 1 Layout/TrailingWhitespace -- 1 Total RESULT end it 'finds included files' do create_file('file.rb', 'x=0') # Included by default create_file('example', 'x=0') create_file('regexp', 'x=0') create_file('.dot1/file.rb', 'x=0') # Hidden but explicitly included create_file('.dot2/file.rb', 'x=0') # Hidden, excluded by default create_file('.dot3/file.rake', 'x=0') # Hidden, not included by wildcard create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Include: - example - "**/*.rake" - !ruby/regexp /regexp$/ - .dot1/**/* YAML expect(cli.run(%w[--format files])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string.split($RS).sort).to eq([abs('.dot1/file.rb'), abs('example'), abs('file.rb'), abs('regexp')]) end it 'ignores excluded files' do create_file('example.rb', ['x = 0', 'puts x']) create_file('regexp.rb', ['x = 0', 'puts x']) create_file('exclude_glob.rb', ['#!/usr/bin/env ruby', 'x = 0', 'puts x']) create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - example.rb - !ruby/regexp /regexp.rb$/ - "exclude_*" YAML expect(cli.run(%w[--format simple])).to eq(0) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end it 'only reads configuration in explicitly included hidden directories' do create_file('.hidden/example.rb', 'x=0') # This file contains configuration for an unknown cop. This would cause a # warning to be printed on stderr if the file was read. But it's in a # hidden directory, so it's not read. create_file('.hidden/.rubocop.yml', <<-YAML.strip_indent) SymbolName: Enabled: false YAML create_file('.other/example.rb', 'x=0') # The .other directory is explicitly included, so the configuration file # is read, and modifies the behavior. create_file('.other/.rubocop.yml', <<-YAML.strip_indent) Layout/SpaceAroundOperators: Enabled: false YAML create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Include: - .other/**/* YAML expect(cli.run(%w[--format simple])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string) .to eq(<<-RESULT.strip_indent) == .other/example.rb == W: 1: 1: Lint/UselessAssignment: Useless assignment to variable - x. 1 file inspected, 1 offense detected RESULT end it 'does not consider Include parameters in subdirectories' do create_file('dir/example.ruby3', 'x=0') create_file('dir/.rubocop.yml', <<-YAML.strip_indent) AllCops: Include: - "*.ruby3" YAML expect(cli.run(%w[--format simple])).to eq(0) expect($stderr.string).to eq('') expect($stdout.string) .to eq(<<-RESULT.strip_indent) 0 files inspected, no offenses detected RESULT end it 'matches included/excluded files correctly when . argument is given' do create_file('example.rb', 'x = 0') create_file('special.dsl', 'setup { "stuff" }') create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Include: - "*.dsl" Exclude: - example.rb YAML expect(cli.run(%w[--format simple .])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == special.dsl == C: 1: 9: Style/StringLiterals: Prefer single-quoted strings when you don't need string interpolation or special symbols. 1 file inspected, 1 offense detected RESULT end it 'does not read files in excluded list' do %w[rb.rb non-rb.ext without-ext].each do |filename| create_file("example/ignored/#{filename}", '#' * 90) end create_file('example/.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - ignored/** YAML expect(File).not_to receive(:open).with(%r{/ignored/}) allow(File).to receive(:open).and_call_original expect(cli.run(%w[--format simple example])).to eq(0) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end it 'can be configured with option to disable a certain error' do create_file('example1.rb', 'puts 0 ') create_file('rubocop.yml', <<-YAML.strip_indent) Style/Encoding: Enabled: false Layout/CaseIndentation: Enabled: false YAML expect(cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 7: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end context 'without using namespace' do it 'can be configured with option to disable a certain error' do create_file('example1.rb', 'puts 0 ') create_file('rubocop.yml', <<-YAML.strip_indent) Encoding: Enabled: false CaseIndentation: Enabled: false YAML expect(cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 7: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end end it 'can disable parser-derived offenses with warning severity' do # `-' interpreted as argument prefix create_file('example.rb', 'puts -1') create_file('.rubocop.yml', <<-YAML.strip_indent) Style/Encoding: Enabled: false Lint/AmbiguousOperator: Enabled: false YAML expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(0) end it 'cannot disable Syntax offenses' do create_file('example.rb', 'class Test') create_file('.rubocop.yml', <<-YAML.strip_indent) Style/Encoding: Enabled: false Syntax: Enabled: false YAML expect(cli.run(['--format', 'emacs', 'example.rb'])).to eq(2) expect($stderr.string).to include( 'Error: configuration for Syntax cop found' ) expect($stderr.string).to include( 'It\'s not possible to disable this cop.' ) end it 'can be configured to merge a parameter that is a hash' do create_file('example1.rb', ['puts %w(a b c)', 'puts %q|hi|']) # We want to change the preferred delimiters for word arrays. The other # settings from default.yml are unchanged. create_file('rubocop.yml', <<-YAML.strip_indent) Style/PercentLiteralDelimiters: PreferredDelimiters: '%w': '[]' '%W': '[]' YAML cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb']) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 6: Style/PercentLiteralDelimiters: %w-literals should be delimited by [ and ]. C: 2: 6: Style/PercentLiteralDelimiters: %q-literals should be delimited by ( and ). C: 2: 6: Style/UnneededPercentQ: Use %q only for strings that contain both single quotes and double quotes. 1 file inspected, 3 offenses detected RESULT end it 'can be configured to override a parameter that is a hash in a ' \ 'special case' do create_file('example1.rb', <<-RUBY.strip_indent) arr.select { |e| e > 0 }.collect { |e| e * 2 } a2.find_all { |e| e > 0 } RUBY # We prefer find_all over select. This setting overrides the default # select over find_all. Other preferred methods appearing in the default # config (e.g., map over collect) are kept. create_file('rubocop.yml', <<-YAML.strip_indent) Style/CollectionMethods: PreferredMethods: select: find_all YAML cli.run(['--format', 'simple', '-c', 'rubocop.yml', '--only', 'CollectionMethods', 'example1.rb']) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 5: Style/CollectionMethods: Prefer find_all over select. C: 1: 26: Style/CollectionMethods: Prefer map over collect. 1 file inspected, 2 offenses detected RESULT end it 'works when a cop that others depend on is disabled' do create_file('example1.rb', <<-RUBY.strip_indent) if a b end RUBY create_file('rubocop.yml', <<-YAML.strip_indent) Style/Encoding: Enabled: false Metrics/LineLength: Enabled: false YAML result = cli.run(['--format', 'simple', '-c', 'rubocop.yml', 'example1.rb']) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example1.rb == C: 1: 1: Style/IfUnlessModifier: Favor modifier if usage when having a single-line body. Another good alternative is the usage of control flow &&/||. 1 file inspected, 1 offense detected RESULT expect(result).to eq(1) end it 'can be configured with project config to disable a certain error' do create_file('example_src/example1.rb', 'puts 0 ') create_file('example_src/.rubocop.yml', <<-YAML.strip_indent) Style/Encoding: Enabled: false Layout/CaseIndentation: Enabled: false YAML expect(cli.run(['--format', 'simple', 'example_src/example1.rb'])).to eq(1) expect($stdout.string) .to eq(<<-RESULT.strip_indent) == example_src/example1.rb == C: 1: 7: Layout/TrailingWhitespace: Trailing whitespace detected. 1 file inspected, 1 offense detected RESULT end it 'can use an alternative max line length from a config file' do create_file('example_src/example1.rb', '#' * 90) create_file('example_src/.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Max: 100 YAML expect(cli.run(['--format', 'simple', 'example_src/example1.rb'])).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end it 'can have different config files in different directories' do %w[src lib].each do |dir| create_file("example/#{dir}/example1.rb", '#' * 90) end create_file('example/src/.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Max: 100 YAML expect(cli.run(%w[--format simple example])).to eq(1) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example/lib/example1.rb == C: 1: 81: Metrics/LineLength: Line is too long. [90/80] 2 files inspected, 1 offense detected RESULT end it 'prefers a config file in ancestor directory to another in home' do create_file('example_src/example1.rb', '#' * 90) create_file('example_src/.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Max: 100 YAML create_file("#{Dir.home}/.rubocop.yml", <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Max: 80 YAML expect(cli.run(['--format', 'simple', 'example_src/example1.rb'])).to eq(0) expect($stdout.string) .to eq(['', '1 file inspected, no offenses detected', ''].join("\n")) end it 'can exclude directories relative to .rubocop.yml' do %w[src etc/test etc/spec tmp/test tmp/spec].each do |dir| create_file("example/#{dir}/example1.rb", '#' * 90) end # Hidden subdirectories should also be excluded. create_file('example/etc/.dot/example1.rb', '#' * 90) create_file('example/.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - src/** - etc/**/* - tmp/spec/** YAML expect(cli.run(%w[--format simple example])).to eq(1) expect($stderr.string).to eq('') expect($stdout.string).to eq(<<-RESULT.strip_indent) == example/tmp/test/example1.rb == C: 1: 81: Metrics/LineLength: Line is too long. [90/80] 1 file inspected, 1 offense detected RESULT end it 'can exclude a typical vendor directory' do create_file( 'vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml', <<-YAML.strip_indent AllCops: Exclude: - lib/parser/lexer.rb YAML ) create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb', '#' * 90) create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/**/* YAML cli.run(%w[--format simple]) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end it 'excludes the vendor directory by default' do create_file('vendor/ex.rb', '#' * 90) cli.run(%w[--format simple]) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end # Being immune to bad configuration files in excluded directories has # become important due to a bug in rubygems # (https://github.com/rubygems/rubygems/issues/680) that makes # installations of, for example, rubocop lack their .rubocop.yml in the # root directory. it 'can exclude a vendor directory with an erroneous config file' do create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml', ['inherit_from: non_existent.yml']) create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb', '#' * 90) create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/**/* YAML cli.run(%w[--format simple]) expect($stderr.string).to eq('') expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end # Relative exclude paths in .rubocop.yml files are relative to that file, # but in configuration files with other names they will be relative to # whatever file inherits from them. it 'can exclude a vendor directory indirectly' do create_file( 'vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/.rubocop.yml', <<-YAML.strip_indent AllCops: Exclude: - lib/parser/lexer.rb YAML ) create_file('vendor/bundle/ruby/1.9.1/gems/parser-2.0.0/lib/ex.rb', '#' * 90) create_file('.rubocop.yml', ['inherit_from: config/default.yml']) create_file('config/default.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/**/* YAML cli.run(%w[--format simple]) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end it 'prints a warning for an unrecognized cop name in .rubocop.yml' do create_file('example/example1.rb', '#' * 90) create_file('example/.rubocop.yml', <<-YAML.strip_indent) Style/LyneLenth: Enabled: true Max: 100 YAML expect(cli.run(%w[--format simple example])).to eq(1) expect($stderr.string) .to eq(['Warning: unrecognized cop Style/LyneLenth found in ' \ 'example/.rubocop.yml', ''].join("\n")) end it 'prints a warning for an unrecognized configuration parameter' do create_file('example/example1.rb', '#' * 90) create_file('example/.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Min: 10 YAML expect(cli.run(%w[--format simple example])).to eq(1) expect($stderr.string) .to eq(['Warning: unrecognized parameter Metrics/LineLength:Min ' \ 'found in example/.rubocop.yml', ''].join("\n")) end it 'prints an error message for an unrecognized EnforcedStyle' do create_file('example/example1.rb', 'puts "hello"') create_file('example/.rubocop.yml', <<-YAML.strip_indent) Style/BracesAroundHashParameters: EnforcedStyle: context YAML expect(cli.run(%w[--format simple example])).to eq(2) expect($stderr.string) .to eq(["Error: invalid EnforcedStyle 'context' for " \ 'Style/BracesAroundHashParameters found in ' \ 'example/.rubocop.yml', 'Valid choices are: braces, no_braces, context_dependent', ''].join("\n")) end it 'works when a configuration file passed by -c specifies Exclude ' \ 'with regexp' do create_file('example/example1.rb', '#' * 90) create_file('rubocop.yml', <<-'YAML'.strip_indent) AllCops: Exclude: - !ruby/regexp /example1\.rb$/ YAML cli.run(%w[--format simple -c rubocop.yml]) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end it 'works when a configuration file passed by -c specifies Exclude ' \ 'with strings' do create_file('example/example1.rb', '#' * 90) create_file('rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - example/** YAML cli.run(%w[--format simple -c rubocop.yml]) expect($stdout.string) .to eq(['', '0 files inspected, no offenses detected', ''].join("\n")) end shared_examples 'specified Severity' do |key| it 'works when a configuration file specifies Severity for ' \ "Metrics/ParameterLists and #{key}" do create_file('example/example1.rb', <<-RUBY.strip_indent) def method(a, b, c, d, e, f) end #{'#' * 57} RUBY create_file('rubocop.yml', <<-YAML.strip_indent) #{key}: Severity: error Metrics/ParameterLists: Severity: convention YAML cli.run(%w[--format simple -c rubocop.yml]) expect($stdout.string).to eq(<<-RESULT.strip_indent) == example/example1.rb == C: 1: 11: Metrics/ParameterLists: Avoid parameter lists longer than 5 parameters. [6/5] C: 1: 34: Style/CommentedKeyword: Do not place comments on the same line as the def keyword. E: 1: 81: Metrics/LineLength: Line is too long. [90/80] 1 file inspected, 3 offenses detected RESULT expect($stderr.string).to eq('') end end include_examples 'specified Severity', 'Metrics/LineLength' include_examples 'specified Severity', 'Metrics' it 'fails when a configuration file specifies an invalid Severity' do create_file('example/example1.rb', '#' * 90) create_file('rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Severity: superbad YAML cli.run(%w[--format simple -c rubocop.yml]) expect($stderr.string) .to eq(["Warning: Invalid severity 'superbad'. " \ 'Valid severities are refactor, convention, ' \ 'warning, error, fatal.', ''].join("\n")) end it 'fails when a configuration file has invalid YAML syntax' do create_file('example/.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - **/*_old.rb YAML cli.run(['example']) # MRI and JRuby return slightly different error messages. expect($stderr.string) .to match(%r{^\(\S+example/\.rubocop\.yml\):\ (did\ not\ find\ )? expected\ alphabetic\ or \ numeric\ character}x) end context 'when a file inherits from a higher level' do before do create_file('.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Exclude: - dir/example.rb YAML create_file('dir/.rubocop.yml', 'inherit_from: ../.rubocop.yml') create_file('dir/example.rb', '#' * 90) end it 'inherits relative excludes correctly' do expect(cli.run([])).to eq(0) end end context 'when configuration is taken from $HOME/.rubocop.yml' do before do create_file("#{Dir.home}/.rubocop.yml", <<-YAML.strip_indent) Metrics/LineLength: Exclude: - dir/example.rb YAML create_file('dir/example.rb', '#' * 90) end it 'handles relative excludes correctly when run from project root' do expect(cli.run([])).to eq(0) end end it 'shows an error if the input file cannot be found' do begin cli.run(%w[/tmp/not_a_file]) rescue SystemExit => e expect(e.status).to eq(1) expect(e.message) .to eq 'rubocop: No such file or directory -- /tmp/not_a_file' end end end describe 'configuration of target Ruby versions' do context 'when configured with an unknown version' do it 'fails with an error message' do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: TargetRubyVersion: 2.6 YAML expect(cli.run([])).to eq(2) expect($stderr.string.strip).to match( /\AError: Unknown Ruby version 2.6 found in `TargetRubyVersion`/ ) expect($stderr.string.strip).to match( /Supported versions: 2.1, 2.2, 2.3, 2.4, 2.5/ ) end end context 'when configured with an unsupported ruby' do it 'fails with an error message' do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: TargetRubyVersion: 2.0 YAML expect(cli.run([])).to eq(2) expect($stderr.string.strip).to match( /\AError: Unsupported Ruby version 2.0 found in `TargetRubyVersion`/ ) expect($stderr.string.strip).to match( /2\.0-compatible analysis was dropped after version 0\.50/ ) expect($stderr.string.strip).to match( /Supported versions: 2.1, 2.2, 2.3, 2.4/ ) end end end context 'configuration of `require`' do context 'unknown library is specified' do it 'exits with 2' do create_file('.rubocop.yml', <<-YAML.strip_indent) require: unknownlibrary YAML regexp = if RUBY_ENGINE == 'jruby' /no such file to load -- unknownlibrary/ else /cannot load such file -- unknownlibrary/ end expect(cli.run([])).to eq(2) expect($stderr.string).to match(regexp) end end end describe 'obsolete cops' do context 'when configuration for TrailingComma is given' do it 'fails with an error message' do create_file('example1.rb', "puts 'hello'") create_file('.rubocop.yml', <<-YAML.strip_indent) Style/TrailingComma: Enabled: true YAML expect(cli.run(['example1.rb'])).to eq(2) expect($stderr.string.strip).to eq( ['Error: The `Style/TrailingComma` cop no longer exists. Please ' \ 'use `Style/TrailingCommaInLiteral` and/or ' \ '`Style/TrailingCommaInArguments` instead.', '(obsolete configuration found in .rubocop.yml, ' \ 'please update it)'].join("\n") ) end end end end rubocop-0.52.1/spec/rubocop/comment_config_spec.rb000066400000000000000000000137031322072016200222000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::CommentConfig do subject(:comment_config) { described_class.new(parse_source(source)) } describe '#cop_enabled_at_line?' do let(:source) do [ '# rubocop:disable Metrics/MethodLength with a comment why', 'def some_method', " puts 'foo'", # 3 'end', '# rubocop:enable Metrics/MethodLength', '', '# rubocop:disable all', 'some_method', # 8 '# rubocop:enable all', '', "code = 'This is evil.'", 'eval(code) # rubocop:disable Security/Eval', "puts 'This is not evil.'", # 12 '', 'def some_method', " puts 'Disabling indented single line' # rubocop:disable " \ 'Metrics/LineLength', 'end', '', # 18 'string = < 40..42, 'Lint/RandOne' => 40..43, 'Lint/BlockAlignment' => 41..42 }.each do |cop_name, expected| actual = disabled_lines_of_cop(cop_name) expect(actual & expected.to_a).to eq(expected.to_a) end end it 'supports enabling/disabling cops without a prefix' do flat_map_disabled_lines = disabled_lines_of_cop('Performance/FlatMap') expected = (44..46).to_a expect(flat_map_disabled_lines & expected).to eq(expected) end it 'supports disabling all lines after a directive' do for_disabled_lines = disabled_lines_of_cop('Style/For') expected_part = (27..source.size).to_a expect(for_disabled_lines & expected_part).to eq(expected_part) end it 'just ignores unpaired enabling directives' do void_disabled_lines = disabled_lines_of_cop('Lint/Void') expected_part = (25..source.size).to_a expect((void_disabled_lines & expected_part).empty?).to be(true) end it 'supports disabling single line with a directive at end of line' do eval_disabled_lines = disabled_lines_of_cop('Security/Eval') expect(eval_disabled_lines).to include(12) expect(eval_disabled_lines).not_to include(13) end it 'handles indented single line' do line_length_disabled_lines = disabled_lines_of_cop('Metrics/LineLength') expect(line_length_disabled_lines).to include(16) expect(line_length_disabled_lines).not_to include(18) end it 'does not confuse a comment directive embedded in a string literal ' \ 'with a real comment' do loop_disabled_lines = disabled_lines_of_cop('Loop') expect(loop_disabled_lines).not_to include(20) end it 'supports disabling all cops except Lint/UnneededDisable with ' \ 'keyword all' do expected_part = (7..8).to_a cops = RuboCop::Cop::Cop.all.reject do |klass| klass == RuboCop::Cop::Lint::UnneededDisable end cops.each do |cop| disabled_lines = disabled_lines_of_cop(cop) expect(disabled_lines & expected_part).to eq(expected_part) end end it 'does not confuse a cop name including "all" with all cops' do alias_disabled_lines = disabled_lines_of_cop('Alias') expect(alias_disabled_lines).not_to include(23) end it 'can handle double disable of one cop' do expect(disabled_lines_of_cop('Style/ClassVars')) .to eq([7, 8, 9] + (31..source.size).to_a) end it 'supports disabling cops with multiple uppercase letters' do expect(disabled_lines_of_cop('RSpec/Example')).to include(47) end it 'supports disabling cops with numbers in their name' do expect(disabled_lines_of_cop('Custom2/Number9')).to include(48) end end end rubocop-0.52.1/spec/rubocop/config_loader_spec.rb000066400000000000000000000655361322072016200220170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::ConfigLoader do include FileHelper let(:default_config) { described_class.default_configuration } describe '.configuration_file_for', :isolated_environment do subject(:configuration_file_for) do described_class.configuration_file_for(dir_path) end context 'when no config file exists in ancestor directories' do let(:dir_path) { 'dir' } before { create_file('dir/example.rb', '') } context 'but a config file exists in home directory' do before { create_file('~/.rubocop.yml', '') } it 'returns the path to the file in home directory' do expect(configuration_file_for).to end_with('home/.rubocop.yml') end end context 'and no config file exists in home directory' do it 'falls back to the provided default file' do expect(configuration_file_for).to end_with('config/default.yml') end end context 'and ENV has no `HOME` defined' do before { ENV.delete 'HOME' } it 'falls back to the provided default file' do expect(configuration_file_for).to end_with('config/default.yml') end end end context 'when a config file exists in the parent directory' do let(:dir_path) { 'dir' } before do create_file('dir/example.rb', '') create_file('.rubocop.yml', '') end it 'returns the path to that configuration file' do expect(configuration_file_for).to end_with('work/.rubocop.yml') end end context 'when multiple config files exist in ancestor directories' do let(:dir_path) { 'dir' } before do create_file('dir/example.rb', '') create_file('dir/.rubocop.yml', '') create_file('.rubocop.yml', '') end it 'prefers closer config file' do expect(configuration_file_for).to end_with('dir/.rubocop.yml') end end end describe '.configuration_from_file', :isolated_environment do subject(:configuration_from_file) do described_class.configuration_from_file(file_path) end context 'with any config file' do let(:file_path) { '.rubocop.yml' } before do create_file(file_path, <<-YAML.strip_indent) Style/Encoding: Enabled: false YAML end it 'returns a configuration inheriting from default.yml' do config = default_config['Style/Encoding'].dup config['Enabled'] = false expect(configuration_from_file.to_h) .to eql(default_config.merge('Style/Encoding' => config)) end end context 'when multiple config files exist in ancestor directories' do let(:file_path) { 'dir/.rubocop.yml' } before do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/** YAML create_file(file_path, <<-YAML.strip_indent) AllCops: Exclude: [] YAML end it 'gets AllCops/Exclude from the highest directory level' do excludes = configuration_from_file['AllCops']['Exclude'] expect(excludes).to eq([File.expand_path('vendor/**')]) end end context 'when a parent file specifies DisabledByDefault: true' do let(:file_path) { '.rubocop.yml' } before do create_file('disable.yml', <<-YAML.strip_indent) AllCops: DisabledByDefault: true YAML create_file(file_path, ['inherit_from: disable.yml']) end it 'disables cops by default' do cop_options = configuration_from_file['Style/Alias'] expect(cop_options.fetch('Enabled')).to be(false) end end context 'when a file inherits from a parent file' do let(:file_path) { 'dir/.rubocop.yml' } before do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/** - !ruby/regexp /[A-Z]/ YAML create_file(file_path, ['inherit_from: ../.rubocop.yml']) end it 'gets an absolute AllCops/Exclude' do excludes = configuration_from_file['AllCops']['Exclude'] expect(excludes).to eq([File.expand_path('vendor/**'), /[A-Z]/]) end it 'ignores parent AllCops/Exclude if ignore_parent_exclusion is true' do sub_file_path = 'vendor/.rubocop.yml' create_file(sub_file_path, <<-YAML.strip_indent) AllCops: Exclude: - 'foo' YAML # dup the class so that setting ignore_parent_exclusion doesn't # interfere with other specs config_loader = described_class.dup config_loader.ignore_parent_exclusion = true configuration = config_loader.configuration_from_file(sub_file_path) excludes = configuration['AllCops']['Exclude'] expect(excludes).not_to include(File.expand_path('vendor/**')) expect(excludes).to include(File.expand_path('vendor/foo')) end end context 'when a file inherits from an empty parent file' do let(:file_path) { 'dir/.rubocop.yml' } before do create_file('.rubocop.yml', ['']) create_file(file_path, ['inherit_from: ../.rubocop.yml']) end it 'does not fail to load' do expect { configuration_from_file }.not_to raise_error end end context 'when a file inherits from a sibling file' do let(:file_path) { 'dir/.rubocop.yml' } before do create_file('src/.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - vendor/** YAML create_file(file_path, ['inherit_from: ../src/.rubocop.yml']) end it 'gets an absolute AllCops/Exclude' do excludes = configuration_from_file['AllCops']['Exclude'] expect(excludes).to eq([File.expand_path('src/vendor/**')]) end end context 'when a third party require defines a new gem' do before do allow(RuboCop::Cop::Cop) .to receive(:registry) .and_return( RuboCop::Cop::Registry.new(RuboCop::Cop::Cop.registry.cops) ) create_file('third_party/gem.rb', <<-RUBY.strip_indent) module RuboCop module Cop module Custom class FilePath < Cop end end end end RUBY create_file('.rubocop.yml', <<-YAML.strip_indent) Custom/FilePath: Enabled: false YAML create_file('.rubocop_with_require.yml', <<-YAML.strip_indent) require: ./third_party/gem Custom/FilePath: Enabled: false YAML end it 'does not emit a warning' do aggregate_failures('loads requires before resolving namespace') do expect { described_class.configuration_from_file('.rubocop.yml') } .to output( a_string_including( '.rubocop.yml: Custom/FilePath has the ' \ "wrong namespace - should be Rails\n" ) ).to_stderr expect do described_class.configuration_from_file('.rubocop_with_require.yml') end.not_to output.to_stderr end end end context 'when a file inherits from a parent and grandparent file' do let(:file_path) { 'dir/subdir/.rubocop.yml' } before do create_file('dir/subdir/example.rb', '') create_file('.rubocop.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: false Max: 77 YAML create_file('dir/.rubocop.yml', <<-YAML.strip_indent) inherit_from: ../.rubocop.yml Metrics/MethodLength: Enabled: true CountComments: false Max: 10 YAML create_file(file_path, <<-YAML.strip_indent) inherit_from: ../.rubocop.yml Metrics/LineLength: Enabled: true Metrics/MethodLength: Max: 5 YAML end it 'returns the ancestor configuration plus local overrides' do config = default_config.merge( 'Metrics/LineLength' => { 'Description' => default_config['Metrics/LineLength']['Description'], 'StyleGuide' => '#80-character-limits', 'Enabled' => true, 'Max' => 77, 'AllowHeredoc' => true, 'AllowURI' => true, 'URISchemes' => %w[http https], 'IgnoreCopDirectives' => false, 'IgnoredPatterns' => [] }, 'Metrics/MethodLength' => { 'Description' => default_config['Metrics/MethodLength']['Description'], 'StyleGuide' => '#short-methods', 'Enabled' => true, 'CountComments' => false, 'Max' => 5 } ) expect(configuration_from_file.to_h).to eq(config) end end context 'when a file inherits from two configurations' do let(:file_path) { '.rubocop.yml' } before do create_file('example.rb', '') create_file('normal.yml', <<-YAML.strip_indent) Metrics/MethodLength: Enabled: false CountComments: true Max: 80 YAML create_file('special.yml', <<-YAML.strip_indent) Metrics/MethodLength: Enabled: false Max: 200 YAML create_file(file_path, <<-YAML.strip_indent) inherit_from: - normal.yml - special.yml Metrics/MethodLength: Enabled: true YAML end it 'returns values from the last one when possible' do expected = { 'Enabled' => true, # overridden in .rubocop.yml 'CountComments' => true, # only defined in normal.yml 'Max' => 200 } # special.yml takes precedence expect( configuration_from_file['Metrics/MethodLength'] .to_set.superset?(expected.to_set) ).to be(true) end end context 'when a file inherits and overrides with non-namedspaced cops' do let(:file_path) { '.rubocop.yml' } before do create_file('example.rb', '') create_file('line_length.yml', <<-YAML.strip_indent) LineLength: Max: 120 YAML create_file(file_path, <<-YAML.strip_indent) inherit_from: - line_length.yml LineLength: AllowHeredoc: false YAML end it 'returns includes both of the cop changes' do config = default_config.merge( 'Metrics/LineLength' => { 'Description' => default_config['Metrics/LineLength']['Description'], 'StyleGuide' => '#80-character-limits', 'Enabled' => true, 'Max' => 120, # overridden in line_length.yml 'AllowHeredoc' => false, # overridden in rubocop.yml 'AllowURI' => true, 'URISchemes' => %w[http https], 'IgnoreCopDirectives' => false, 'IgnoredPatterns' => [] } ) expect(configuration_from_file.to_h).to eq(config) end end context 'when a file inherits from an expanded path' do let(:file_path) { '.rubocop.yml' } before do create_file('~/.rubocop.yml', ['']) create_file(file_path, ['inherit_from: ~/.rubocop.yml']) end it 'does not fail to load expanded path' do expect { configuration_from_file }.not_to raise_error end end context 'when a file inherits from an unknown gem' do let(:file_path) { '.rubocop.yml' } before do create_file(file_path, <<-YAML.strip_indent) inherit_gem: not_a_real_gem: config/rubocop.yml YAML end it 'fails to load' do expect { configuration_from_file }.to raise_error(Gem::LoadError) end end context 'when a file inherits from the rubocop gem' do let(:file_path) { '.rubocop.yml' } before do create_file(file_path, <<-YAML.strip_indent) inherit_gem: rubocop: config/default.yml YAML end it 'fails to load' do expect { configuration_from_file }.to raise_error(ArgumentError) end end context 'when a file inherits from a known gem' do let(:file_path) { '.rubocop.yml' } before do create_file('gemone/config/rubocop.yml', <<-YAML.strip_indent) Metrics/MethodLength: Enabled: false Max: 200 CountComments: false YAML create_file('gemtwo/config/default.yml', <<-YAML.strip_indent) Metrics/LineLength: Enabled: true YAML create_file('gemtwo/config/strict.yml', <<-YAML.strip_indent) Metrics/LineLength: Max: 72 AllowHeredoc: false YAML create_file('local.yml', <<-YAML.strip_indent) Metrics/MethodLength: CountComments: true YAML create_file(file_path, <<-YAML.strip_indent) inherit_gem: gemone: config/rubocop.yml gemtwo: - config/default.yml - config/strict.yml inherit_from: local.yml Metrics/MethodLength: Enabled: true Metrics/LineLength: AllowURI: false YAML end it 'returns values from the gem config with local overrides' do gem_class = Struct.new(:gem_dir) %w[gemone gemtwo].each do |gem_name| mock_spec = gem_class.new(gem_name) expect(Gem::Specification).to receive(:find_by_name) .at_least(:once).with(gem_name).and_return(mock_spec) end expected = { 'Enabled' => true, # overridden in .rubocop.yml 'CountComments' => true, # overridden in local.yml 'Max' => 200 } # inherited from somegem expect( configuration_from_file['Metrics/MethodLength'] .to_set.superset?(expected.to_set) ).to be(true) expected = { 'Enabled' => true, # gemtwo/config/default.yml 'Max' => 72, # gemtwo/config/strict.yml 'AllowHeredoc' => false, # gemtwo/config/strict.yml 'AllowURI' => false } # overridden in .rubocop.yml expect( configuration_from_file['Metrics/LineLength'] .to_set.superset?(expected.to_set) ).to be(true) end end context 'when a file inherits from a url' do let(:file_path) { '.rubocop.yml' } let(:cache_file) { '.rubocop-http---example-com-rubocop-yml' } before do stub_request(:get, /example.com/) .to_return(status: 200, body: "Style/Encoding:\n Enabled: true") create_file(file_path, ['inherit_from: http://example.com/rubocop.yml']) end after do File.unlink cache_file if File.exist? cache_file end it 'creates the cached file alongside the owning file' do configuration_from_file expect(File.exist?(cache_file)).to be true end end context 'when a file inherits from a url inheriting from another file' do let(:file_path) { '.robocop.yml' } let(:cache_file) { '.rubocop-http---example-com-rubocop-yml' } let(:cache_file_2) { '.rubocop-http---example-com-inherit-yml' } before do stub_request(:get, %r{example.com/rubocop}) .to_return(status: 200, body: "inherit_from:\n - inherit.yml") stub_request(:get, %r{example.com/inherit}) .to_return(status: 200, body: "Style/Encoding:\n Enabled: true") create_file(file_path, ['inherit_from: http://example.com/rubocop.yml']) end after do [cache_file, cache_file_2].each do |f| File.unlink f if File.exist? f end end it 'downloads the inherited file from the same url and caches it' do configuration_from_file expect(File.exist?(cache_file)).to be true expect(File.exist?(cache_file_2)).to be true end end context 'EnabledByDefault / DisabledByDefault' do def cop_enabled?(cop_class) configuration_from_file.for_cop(cop_class).fetch('Enabled') end let(:file_path) { '.rubocop.yml' } before do create_file(file_path, config) end context 'when DisabledByDefault is true' do let(:config) do <<-YAML.strip_indent AllCops: DisabledByDefault: true Style/Copyright: Exclude: - foo YAML end it 'enables cops that are explicitly in the config file '\ 'even if they are disabled by default' do cop_class = RuboCop::Cop::Style::Copyright expect(cop_enabled?(cop_class)).to be true end it 'disables cops that are normally enabled by default' do cop_class = RuboCop::Cop::Layout::TrailingWhitespace expect(cop_enabled?(cop_class)).to be false end context 'and a department is enabled' do let(:config) do <<-YAML.strip_indent AllCops: DisabledByDefault: true Style: Enabled: true YAML end it 'enables cops in that department' do cop_class = RuboCop::Cop::Style::Alias expect(cop_enabled?(cop_class)).to be true end it 'disables cops in other departments' do cop_class = RuboCop::Cop::Layout::AlignHash expect(cop_enabled?(cop_class)).to be false end it 'keeps cops that are disabled in default configuration disabled' do cop_class = RuboCop::Cop::Style::AutoResourceCleanup expect(cop_enabled?(cop_class)).to be false end end context 'and the Rails department is enabled' do let(:config) do <<-YAML.strip_indent AllCops: DisabledByDefault: true Rails: Enabled: true Rails/ActionFilter: EnforcedStyle: filter YAML end it 'enables explicitly mentioned cops in that department' do cop_class = RuboCop::Cop::Rails::ActionFilter expect(cop_enabled?(cop_class)).to be true end it 'disables unmentioned cops in that department' do cop_class = RuboCop::Cop::Rails::Date expect(cop_enabled?(cop_class)).to be false end end context 'and the Rails department is disabled' do let(:config) do <<-YAML.strip_indent AllCops: DisabledByDefault: true Rails: Enabled: false Rails/ActionFilter: Enabled: true YAML end it 'disables explicitly mentioned cops in that department' do cop_class = RuboCop::Cop::Rails::ActionFilter expect(cop_enabled?(cop_class)).to be false end it 'disables unmentioned cops in that department' do cop_class = RuboCop::Cop::Rails::Date expect(cop_enabled?(cop_class)).to be false end end end context 'when EnabledByDefault is true' do let(:config) do <<-YAML.strip_indent AllCops: EnabledByDefault: true Layout/TrailingWhitespace: Enabled: false YAML end it 'enables cops that are disabled by default' do cop_class = RuboCop::Cop::Layout::FirstMethodArgumentLineBreak expect(cop_enabled?(cop_class)).to be true end it 'respects cops that are disbled in the config' do cop_class = RuboCop::Cop::Layout::TrailingWhitespace expect(cop_enabled?(cop_class)).to be false end end end end describe '.load_file', :isolated_environment do subject(:load_file) do described_class.load_file(configuration_path) end let(:configuration_path) { '.rubocop.yml' } it 'returns a configuration loaded from the passed path' do create_file(configuration_path, <<-YAML.strip_indent) Style/Encoding: Enabled: true YAML configuration = load_file expect(configuration['Style/Encoding']).to eq( 'Enabled' => true ) end it 'fails with a TypeError when loading a malformed configuration file' do create_file(configuration_path, 'This string is not a YAML hash') expect { load_file }.to raise_error( TypeError, /^Malformed configuration in .*\.rubocop\.yml$/ ) end it 'changes target ruby version with a patch to float' do create_file(configuration_path, <<-YAML.strip_indent) AllCops: TargetRubyVersion: 2.3.4 YAML expect(load_file.to_h).to eq('AllCops' => { 'TargetRubyVersion' => 2.3 }) end it 'loads configuration properly when it includes non-ascii characters ' do create_file(configuration_path, <<-YAML.strip_indent) # All these cops of mine are ❤ Style/Encoding: Enabled: false YAML expect(load_file.to_h).to eq('Style/Encoding' => { 'Enabled' => false }) end it 'returns an empty configuration loaded from an empty file' do create_file(configuration_path, '') configuration = load_file expect(configuration.to_h).to eq({}) end context 'when SafeYAML is required' do before do create_file(configuration_path, <<-YAML.strip_indent) Style/WordArray: WordRegex: !ruby/regexp '/\\A[\\p{Word}]+\\z/' YAML end context 'when it is fully required' do it 'de-serializes Regexp class' do in_its_own_process_with('safe_yaml') do configuration = described_class.load_file('.rubocop.yml') word_regexp = configuration['Style/WordArray']['WordRegex'] expect(word_regexp.is_a?(::Regexp)).to be(true) end end end context 'when safe_yaml is required without monkey patching' do it 'de-serializes Regexp class' do in_its_own_process_with('safe_yaml/load') do configuration = described_class.load_file('.rubocop.yml') word_regexp = configuration['Style/WordArray']['WordRegex'] expect(word_regexp.is_a?(::Regexp)).to be(true) end end context 'and SafeYAML.load is private' do # According to issue #2935, SafeYAML.load can be private in some # circumstances. it 'does not raise private method load called for SafeYAML:Module' do in_its_own_process_with('safe_yaml/load') do SafeYAML.send :private_class_method, :load configuration = described_class.load_file('.rubocop.yml') word_regexp = configuration['Style/WordArray']['WordRegex'] expect(word_regexp.is_a?(::Regexp)).to be(true) end end end end end context 'when the file does not exist' do let(:configuration_path) { 'file_that_does_not_exist.yml' } it 'prints a friendly (concise) message to stderr and exits' do expect { load_file }.to( output(/Configuration file not found/).to_stderr.and( raise_error(SystemExit) do |e| expect(e.status).to(eq(Errno::ENOENT::Errno)) end ) ) end end end describe '.merge' do subject(:merge) { described_class.merge(base, derived) } let(:base) do { 'AllCops' => { 'Include' => ['**/*.gemspec', '**/Rakefile'], 'Exclude' => [] } } end let(:derived) do { 'AllCops' => { 'Exclude' => ['example.rb', 'exclude_*'] } } end it 'returns a recursive merge of its two arguments' do expect(merge).to eq('AllCops' => { 'Include' => ['**/*.gemspec', '**/Rakefile'], 'Exclude' => ['example.rb', 'exclude_*'] }) end end describe 'configuration for CharacterLiteral', :isolated_environment do let(:dir_path) { 'test/blargh' } let(:config) do config_path = described_class.configuration_file_for(dir_path) described_class.configuration_from_file(config_path) end context 'when .rubocop.yml inherits from a file with a name starting ' \ 'with .rubocop' do before do create_file('test/.rubocop_rules.yml', <<-YAML.strip_indent) Style/CharacterLiteral: Exclude: - blargh/blah.rb YAML create_file('test/.rubocop.yml', 'inherit_from: .rubocop_rules.yml') end it 'gets an Exclude relative to the inherited file converted to ' \ 'absolute' do expect(config.for_cop(RuboCop::Cop::Style::CharacterLiteral)['Exclude']) .to eq([File.join(Dir.pwd, 'test/blargh/blah.rb')]) end end end describe 'configuration for AssignmentInCondition' do describe 'AllowSafeAssignment' do it 'is enabled by default' do default_config = described_class.default_configuration symbol_name_config = default_config.for_cop('Lint/AssignmentInCondition') expect(symbol_name_config['AllowSafeAssignment']).to be_truthy end end end describe 'when a requirement is defined', :isolated_environment do let(:required_file_path) { './required_file.rb' } before do create_file('.rubocop.yml', ['require:', " - #{required_file_path}"]) create_file(required_file_path, ['class MyClass', 'end']) end it 'requires the passed path' do config_path = described_class.configuration_file_for('.') described_class.configuration_from_file(config_path) expect(defined?(MyClass)).to be_truthy end it 'uses paths relative to the .rubocop.yml, not cwd' do config_path = described_class.configuration_file_for('.') Dir.chdir '..' do described_class.configuration_from_file(config_path) expect(defined?(MyClass)).to be_truthy end end end describe 'when a unqualified requirement is defined', :isolated_environment do let(:required_file_path) { 'required_file' } before do create_file('.rubocop.yml', ['require:', " - #{required_file_path}"]) create_file(required_file_path + '.rb', ['class MyClass', 'end']) end it 'works without a starting .' do config_path = described_class.configuration_file_for('.') $LOAD_PATH.unshift(File.dirname(config_path)) Dir.chdir '..' do described_class.configuration_from_file(config_path) expect(defined?(MyClass)).to be_truthy end end end end rubocop-0.52.1/spec/rubocop/config_spec.rb000066400000000000000000000533131322072016200204570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Config do include FileHelper subject(:configuration) { described_class.new(hash, loaded_path) } let(:hash) { {} } let(:loaded_path) { 'example/.rubocop.yml' } describe '#validate', :isolated_environment do subject(:configuration) do RuboCop::ConfigLoader.load_file(configuration_path) end let(:configuration_path) { '.rubocop.yml' } context 'when the configuration includes any unrecognized cop name' do before do create_file(configuration_path, <<-YAML.strip_indent) LyneLenth: Enabled: true Max: 100 YAML $stderr = StringIO.new end after do $stderr = STDERR end it 'prints a warning message' do configuration # ConfigLoader.load_file will validate config expect($stderr.string).to match(/unrecognized cop LyneLenth/) end end context 'when the configuration includes an empty section' do before do create_file(configuration_path, ['Metrics/LineLength:']) end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, %r{^empty section Metrics/LineLength}) end end context 'when the empty section is AllCops' do before do create_file(configuration_path, ['AllCops:']) end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, /^empty section AllCops/) end end context 'when the configuration is in the base RuboCop config folder' do before do create_file(configuration_path, <<-YAML.strip_indent) InvalidProperty: Enabled: true YAML stub_const('RuboCop::ConfigLoader::RUBOCOP_HOME', rubocop_home_path) end let(:rubocop_home_path) { File.realpath('.') } let(:configuration_path) { 'config/.rubocop.yml' } it 'is not validated' do expect { configuration.validate }.not_to raise_error end end context 'when the configuration includes any unrecognized parameter' do before do create_file(configuration_path, <<-YAML.strip_indent) Metrics/LineLength: Enabled: true Min: 10 YAML $stderr = StringIO.new end after do $stderr = STDERR end it 'prints a warning message' do configuration # ConfigLoader.load_file will validate config expect($stderr.string).to match( %r{unrecognized parameter Metrics/LineLength:Min} ) end end context 'when the configuration includes any common parameter' do # Common parameters are parameters that are not in the default # configuration, but are nonetheless allowed for any cop. before do create_file(configuration_path, <<-YAML.strip_indent) Metrics/ModuleLength: Exclude: - lib/file.rb Include: - lib/file.xyz Severity: warning StyleGuide: https://example.com/some-style.html YAML end it 'does not raise validation error' do expect { configuration.validate }.not_to raise_error end end context 'when the configuration includes a valid EnforcedStyle' do before do create_file(configuration_path, <<-YAML.strip_indent) Style/AndOr: EnforcedStyle: conditionals YAML end it 'does not raise validation error' do expect { configuration.validate }.not_to raise_error end end context 'when the configuration includes an invalid EnforcedStyle' do before do create_file(configuration_path, <<-YAML.strip_indent) Style/AndOr: EnforcedStyle: itisinvalid YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, /itisinvalid/) end end context 'when the configuration includes a valid EnforcedStyle' do before do create_file(configuration_path, <<-YAML.strip_indent) Layout/SpaceAroundBlockParameters: EnforcedStyleInsidePipes: space YAML end it 'does not raise validation error' do expect { configuration.validate }.not_to raise_error end end context 'when the configuration includes an invalid EnforcedStyle' do before do create_file(configuration_path, <<-YAML.strip_indent) Layout/SpaceAroundBlockParameters: EnforcedStyleInsidePipes: itisinvalid YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, /itisinvalid/) end end context 'when the configuration includes an obsolete cop' do before do create_file(configuration_path, <<-YAML.strip_indent) Style/MethodCallParentheses: Enabled: true YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, %r{Style/MethodCallWithoutArgsParentheses}) end end context 'when the configuration includes an obsolete parameter' do before do create_file(configuration_path, <<-YAML.strip_indent) Rails/UniqBeforePluck: EnforcedMode: conservative YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, /EnforcedStyle/) end end shared_examples 'obsolete MaxLineLength parameter' do |cop_name| context "when the configuration includes the obsolete #{cop_name}: " \ 'MaxLineLength parameter' do before do create_file(configuration_path, <<-YAML.strip_indent) #{cop_name}: MaxLineLength: 100 YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error(RuboCop::ValidationError, /`#{cop_name}: MaxLineLength` has been removed./) end end end include_examples 'obsolete MaxLineLength parameter', 'Style/WhileUntilModifier' include_examples 'obsolete MaxLineLength parameter', 'Style/IfUnlessModifier' context 'when the configuration includes obsolete parameters and cops' do before do create_file(configuration_path, <<-YAML.strip_indent) Rails/UniqBeforePluck: EnforcedMode: conservative Style/MethodCallParentheses: Enabled: false Lint/BlockAlignment: AlignWith: either Layout/SpaceBeforeModifierKeyword: Enabled: false YAML end it 'raises validation error' do message_matcher = lambda do |message| message.include?('EnforcedStyle') && message.include?('MethodCallWithoutArgsParentheses') && message.include?('EnforcedStyleAlignWith') && message.include?('Layout/SpaceAroundKeyword') end expect { configuration.validate } .to raise_error(RuboCop::ValidationError, message_matcher) end end context 'when all cops are both Enabled and Disabled by default' do before do create_file(configuration_path, <<-YAML.strip_indent) AllCops: EnabledByDefault: true DisabledByDefault: true YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error( RuboCop::ValidationError, /Cops cannot be both enabled by default and disabled by default/ ) end end context 'when the configuration includes Lint/Syntax cop' do before do # Force reloading default configuration RuboCop::ConfigLoader.default_configuration = nil end context 'when the configuration matches the default' do before do create_file(configuration_path, <<-YAML.strip_indent) Lint/Syntax: Enabled: true YAML end it 'does not raise validation error' do expect { configuration.validate }.not_to raise_error end end context 'when the configuration does not match the default' do before do create_file(configuration_path, <<-YAML.strip_indent) Lint/Syntax: Enabled: false YAML end it 'raises validation error' do expect { configuration.validate } .to raise_error( RuboCop::ValidationError, /configuration for Syntax cop found/ ) end end end end describe '#make_excludes_absolute' do context 'when config is in root directory' do let(:hash) do { 'AllCops' => { 'Exclude' => [ 'config/environment', 'spec' ] } } end before do allow(configuration) .to receive(:base_dir_for_path_parameters) .and_return('/home/foo/project') configuration.make_excludes_absolute end it 'generates valid absolute directory' do excludes = configuration['AllCops']['Exclude'] .map { |e| e.sub(/^[A-Z]:/, '') } expect(excludes) .to eq [ '/home/foo/project/config/environment', '/home/foo/project/spec' ] end end context 'when config is in subdirectory' do let(:hash) do { 'AllCops' => { 'Exclude' => [ '../../config/environment', '../../spec' ] } } end before do allow(configuration) .to receive(:base_dir_for_path_parameters) .and_return('/home/foo/project/config/tools') configuration.make_excludes_absolute end it 'generates valid absolute directory' do excludes = configuration['AllCops']['Exclude'] .map { |e| e.sub(/^[A-Z]:/, '') } expect(excludes) .to eq [ '/home/foo/project/config/environment', '/home/foo/project/spec' ] end end end describe '#file_to_include?' do let(:hash) do { 'AllCops' => { 'Include' => ['**/Gemfile', 'config/unicorn.rb.example'] } } end let(:loaded_path) { '/home/foo/project/.rubocop.yml' } context 'when the passed path matches any of patterns to include' do it 'returns true' do file_path = '/home/foo/project/Gemfile' expect(configuration.file_to_include?(file_path)).to be_truthy end end context 'when the passed path does not match any of patterns to include' do it 'returns false' do file_path = '/home/foo/project/Gemfile.lock' expect(configuration.file_to_include?(file_path)).to be_falsey end end end describe '#file_to_exclude?' do before { $stderr = StringIO.new } after { $stderr = STDERR } let(:hash) do { 'AllCops' => { 'Exclude' => [ "#{Dir.pwd}/log/**/*", '**/bar.rb' ] } } end let(:loaded_path) { '/home/foo/project/.rubocop.yml' } context 'when the passed path matches any of patterns to exclude' do it 'returns true' do file_path = "#{Dir.pwd}/log/foo.rb" expect(configuration.file_to_exclude?(file_path)).to be_truthy expect(configuration.file_to_exclude?('log/foo.rb')).to be_truthy expect(configuration.file_to_exclude?('bar.rb')).to be_truthy end end context 'when the passed path does not match any of patterns to exclude' do it 'returns false' do file_path = "#{Dir.pwd}/log_file.rb" expect(configuration.file_to_exclude?(file_path)).to be_falsey expect(configuration.file_to_exclude?('app/controller.rb')).to be_falsey expect(configuration.file_to_exclude?('baz.rb')).to be_falsey end end end describe '#patterns_to_include' do subject(:patterns_to_include) do configuration = described_class.new(hash, loaded_path) configuration.patterns_to_include end let(:loaded_path) { 'example/.rubocop.yml' } context 'when config file has AllCops => Include key' do let(:hash) do { 'AllCops' => { 'Include' => ['**/Gemfile', 'config/unicorn.rb.example'] } } end it 'returns the Include value' do expect(patterns_to_include).to eq([ '**/Gemfile', 'config/unicorn.rb.example' ]) end end end describe '#possibly_include_hidden?' do subject(:configuration) do described_class.new(hash, loaded_path) end let(:loaded_path) { 'example/.rubocop.yml' } it 'returns true when Include config only includes regular paths' do configuration['AllCops'] = { 'Include' => ['**/Gemfile', 'config/unicorn.rb.example'] } expect(configuration.possibly_include_hidden?).to be(false) end it 'returns true when Include config includes a regex' do configuration['AllCops'] = { 'Include' => [/foo/] } expect(configuration.possibly_include_hidden?).to be(true) end it 'returns true when Include config includes a toplevel dotfile' do configuration['AllCops'] = { 'Include' => ['.foo'] } expect(configuration.possibly_include_hidden?).to be(true) end it 'returns true when Include config includes a dotfile in a path' do configuration['AllCops'] = { 'Include' => ['foo/.bar'] } expect(configuration.possibly_include_hidden?).to be(true) end end describe '#patterns_to_exclude' do subject(:patterns_to_exclude) do configuration = described_class.new(hash, loaded_path) configuration.patterns_to_exclude end let(:loaded_path) { 'example/.rubocop.yml' } context 'when config file has AllCops => Exclude key' do let(:hash) do { 'AllCops' => { 'Exclude' => ['log/*'] } } end it 'returns the Exclude value' do expect(patterns_to_exclude).to eq(['log/*']) end end end describe '#check' do subject(:configuration) do described_class.new(hash, loaded_path) end let(:loaded_path) { 'example/.rubocop.yml' } context 'when a deprecated configuration is detected' do let(:hash) { { 'AllCops' => { 'Includes' => [] } } } before { $stderr = StringIO.new } after { $stderr = STDERR } it 'prints a warning message for the loaded path' do configuration.check expect($stderr.string).to include( "#{loaded_path} - AllCops/Includes was renamed" ) end end end describe '#deprecation_check' do context 'when there is no AllCops configuration' do let(:hash) { {} } it 'does not yield' do expect { |b| configuration.deprecation_check(&b) }.not_to yield_control end end context 'when there is AllCops configuration' do context 'if there are no Excludes or Includes keys' do let(:hash) { { 'AllCops' => { 'Exclude' => [], 'Include' => [] } } } it 'does not yield' do expect do |b| configuration.deprecation_check(&b) end.not_to yield_control end end context 'if there are is an Includes key' do let(:hash) { { 'AllCops' => { 'Includes' => [] } } } it 'yields' do expect do |b| configuration.deprecation_check(&b) end.to yield_with_args(String) end end context 'if there are is an Excludes key' do let(:hash) { { 'AllCops' => { 'Excludes' => [] } } } it 'yields' do expect do |b| configuration.deprecation_check(&b) end.to yield_with_args(String) end end end end context 'whether the cop is enabled' do def cop_enabled(cop_class) configuration.for_cop(cop_class).fetch('Enabled') end context 'when an entire cop department is disabled' do context 'but an individual cop is enabled' do let(:hash) do { 'Layout' => { 'Enabled' => false }, 'Layout/TrailingWhitespace' => { 'Enabled' => true } } end it 'still disables the cop' do cop_class = RuboCop::Cop::Layout::TrailingWhitespace expect(cop_enabled(cop_class)).to be false end end end context 'when an entire cop department is enabled' do context 'but an individual cop is disabled' do let(:hash) do { 'Style' => { 'Enabled' => true }, 'Layout/TrailingWhitespace' => { 'Enabled' => false } } end it 'still disables the cop' do cop_class = RuboCop::Cop::Layout::TrailingWhitespace expect(cop_enabled(cop_class)).to be false end end end context 'when a cop has configuration but no explicit Enabled setting' do let(:hash) do { 'Layout/TrailingWhitespace' => { 'Exclude' => ['foo'] } } end it 'enables the cop by default' do cop_class = RuboCop::Cop::Layout::TrailingWhitespace expect(cop_enabled(cop_class)).to be true end end end describe '#target_rails_version' do context 'when TargetRailsVersion is set' do let(:rails_version) { 4.0 } let(:hash) do { 'AllCops' => { 'TargetRailsVersion' => rails_version } } end it 'uses TargetRailsVersion' do expect(configuration.target_rails_version).to eq rails_version end end context 'when TargetRailsVersion is not set' do let(:hash) do { 'AllCops' => {} } end it 'uses the default rails version' do default_version = RuboCop::Config::DEFAULT_RAILS_VERSION expect(configuration.target_rails_version).to eq default_version end end end describe '#target_ruby_version', :isolated_environment do context 'when TargetRubyVersion is set' do let(:ruby_version) { 2.1 } let(:hash) do { 'AllCops' => { 'TargetRubyVersion' => ruby_version } } end before do allow(File).to receive(:file?).and_call_original end it 'uses TargetRubyVersion' do expect(configuration.target_ruby_version).to eq ruby_version end it 'does not read .ruby-version' do configuration.target_ruby_version expect(File).not_to have_received(:file?).with('.ruby-version') end end context 'when TargetRubyVersion is not set' do context 'when .ruby-version is present' do before do dir = configuration.base_dir_for_path_parameters create_file(File.join(dir, '.ruby-version'), ruby_version) end context 'when .ruby-version contains an MRI version' do let(:ruby_version) { '2.2.4' } let(:ruby_version_to_f) { 2.2 } it 'reads it to determine the target ruby version' do expect(configuration.target_ruby_version).to eq ruby_version_to_f end end context 'when the MRI version contains multiple digits' do let(:ruby_version) { '10.11.0' } let(:ruby_version_to_f) { 10.11 } it 'reads it to determine the target ruby version' do expect(configuration.target_ruby_version).to eq ruby_version_to_f end end context 'when .ruby-version contains a version prefixed by "ruby-"' do let(:ruby_version) { 'ruby-2.3.0' } let(:ruby_version_to_f) { 2.3 } it 'correctly determines the target ruby version' do expect(configuration.target_ruby_version).to eq ruby_version_to_f end end context 'when .ruby-version contains a JRuby version' do let(:ruby_version) { 'jruby-9.1.2.0' } it 'uses the default target ruby version' do expect(configuration.target_ruby_version) .to eq described_class::DEFAULT_RUBY_VERSION end end context 'when .ruby-version contains a Rbx version' do let(:ruby_version) { 'rbx-3.42' } it 'uses the default target ruby version' do expect(configuration.target_ruby_version) .to eq described_class::DEFAULT_RUBY_VERSION end end context 'when .ruby-version contains "system" version' do let(:ruby_version) { 'system' } it 'uses the default target ruby version' do expect(configuration.target_ruby_version) .to eq described_class::DEFAULT_RUBY_VERSION end end end context 'when .ruby-version is not present' do it 'uses the default target ruby version' do expect(configuration.target_ruby_version) .to eq described_class::DEFAULT_RUBY_VERSION end end context 'when .ruby-version is in a parent directory' do before do dir = configuration.base_dir_for_path_parameters create_file(File.join(dir, '..', '.ruby-version'), '2.4.1') end it 'reads it to determine the target ruby version' do expect(configuration.target_ruby_version).to eq 2.4 end end end end end rubocop-0.52.1/spec/rubocop/config_store_spec.rb000066400000000000000000000045211322072016200216700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::ConfigStore do subject(:config_store) { described_class.new } before do allow(RuboCop::ConfigLoader).to receive(:configuration_file_for) do |arg| # File tree: # file1 # dir/.rubocop.yml # dir/file2 # dir/subdir/file3 (arg =~ /dir/ ? 'dir' : '.') + '/.rubocop.yml' end allow(RuboCop::ConfigLoader) .to receive(:configuration_from_file) { |arg| arg } allow(RuboCop::ConfigLoader) .to receive(:load_file) { |arg| RuboCop::Config.new(arg) } allow(RuboCop::ConfigLoader) .to receive(:merge_with_default) { |config| "merged #{config.to_h}" } allow(RuboCop::ConfigLoader) .to receive(:default_configuration).and_return('default config') end describe '.for' do it 'always uses config specified in command line' do config_store.options_config = { options_config: true } expect(config_store.for('file1')).to eq('merged {:options_config=>true}') end context 'when no config specified in command line' do it 'gets config path and config from cache if available' do expect(RuboCop::ConfigLoader) .to receive(:configuration_file_for).once.with('dir') expect(RuboCop::ConfigLoader) .to receive(:configuration_file_for).once.with('dir/subdir') # The stub returns the same config path for dir and dir/subdir. expect(RuboCop::ConfigLoader) .to receive(:configuration_from_file).once.with('dir/.rubocop.yml') config_store.for('dir/file2') config_store.for('dir/file2') config_store.for('dir/subdir/file3') end it 'searches for config path if not available in cache' do expect(RuboCop::ConfigLoader).to receive(:configuration_file_for).once expect(RuboCop::ConfigLoader).to receive(:configuration_from_file).once config_store.for('file1') end context 'when --force-default-config option is specified' do it 'uses default config without searching for config path' do expect(RuboCop::ConfigLoader).not_to receive(:configuration_file_for) expect(RuboCop::ConfigLoader).not_to receive(:configuration_from_file) config_store.force_default_config! expect(config_store.for('file1')).to eq('default config') end end end end end rubocop-0.52.1/spec/rubocop/cop/000077500000000000000000000000001322072016200164275ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/badge_spec.rb000066400000000000000000000026631322072016200210370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Badge do subject(:badge) { described_class.new('Test', 'ModuleMustBeAClassCop') } it 'exposes department name' do expect(badge.department).to be(:Test) end it 'exposes cop name' do expect(badge.cop_name).to eql('ModuleMustBeAClassCop') end describe '.parse' do it 'parses Department/CopName syntax' do expect(described_class.parse('Foo/Bar')) .to eq(described_class.new('Foo', 'Bar')) end it 'parses unqualified badge references' do expect(described_class.parse('Bar')) .to eql(described_class.new(nil, 'Bar')) end end describe '.for' do it 'parses cop class name' do expect(described_class.for('RuboCop::Cop::Foo::Bar')) .to eq(described_class.new('Foo', 'Bar')) end end it 'compares by value' do badge1 = described_class.new('Foo', 'Bar') badge2 = described_class.new('Foo', 'Bar') expect(Set.new([badge1, badge2]).one?).to be(true) end it 'can be converted to a string with the Department/CopName format' do expect(described_class.new('Foo', 'Bar').to_s).to eql('Foo/Bar') end describe '#qualified?' do it 'says `CopName` is not qualified' do expect(described_class.parse('Bar').qualified?).to be(false) end it 'says `Department/CopName` is qualified' do expect(described_class.parse('Department/Bar').qualified?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/bundler/000077500000000000000000000000001322072016200200625ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/bundler/duplicated_gem_spec.rb000066400000000000000000000041601322072016200243700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Bundler::DuplicatedGem, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Include' => ['**/Gemfile'] } } context 'when investigating Ruby files' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) # cop will not read these contents gem('rubocop') gem('rubocop') RUBY end end context 'when investigating Gemfiles' do context 'and the file is empty' do let(:source) { '' } it 'does not raise an error' do expect { inspect_source('gems.rb') }.not_to raise_error end it 'does not register any offenses' do expect(cop.offenses.empty?).to be(true) end end context 'and no duplicate gems are present' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent, 'Gemfile') gem 'rubocop' gem 'flog' RUBY end end context 'and a gem is duplicated in default group' do let(:source) { <<-GEM } source 'https://rubygems.org' gem 'rubocop' gem 'rubocop' GEM it 'registers an offense' do inspect_gemfile(source) expect(cop.offenses.size).to eq(1) end it "references gem's first occurrence in message" do inspect_gemfile(source) expect(cop.offenses.first.message).to include('2') end it 'highlights the duplicate gem' do inspect_gemfile(source) expect(cop.highlights).to eq(["gem 'rubocop'"]) end end context 'and a duplicated gem is in a git/path/group/platforms block' do let(:source) { <<-GEM } gem 'rubocop' group :development do gem 'rubocop', path: '/path/to/gem' end GEM it 'registers an offense' do inspect_gemfile(source) expect(cop.offenses.size).to eq(1) end it 'highlights the duplicate gem' do inspect_gemfile(source) expect(cop.highlights).to eq(["gem 'rubocop', path: '/path/to/gem'"]) end end end end rubocop-0.52.1/spec/rubocop/cop/bundler/insecure_protocol_source_spec.rb000066400000000000000000000032511322072016200265400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Bundler::InsecureProtocolSource do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `source :gemcutter`' do expect_offense(<<-RUBY.strip_indent) source :gemcutter ^^^^^^^^^^ The source `:gemcutter` is deprecated because HTTP requests are insecure. Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. RUBY end it 'registers an offense when using `source :rubygems`' do expect_offense(<<-RUBY.strip_indent) source :rubygems ^^^^^^^^^ The source `:rubygems` is deprecated because HTTP requests are insecure. Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. RUBY end it 'registers an offense when using `source :rubyforge`' do expect_offense(<<-RUBY.strip_indent) source :rubyforge ^^^^^^^^^^ The source `:rubyforge` is deprecated because HTTP requests are insecure. Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not. RUBY end it 'autocorrects `source :gemcutter`' do new_source = autocorrect_source('source :gemcutter') expect(new_source).to eq "source 'https://rubygems.org'" end it 'autocorrects `source :rubygems`' do new_source = autocorrect_source('source :rubygems') expect(new_source).to eq "source 'https://rubygems.org'" end it 'autocorrects `source :rubyforge`' do new_source = autocorrect_source('source :rubyforge') expect(new_source).to eq "source 'https://rubygems.org'" end end rubocop-0.52.1/spec/rubocop/cop/bundler/ordered_gems_spec.rb000066400000000000000000000146741322072016200240740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Bundler::OrderedGems, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'TreatCommentsAsGroupSeparators' => treat_comments_as_group_separators, 'Include' => nil } end let(:treat_comments_as_group_separators) { false } let(:message) do 'Gems should be sorted in an alphabetical order within their ' \ 'section of the Gemfile. Gem `%s` should appear before `%s`.' end context 'When gems are alphabetically sorted' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) gem 'rspec' gem 'rubocop' RUBY end end context 'when a gem is referenced from a variable' do it 'ignores the line' do expect_no_offenses(<<-RUBY.strip_indent) gem 'rspec' gem ENV['env_key_undefined'] if ENV.key?('env_key_undefined') gem 'rubocop' RUBY end it 'resets the sorting to a new block' do expect_no_offenses(<<-RUBY.strip_indent) gem 'rubocop' gem ENV['env_key_undefined'] if ENV.key?('env_key_undefined') gem 'ast' RUBY end end context 'When gems are not alphabetically sorted' do let(:source) { <<-RUBY.strip_indent } gem 'rubocop' gem 'rspec' RUBY it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) gem 'rubocop' gem 'rspec' ^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) gem 'rspec' gem 'rubocop' RUBY end end context 'When each individual group of line is sorted' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) gem 'rspec' gem 'rubocop' gem 'hello' gem 'world' RUBY end end context 'When a gem declaration takes several lines' do let(:source) { <<-RUBY.strip_indent } gem 'rubocop', '0.1.1' gem 'rspec' RUBY it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) gem 'rubocop', '0.1.1' gem 'rspec' ^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) gem 'rspec' gem 'rubocop', '0.1.1' RUBY end end context 'When the gemfile is empty' do it 'does not register any offenses' do expect_no_offenses('# Gemfile') end end context 'When each individual group of line is not sorted' do let(:source) { <<-RUBY.strip_indent } gem "d" gem "b" gem "e" gem "a" gem "c" gem "h" gem "g" gem "j" gem "f" gem "i" RUBY it 'registers some offenses' do expect_offense(<<-RUBY.strip_indent) gem "d" gem "b" ^^^^^^^ #{format(message, 'b', 'd')} gem "e" gem "a" ^^^^^^^ #{format(message, 'a', 'e')} gem "c" gem "h" gem "g" ^^^^^^^ #{format(message, 'g', 'h')} gem "j" gem "f" ^^^^^^^ #{format(message, 'f', 'j')} gem "i" RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) gem "a" gem "b" gem "c" gem "d" gem "e" gem "f" gem "g" gem "h" gem "i" gem "j" RUBY end end context 'When gem groups is separated by multiline comment' do let(:source) { <<-RUBY.strip_indent } # For code quality gem 'rubocop' # For # test gem 'rspec' RUBY context 'with TreatCommentsAsGroupSeparators: true' do let(:treat_comments_as_group_separators) { true } it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) # For code quality gem 'rubocop' # For # test gem 'rspec' RUBY end end context 'with TreatCommentsAsGroupSeparators: false' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # For code quality gem 'rubocop' # For # test gem 'rspec' ^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) # For # test gem 'rspec' # For code quality gem 'rubocop' RUBY end end end context 'When gems have an inline comment, and not sorted' do let(:source) { <<-RUBY.strip_indent } gem 'rubocop' # For code quality gem 'pry' gem 'rspec' # For test RUBY it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) gem 'rubocop' # For code quality gem 'pry' ^^^^^^^^^ #{format(message, 'pry', 'rubocop')} gem 'rspec' # For test RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) gem 'pry' gem 'rspec' # For test gem 'rubocop' # For code quality RUBY end end context 'When gems are asciibetically sorted' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) gem 'paper_trail' gem 'paperclip' RUBY end end context 'When a gem that starts with a capital letter is sorted' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) gem 'a' gem 'Z' RUBY end end context 'When a gem that starts with a capital letter is not sorted' do let(:source) { <<-RUBY.strip_indent } gem 'Z' gem 'a' RUBY it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) gem 'Z' gem 'a' ^^^^^^^ #{format(message, 'a', 'Z')} RUBY end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) gem 'a' gem 'Z' RUBY end end end rubocop-0.52.1/spec/rubocop/cop/commissioner_spec.rb000066400000000000000000000056141322072016200225030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Commissioner do describe '#investigate' do let(:cop) do double(RuboCop::Cop, offenses: [], excluded_file?: false).as_null_object end let(:force) { double(RuboCop::Cop::Force).as_null_object } it 'returns all offenses found by the cops' do allow(cop).to receive(:offenses).and_return([1]) commissioner = described_class.new([cop], []) source = [] processed_source = parse_source(source) expect(commissioner.investigate(processed_source)).to eq [1] end context 'when a cop has no interest in the file' do it 'returns all offenses except the ones of the cop' do cops = [] cops << double('cop A', offenses: %w[foo], excluded_file?: false) cops << double('cop B', excluded_file?: true) cops << double('cop C', offenses: %w[baz], excluded_file?: false) cops.each(&:as_null_object) commissioner = described_class.new(cops, []) source = [] processed_source = parse_source(source) expect(commissioner.investigate(processed_source)).to eq %w[foo baz] end end it 'traverses the AST and invoke cops specific callbacks' do expect(cop).to receive(:on_def) commissioner = described_class.new([cop], []) source = ['def method', '1', 'end'] processed_source = parse_source(source) commissioner.investigate(processed_source) end it 'passes the input params to all cops/forces that implement their own' \ ' #investigate method' do source = [] processed_source = parse_source(source) expect(cop).to receive(:investigate).with(processed_source) expect(force).to receive(:investigate).with(processed_source) commissioner = described_class.new([cop], [force]) commissioner.investigate(processed_source) end it 'stores all errors raised by the cops' do allow(cop).to receive(:on_int) { raise RuntimeError } commissioner = described_class.new([cop], []) source = ['def method', '1', 'end'] processed_source = parse_source(source) commissioner.investigate(processed_source) expect(commissioner.errors[cop].size).to eq(1) expect( commissioner.errors[cop][0].error.instance_of?(RuntimeError) ).to be(true) expect(commissioner.errors[cop][0].line).to eq 2 expect(commissioner.errors[cop][0].column).to eq 0 end context 'when passed :raise_error option' do it 're-raises the exception received while processing' do allow(cop).to receive(:on_int) { raise RuntimeError } commissioner = described_class.new([cop], [], raise_error: true) source = ['def method', '1', 'end'] processed_source = parse_source(source) expect do commissioner.investigate(processed_source) end.to raise_error(RuntimeError) end end end end rubocop-0.52.1/spec/rubocop/cop/cop_spec.rb000066400000000000000000000167641322072016200205650ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Cop do subject(:cop) { described_class.new } let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end it 'initially has 0 offenses' do expect(cop.offenses.empty?).to be(true) end describe '.qualified_cop_name' do before do $stderr = StringIO.new end after do $stderr = STDERR end it 'adds namespace if the cop name is found in exactly one namespace' do expect(described_class.qualified_cop_name('LineLength', '--only')) .to eq('Metrics/LineLength') end it 'returns the given cop name if it is not found in any namespace' do expect(described_class.qualified_cop_name('UnknownCop', '--only')) .to eq('UnknownCop') end it 'returns the given cop name if it already has a namespace' do expect(described_class.qualified_cop_name('Metrics/LineLength', '--only')) .to eq('Metrics/LineLength') end it 'returns the cop name in a different namespace if the provided ' \ 'namespace is incorrect' do expect(described_class.qualified_cop_name('Style/LineLength', '--only')) .to eq('Metrics/LineLength') end it 'raises an error if the cop name is in more than one namespace' do expect { described_class.qualified_cop_name('SafeNavigation', '--only') } .to raise_error(RuboCop::Cop::AmbiguousCopName) end it 'returns the given cop name if it already has a namespace even when ' \ 'the cop exists in multiple namespaces' do qualified_cop_name = described_class.qualified_cop_name('Style/SafeNavigation', '--only') expect(qualified_cop_name).to eq('Style/SafeNavigation') end end it 'keeps track of offenses' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.size).to eq(1) end it 'will report registered offenses' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.empty?).to be(false) end it 'will set default severity' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.severity).to eq(:convention) end it 'will set custom severity if present' do cop.config[cop.name] = { 'Severity' => 'warning' } cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.severity).to eq(:warning) end it 'will warn if custom severity is invalid' do cop.config[cop.name] = { 'Severity' => 'superbad' } expect(cop).to receive(:warn) cop.add_offense(nil, location: location, message: 'message') end it 'registers offense with its name' do cop = RuboCop::Cop::Style::For.new cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.cop_name).to eq('Style/For') end describe 'setting of Offense#corrected attribute' do context 'when cop does not support autocorrection' do before do allow(cop).to receive(:support_autocorrect?).and_return(false) end it 'is not specified (set to nil)' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.corrected?).to be(false) end end context 'when cop supports autocorrection' do let(:cop) { RuboCop::Cop::Style::Alias.new } context 'when offense was corrected' do before do allow(cop).to receive(:autocorrect?).and_return(true) allow(cop).to receive(:autocorrect).and_return(->(_corrector) {}) end it 'is set to true' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.corrected?).to eq(true) end end context 'when autocorrection is not needed' do before do allow(cop).to receive(:autocorrect?).and_return(false) end it 'is set to false' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.corrected?).to eq(false) end end context 'when offense was not corrected because of an error' do before do allow(cop).to receive(:autocorrect?).and_return(true) allow(cop).to receive(:autocorrect).and_return(false) end it 'is set to false' do cop.add_offense(nil, location: location, message: 'message') expect(cop.offenses.first.corrected?).to eq(false) end end end end context 'with no submodule' do subject(:cop) { described_class } it('has right name') { expect(cop.cop_name).to eq('Cop/Cop') } it('has right department') { expect(cop.department).to eq(:Cop) } end context 'with style cops' do subject(:cop) { RuboCop::Cop::Style::For } it('has right name') { expect(cop.cop_name).to eq('Style/For') } it('has right department') { expect(cop.department).to eq(:Style) } end context 'with lint cops' do subject(:cop) { RuboCop::Cop::Lint::Loop } it('has right name') { expect(cop.cop_name).to eq('Lint/Loop') } it('has right department') { expect(cop.department).to eq(:Lint) } end context 'with rails cops' do subject(:cop) { RuboCop::Cop::Rails::Validation } it('has right name') { expect(cop.cop_name).to eq('Rails/Validation') } it('has right department') { expect(cop.department).to eq(:Rails) } end describe 'Registry' do context '#departments' do subject(:departments) { described_class.registry.departments } it('has departments') { expect(departments.length).not_to eq(0) } it { is_expected.to include(:Lint) } it { is_expected.to include(:Rails) } it { is_expected.to include(:Style) } it 'contains every value only once' do expect(departments.length).to eq(departments.uniq.length) end end context '#with_department' do let(:departments) { described_class.registry.departments } it 'has at least one cop per department' do departments.each do |c| expect(described_class.registry.with_department(c).length).to be > 0 end end it 'has each cop in exactly one type' do sum = 0 departments.each do |c| sum += described_class.registry.with_department(c).length end expect(sum).to be described_class.registry.length end it 'returns 0 for an invalid type' do expect(described_class.registry.with_department('x').length).to be 0 end end end describe '#autocorrect?' do # dummy config for a generic cop instance subject { cop.autocorrect? } let(:config) { RuboCop::Config.new({}) } let(:cop) { described_class.new(config, options) } let(:support_autocorrect) { true } before do allow(cop).to receive(:support_autocorrect?) { support_autocorrect } end context 'when the option is not given' do let(:options) { {} } it { is_expected.to be(false) } end context 'when the option is given' do let(:options) { { auto_correct: true } } it { is_expected.to be(true) } context 'when cop does not support autocorrection' do let(:support_autocorrect) { false } it { is_expected.to be(false) } end context 'when the cop is set to not autocorrect' do let(:config) do RuboCop::Config.new('Cop/Cop' => { 'AutoCorrect' => false }) end it { is_expected.to be(false) } end end end end rubocop-0.52.1/spec/rubocop/cop/corrector_spec.rb000066400000000000000000000033141322072016200217710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Corrector do describe '#rewrite' do it 'allows removal of a range' do source = 'true and false' processed_source = parse_source(source) correction = lambda do |corrector| node = processed_source.ast corrector.remove(node.loc.operator) end corrector = described_class.new(processed_source.buffer, [correction]) expect(corrector.rewrite).to eq 'true false' end it 'allows insertion before a source range' do source = 'true and false' processed_source = parse_source(source) correction = lambda do |corrector| node = processed_source.ast corrector.insert_before(node.loc.operator, ';nil ') end corrector = described_class.new(processed_source.buffer, [correction]) expect(corrector.rewrite).to eq 'true ;nil and false' end it 'allows insertion after a source range' do source = 'true and false' processed_source = parse_source(source) correction = lambda do |corrector| node = processed_source.ast corrector.insert_after(node.loc.operator, ' nil;') end corrector = described_class.new(processed_source.buffer, [correction]) expect(corrector.rewrite).to eq 'true and nil; false' end it 'allows replacement of a range' do source = 'true and false' processed_source = parse_source(source) correction = lambda do |corrector| node = processed_source.ast corrector.replace(node.loc.operator, 'or') end corrector = described_class.new(processed_source.buffer, [correction]) expect(corrector.rewrite).to eq 'true or false' end end end rubocop-0.52.1/spec/rubocop/cop/force_spec.rb000066400000000000000000000013271322072016200210670ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Force do subject(:force) { described_class.new(cops) } let(:cops) { [double('cop1'), double('cop2')] } describe '.force_name' do it 'returns the class name without namespace' do expect(RuboCop::Cop::VariableForce.force_name).to eq('VariableForce') end end describe '#run_hook' do it 'invokes a hook in all cops' do expect(cops).to all(receive(:some_hook).with(:foo, :bar)) force.run_hook(:some_hook, :foo, :bar) end it 'does not invoke a hook if the cop does not respond to the hook' do expect(cops.last).to receive(:some_hook).with(:foo, :bar) force.run_hook(:some_hook, :foo, :bar) end end end rubocop-0.52.1/spec/rubocop/cop/gemspec/000077500000000000000000000000001322072016200200525ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/gemspec/duplicated_assignment_spec.rb000066400000000000000000000040151322072016200257570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Gemspec::DuplicatedAssignment do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `name=` twice' do expect_offense(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.name = 'rubocop' spec.name = 'rubocop2' ^^^^^^^^^^^^^^^^^^^^^^ `name=` method calls already given on line 2 of the gemspec. end RUBY end it 'registers an offense when using `version=` twice' do expect_offense(<<-RUBY.strip_indent) require 'rubocop/version' Gem::Specification.new do |spec| spec.version = RuboCop::Version::STRING spec.version = RuboCop::Version::STRING ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `version=` method calls already given on line 4 of the gemspec. end RUBY end it 'registers an offense when using `name=` twice with `cbase`' do expect_offense(<<-RUBY.strip_indent) ::Gem::Specification.new do |spec| spec.name = 'rubocop' spec.name = 'rubocop2' ^^^^^^^^^^^^^^^^^^^^^^ `name=` method calls already given on line 2 of the gemspec. end RUBY end it 'registers an offense when using `<<` twice' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.requirements << 'libmagick, v6.0' spec.requirements << 'A good graphics card' end RUBY end it 'registers an offense when using `spec.add_dependency` twice' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.add_runtime_dependency('parallel', '~> 1.10') spec.add_runtime_dependency('parser', '>= 2.3.3.1', '< 3.0') end RUBY end it 'registers an offense when `name=` method call is not block value' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| foo = Foo.new foo.name = :foo foo.name = :bar end RUBY end end rubocop-0.52.1/spec/rubocop/cop/gemspec/ordered_dependencies_spec.rb000066400000000000000000000136171322072016200255530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Gemspec::OrderedDependencies, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'TreatCommentsAsGroupSeparators' => treat_comments_as_group_separators, 'Include' => nil } end let(:treat_comments_as_group_separators) { false } let(:message) do 'Dependencies should be sorted in an alphabetical order within their ' \ 'section of the gemspec. Dependency `%s` should appear before `%s`.' end shared_examples :ordered_dependency do |add_dependency| context "When #{add_dependency}" do context 'When gems are alphabetically sorted' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.#{add_dependency} 'rspec' spec.#{add_dependency} 'rubocop' end RUBY end end context 'When gems are not alphabetically sorted' do let(:source) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| spec.#{add_dependency} 'rubocop' spec.#{add_dependency} 'rspec' end RUBY it 'registers an offense' do expect_offense(offense_message) end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.#{add_dependency} 'rspec' spec.#{add_dependency} 'rubocop' end RUBY end end context 'When each individual group of line is sorted' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.#{add_dependency} 'rspec' spec.#{add_dependency} 'rubocop' spec.#{add_dependency} 'hello' spec.#{add_dependency} 'world' end RUBY end end context 'When dependency is separated by multiline comment' do let(:source) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| # For code quality spec.#{add_dependency} 'rubocop' # For # test spec.#{add_dependency} 'rspec' end RUBY context 'with TreatCommentsAsGroupSeparators: true' do let(:treat_comments_as_group_separators) { true } it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| # For code quality spec.#{add_dependency} 'rubocop' # For # test spec.#{add_dependency} 'rspec' end RUBY end end context 'with TreatCommentsAsGroupSeparators: false' do it 'registers an offense' do expect_offense(offense_message_with_multiline_comment) end it 'autocorrects' do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(<<-RUBY.strip_indent) Gem::Specification.new do |spec| # For # test spec.#{add_dependency} 'rspec' # For code quality spec.#{add_dependency} 'rubocop' end RUBY end end end end end include_examples :ordered_dependency, 'add_dependency' do let(:offense_message) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| spec.add_dependency 'rubocop' spec.add_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY let(:offense_message_with_multiline_comment) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| # For code quality spec.add_dependency 'rubocop' # For # test spec.add_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY end include_examples :ordered_dependency, 'add_runtime_dependency' do let(:offense_message) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| spec.add_runtime_dependency 'rubocop' spec.add_runtime_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY let(:offense_message_with_multiline_comment) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| # For code quality spec.add_runtime_dependency 'rubocop' # For # test spec.add_runtime_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY end include_examples :ordered_dependency, 'add_development_dependency' do let(:offense_message) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| spec.add_development_dependency 'rubocop' spec.add_development_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY let(:offense_message_with_multiline_comment) { <<-RUBY.strip_indent } Gem::Specification.new do |spec| # For code quality spec.add_development_dependency 'rubocop' # For # test spec.add_development_dependency 'rspec' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{format(message, 'rspec', 'rubocop')} end RUBY end context 'When different dependencies are consecutive' do it 'does not register any offenses' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.add_dependency 'rubocop' spec.add_runtime_dependency 'rspec' end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/gemspec/required_ruby_version_spec.rb000066400000000000000000000056321322072016200260450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Gemspec::RequiredRubyVersion, :config do subject(:cop) { described_class.new(config) } context 'target ruby version > 2.4', :ruby24 do it 'registers an offense when `required_ruby_version` is lower than ' \ '`TargetRubyVersion`' do expect_offense(<<-RUBY.strip_indent, '/path/to/foo.gemspec') Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.3.0' ^^^^^^^^^^ `required_ruby_version` (2.3, declared in foo.gemspec) and `TargetRubyVersion` (2.4, declared in .rubocop.yml) should be equal. end RUBY end describe 'false negatives' do it 'does not register an offense when `required_ruby_version` ' \ 'is assigned as a variable (string literal)' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| version = '>= 2.3.0' spec.required_ruby_version = version end RUBY end it 'does not register an offense when `required_ruby_version` ' \ 'is assigned as a variable (an array of string literal)' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| lowest_version = '>= 2.3.0' highest_version = '< 2.5.0' spec.required_ruby_version = [lowest_version, highest_version] end RUBY end end end context 'target ruby version > 2.2', :ruby22 do it 'registers an offense when `required_ruby_version` is higher than ' \ '`TargetRubyVersion`' do expect_offense(<<-RUBY.strip_indent, '/path/to/bar.gemspec') Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.3.0' ^^^^^^^^^^ `required_ruby_version` (2.3, declared in bar.gemspec) and `TargetRubyVersion` (2.2, declared in .rubocop.yml) should be equal. end RUBY end end context 'target ruby version > 2.3', :ruby23 do it 'does not register an offense when `required_ruby_version` equals ' \ '`TargetRubyVersion`' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.3.0' end RUBY end it 'does not register an offense when `required_ruby_version` ' \ '(omit patch version) equals `TargetRubyVersion`' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.3' end RUBY end it 'does not register an offense when lowest version of ' \ '`required_ruby_version` equals `TargetRubyVersion`' do expect_no_offenses(<<-RUBY.strip_indent) Gem::Specification.new do |spec| spec.required_ruby_version = ['>= 2.3.0', '< 2.5.0'] end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/generator/000077500000000000000000000000001322072016200204155ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/generator/require_file_injector_spec.rb000066400000000000000000000135521322072016200263320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Generator::RequireFileInjector do let(:stdout) { StringIO.new } let(:root_file_path) { 'lib/root.rb' } let(:injector) do described_class.new( source_path: source_path, root_file_path: root_file_path, output: stdout ) end around do |example| Dir.mktmpdir('rubocop-require_file_injector_spec-') do |dir| Dir.chdir(dir) do Dir.mkdir('lib') example.run end end end context 'when a `require_relative` entry does not exist from before' do let(:source_path) { 'lib/rubocop/cop/style/fake_cop.rb' } before do File.write(root_file_path, <<-RUBY.strip_indent) # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY end it 'injects a `require_relative` statement ' \ 'on the right line in the root file' do generated_source = <<-RUBY.strip_indent # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/fake_cop' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY injector.inject expect(File.read(root_file_path)).to eq generated_source expect(stdout.string).to eq(<<-MESSAGE.strip_indent) [modify] lib/root.rb - `require_relative 'rubocop/cop/style/fake_cop'` was injected. MESSAGE end end context 'when a cop of style department already exists' do let(:source_path) { 'lib/rubocop/cop/style/the_end_of_style.rb' } before do File.write(root_file_path, <<-RUBY.strip_indent) # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY end it 'injects a `require_relative` statement ' \ 'on the end of style department' do generated_source = <<-RUBY.strip_indent # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/style/the_end_of_style' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY injector.inject expect(File.read(root_file_path)).to eq generated_source expect(stdout.string).to eq(<<-MESSAGE.strip_indent) [modify] lib/root.rb - `require_relative 'rubocop/cop/style/the_end_of_style'` was injected. MESSAGE end end context 'when a `require` entry already exists' do let(:source_path) { 'lib/rubocop/cop/style/fake_cop.rb' } let(:source) { <<-RUBY.strip_indent } # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/fake_cop' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY before do File.write(root_file_path, source) end it 'does not write to any file' do injector.inject expect(File.read(root_file_path)).to eq source expect(stdout.string.empty?).to be(true) end end context 'when using an unknown department' do let(:source_path) { 'lib/rubocop/cop/unknown/fake_cop.rb' } let(:source) { <<-RUBY } # frozen_string_literal: true require 'parser' require 'rainbow' require 'English' require 'set' require 'forwardable' require_relative 'rubocop/version' require_relative 'rubocop/cop/style/end_block' require_relative 'rubocop/cop/style/even_odd' require_relative 'rubocop/cop/style/fake_cop' require_relative 'rubocop/cop/style/file_name' require_relative 'rubocop/cop/style/flip_flop' require_relative 'rubocop/cop/rails/action_filter' require_relative 'rubocop/cop/team' RUBY before do File.write(root_file_path, source) end it 'does not write to any file' do injector.inject expect(File.read(root_file_path)).to eq source expect(stdout.string.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/generator_spec.rb000066400000000000000000000155321322072016200217620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Generator do subject(:generator) { described_class.new(cop_identifier, output: stdout) } let(:stdout) { StringIO.new } let(:cop_identifier) { 'Style/FakeCop' } before do allow(File).to receive(:write) end describe '#write_source' do it 'generates a helpful source file with the name filled in' do generated_source = <<-RUBY.strip_indent # frozen_string_literal: true # TODO: when finished, run `rake generate_cops_documentation` to update the docs module RuboCop module Cop module Style # TODO: Write cop description and example of bad / good code. # # @example # # bad # bad_method() # # # bad # bad_method(args) # # # good # good_method() # # # good # good_method(args) class FakeCop < Cop # TODO: Implement the cop into here. # # In many cases, you can use a node matcher for matching node pattern. # See. https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/node_pattern.rb # # For example MSG = 'Use `#good_method` instead of `#bad_method`.'.freeze def_node_matcher :bad_method?, <<-PATTERN (send nil? :bad_method ...) PATTERN def on_send(node) return unless bad_method?(node) add_offense(node) end end end end end RUBY generator.write_source expect(File) .to have_received(:write) .with('lib/rubocop/cop/style/fake_cop.rb', generated_source) expect(stdout.string) .to eq("[create] lib/rubocop/cop/style/fake_cop.rb\n") end it 'refuses to overwrite existing files' do new_cop = described_class.new('Layout/Tab') expect(new_cop).to receive(:exit!) expect { new_cop.write_source } .to output( "rake new_cop: lib/rubocop/cop/layout/tab.rb already exists!\n" ).to_stderr end end describe '#write_spec' do it 'generates a helpful starting spec file with the class filled in' do generated_source = <<-SPEC.strip_indent # frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::FakeCop do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } # TODO: Write test code # # For example it 'registers an offense when using `#bad_method`' do expect_offense(<<-RUBY.strip_indent) bad_method ^^^^^^^^^^ Use `#good_method` instead of `#bad_method`. RUBY end it 'does not register an offense when using `#good_method`' do expect_no_offenses(<<-RUBY.strip_indent) good_method RUBY end end SPEC generator.write_spec expect(File) .to have_received(:write) .with('spec/rubocop/cop/style/fake_cop_spec.rb', generated_source) end it 'refuses to overwrite existing files' do new_cop = described_class.new('Layout/Tab') expect(new_cop).to receive(:exit!) expect { new_cop.write_spec } .to output( "rake new_cop: spec/rubocop/cop/layout/tab_spec.rb already exists!\n" ).to_stderr end end describe '#todo' do it 'provides a checklist for implementing the cop' do expect(generator.todo).to eql(<<-TODO.strip_indent) Do 3 steps: 1. Add an entry to the "New features" section in CHANGELOG.md, e.g. "Add new `Style/FakeCop` cop. ([@your_id][])" 2. Modify the description of Style/FakeCop in config/enabled.yml 3. Implement your new cop in the generated file! TODO end end describe '.new' do it 'does not accept an unqualified cop' do expect { described_class.new('FakeCop') } .to raise_error(ArgumentError) .with_message('Specify a cop name with Department/Name style') end end describe '#inject_config' do let(:path) { @path } # rubocop:disable RSpec/InstanceVariable around do |example| Tempfile.create('rubocop-config.yml') do |file| @path = file.path example.run end end before do IO.write(path, <<-YAML.strip_indent) Style/Alias: Enabled: true Style/Lambda: Enabled: true Style/SpecialGlobalVars: Enabled: true YAML end it 'inserts the cop in alphabetical' do expect(File).to receive(:write).with(path, <<-YAML.strip_indent) Style/Alias: Enabled: true Style/FakeCop: Description: 'TODO: Write a description of the cop.' Enabled: true Style/Lambda: Enabled: true Style/SpecialGlobalVars: Enabled: true YAML generator.inject_config(config_file_path: path) expect(stdout.string).to eq(<<-MESSAGE.strip_indent) [modify] A configuration for the cop is added into #{path}. If you want to disable the cop by default, move the added config to config/disabled.yml MESSAGE end end describe '#snake_case' do it 'converts "Lint" to snake_case' do expect(generator.__send__(:snake_case, 'Lint')).to eq('lint') end it 'converts "FooBar" to snake_case' do expect(generator.__send__(:snake_case, 'FooBar')).to eq('foo_bar') end it 'converts "RSpec" to snake_case' do expect(generator.__send__(:snake_case, 'RSpec')).to eq('rspec') end end describe 'compliance with rubocop', :isolated_environment do include FileHelper around do |example| orig_registry = RuboCop::Cop::Cop.registry RuboCop::Cop::Cop.instance_variable_set(:@registry, RuboCop::Cop::Registry.new) example.run RuboCop::Cop::Cop.instance_variable_set(:@registry, orig_registry) end before { allow(File).to receive(:write).and_call_original } let(:config) do config = RuboCop::ConfigStore.new path = File.join(RuboCop::ConfigLoader::RUBOCOP_HOME, RuboCop::ConfigLoader::DOTFILE) config.options_config = path config end let(:options) { { formatters: [] } } let(:runner) { RuboCop::Runner.new(options, config) } it 'generates a cop file that has no offense' do generator.write_source expect(runner.run([])).to be true end it 'generates a spec file that has no offense' do generator.write_spec expect(runner.run([])).to be true end end end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/000077500000000000000000000000001322072016200217365ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/internal_affairs/node_destructuring_spec.rb000066400000000000000000000021331322072016200272030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::NodeDestructuring do subject(:cop) { described_class.new } context 'when destructuring using `node.children`' do it 'registers an offense when receiver is named `node`' do expect_offense(<<-RUBY, 'example_cop.rb') lhs, rhs = node.children ^^^^^^^^^^^^^^^^^^^^^^^^ Use the methods provided with the node extensions, or destructure the node using `*`. RUBY end it 'registers an offense when receiver is named `send_node`' do expect_offense(<<-RUBY, 'example_cop.rb') lhs, rhs = send_node.children ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the methods provided with the node extensions, or destructure the node using `*`. RUBY end end it 'does not register an offense for a predicate node type check' do expect_no_offenses(<<-RUBY, 'example_spec.rb') lhs, rhs = *node RUBY end it 'does not register an offense when receiver is named `array`' do expect_no_offenses(<<-RUBY, 'example_spec.rb') lhs, rhs = array.children RUBY end end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/node_type_predicate_spec.rb000066400000000000000000000012551322072016200273060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::NodeTypePredicate do subject(:cop) { described_class.new } context 'comparison node type check' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') node.type == :send ^^^^^^^^^^^^^^^^^^ Use `#send_type?` to check node type. RUBY end it 'auto-corrects' do new_source = autocorrect_source('node.type == :send') expect(new_source).to eq('node.send_type?') end end it 'does not register an offense for a predicate node type check' do expect_no_offenses(<<-RUBY, 'example_spec.rb') node.send_type? RUBY end end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/offense_location_keyword_spec.rb000066400000000000000000000037421322072016200303640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::OffenseLocationKeyword do subject(:cop) { described_class.new } shared_examples 'auto-correction' do |name, old_source, new_source| it "auto-corrects #{name}" do corrected_source = autocorrect_source(old_source) expect(corrected_source).to eq(new_source) end end context 'when `node.loc.selector` is passed' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, location: node.loc.selector) ^^^^^^^^^^^^^^^^^ Use `:selector` as the location argument to `#add_offense`. RUBY end it 'registers an offense if message argument is passed' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense( node, message: 'message', location: node.loc.selector ^^^^^^^^^^^^^^^^^ Use `:selector` as the location argument to `#add_offense`. ) RUBY end end it 'does not register an offense when the `loc` is on a child node' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node, location: node.arguments.loc.selector) RUBY end it 'does not register an offense when the `loc` is on a different node' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node, location: other_node.loc.selector) RUBY end it_behaves_like( 'auto-correction', 'when there are no other kwargs but location', 'add_offense(node, location: node.loc.selector)', 'add_offense(node, location: :selector)' ) it_behaves_like( 'auto-correction', 'when there are other kwargs', <<-RUBY, add_offense( node, message: 'foo', location: node.loc.selector, severity: :warning ) RUBY <<-RUBY add_offense( node, message: 'foo', location: :selector, severity: :warning ) RUBY ) end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/redundant_location_argument_spec.rb000066400000000000000000000050771322072016200310640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::RedundantLocationArgument do subject(:cop) { described_class.new } shared_examples 'auto-correction' do |name, old_source, new_source| it "auto-corrects #{name}" do corrected_source = autocorrect_source(old_source) expect(corrected_source).to eq(new_source) end end context 'when location argument is passed' do context 'when location argument is :expression' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, location: :expression) ^^^^^^^^^^^^^^^^^^^^^ Redundant location argument to `#add_offense`. RUBY end context 'when there is a message argument' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, location: :expression, message: 'message') ^^^^^^^^^^^^^^^^^^^^^ Redundant location argument to `#add_offense`. RUBY end end it_behaves_like( 'auto-correction', 'when there is no message argument', 'add_offense(node, location: :expression)', 'add_offense(node)' ) it_behaves_like( 'auto-correction', 'when there is a message argument before location', "add_offense(node, message: 'foo', location: :expression)", "add_offense(node, message: 'foo')" ) it_behaves_like( 'auto-correction', 'when there is a message argument after location', "add_offense(node, location: :expression, message: 'foo')", "add_offense(node, message: 'foo')" ) it_behaves_like( 'auto-correction', 'when there are arguments around location', <<-RUBY, add_offense( node, severity: :error, location: :expression, message: 'message' ) RUBY <<-RUBY add_offense( node, severity: :error, message: 'message' ) RUBY ) end context 'when location argument does not equal to :expression' do it 'does not register an offense' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node, location: :selector) RUBY end end end context 'when location argument is not passed' do it 'does not register an offense' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node) RUBY end end end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/redundant_message_argument_spec.rb000066400000000000000000000061471322072016200306770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::RedundantMessageArgument do subject(:cop) { described_class.new } context 'when `MSG` is passed' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, message: MSG) ^^^^^^^^^^^^ Redundant message argument to `#add_offense`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('add_offense(node, message: MSG)') expect(new_source).to eq('add_offense(node)') end end it 'does not register an offense when formatted `MSG` is passed' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node, location: :expression, message: MSG % foo) RUBY end context 'when `#message` is passed' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, location: :expression, message: message) ^^^^^^^^^^^^^^^^ Redundant message argument to `#add_offense`. RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY) add_offense( node, location: :expression, message: message, severity: :error ) RUBY expect(new_source).to eq(<<-RUBY) add_offense( node, location: :expression, severity: :error ) RUBY end end context 'when `#message` with offending node is passed' do context 'when message is the only keyword argument' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, message: message(node)) ^^^^^^^^^^^^^^^^^^^^^^ Redundant message argument to `#add_offense`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('add_offense(node, message: message(node))') expect(new_source).to eq('add_offense(node)') end end context 'when there are others keyword arguments' do it 'registers an offense' do expect_offense(<<-RUBY, 'example_cop.rb') add_offense(node, location: :selector, message: message(node), ^^^^^^^^^^^^^^^^^^^^^^ Redundant message argument to `#add_offense`. severity: :fatal) RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) add_offense(node, location: :selector, message: message(node), severity: :fatal) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) add_offense(node, location: :selector, severity: :fatal) RUBY end end end it 'does not register an offense when `#message` with another node ' \ ' is passed' do expect_no_offenses(<<-RUBY, 'example_cop.rb') add_offense(node, message: message(other_node)) RUBY end end rubocop-0.52.1/spec/rubocop/cop/internal_affairs/useless_message_assertion_spec.rb000066400000000000000000000020651322072016200305560ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::InternalAffairs::UselessMessageAssertion do subject(:cop) { described_class.new } it 'registers an offense for specs that assert using the MSG' do expect_offense(<<-RUBY, 'example_spec.rb') it 'uses described_class::MSG to specify the expected message' do inspect_source(cop, 'foo') expect(cop.messages).to eq([described_class::MSG]) ^^^^^^^^^^^^^^^^^^^^ Do not specify cop behavior using `described_class::MSG`. end RUBY end it 'registers an offense for described_class::MSG in let' do expect_offense(<<-RUBY, 'example_spec.rb') let(:msg) { described_class::MSG } ^^^^^^^^^^^^^^^^^^^^ Do not specify cop behavior using `described_class::MSG`. RUBY end it 'does not register an offense for an assertion about the message' do expect_no_offenses(<<-RUBY, 'example_spec.rb') it 'has a good message' do expect(described_class::MSG).to eq('Good message.') end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/000077500000000000000000000000001322072016200177445ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/layout/access_modifier_indentation_spec.rb000066400000000000000000000245731322072016200270310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::AccessModifierIndentation do subject(:cop) { described_class.new(config) } let(:config) do c = cop_config.merge('SupportedStyles' => %w[indent outdent]) RuboCop::Config .new('Layout/AccessModifierIndentation' => c, 'Layout/IndentationWidth' => { 'Width' => indentation_width }) end let(:indentation_width) { 2 } context 'when EnforcedStyle is set to indent' do let(:cop_config) { { 'EnforcedStyle' => 'indent' } } it 'registers an offense for misaligned private' do inspect_source(<<-RUBY.strip_indent) class Test private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Indent access modifiers like `private`.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'outdent') end it 'registers an offense for misaligned private in module' do inspect_source(<<-RUBY.strip_indent) module Test private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Indent access modifiers like `private`.']) # Not aligned according to `indent` or `outdent` style: expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for misaligned module_function in module' do inspect_source(<<-RUBY.strip_indent) module Test module_function def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Indent access modifiers like `module_function`.']) # Not aligned according to `indent` or `outdent` style: expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for correct + opposite alignment' do inspect_source(<<-RUBY.strip_indent) module Test public private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Indent access modifiers like `private`.']) # No EnforcedStyle can allow both alignments: expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for opposite + correct alignment' do inspect_source(<<-RUBY.strip_indent) module Test public private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Indent access modifiers like `public`.']) # No EnforcedStyle can allow both alignments: expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for misaligned private in singleton class' do expect_offense(<<-RUBY.strip_indent) class << self private ^^^^^^^ Indent access modifiers like `private`. def test; end end RUBY end it 'registers an offense for misaligned private in class ' \ 'defined with Class.new' do inspect_source(<<-RUBY.strip_indent) Test = Class.new do private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Indent access modifiers like `private`.']) end it 'accepts misaligned private in blocks that are not recognized as ' \ 'class/module definitions' do inspect_source(<<-RUBY.strip_indent) Test = func do private def test; end end RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for misaligned private in module ' \ 'defined with Module.new' do inspect_source(<<-RUBY.strip_indent) Test = Module.new do private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Indent access modifiers like `private`.']) end it 'registers an offense for misaligned protected' do expect_offense(<<-RUBY.strip_indent) class Test protected ^^^^^^^^^ Indent access modifiers like `protected`. def test; end end RUBY end it 'accepts properly indented private' do expect_no_offenses(<<-RUBY.strip_indent) class Test private def test; end end RUBY end it 'accepts properly indented protected' do expect_no_offenses(<<-RUBY.strip_indent) class Test protected def test; end end RUBY end it 'accepts an empty class' do expect_no_offenses(<<-RUBY.strip_indent) class Test end RUBY end it 'accepts methods with a body' do expect_no_offenses(<<-RUBY.strip_indent) module Test def test foo end end RUBY end it 'handles properly nested classes' do expect_offense(<<-RUBY.strip_indent) class Test class Nested private ^^^^^^^ Indent access modifiers like `private`. def a; end end protected def test; end end RUBY end it 'auto-corrects incorrectly indented access modifiers' do corrected = autocorrect_source(<<-RUBY.strip_indent) class Test public private protected def test; end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class Test public private protected def test; end end RUBY end context 'when 4 spaces per indent level are used' do let(:indentation_width) { 4 } it 'accepts properly indented private' do expect_no_offenses(<<-RUBY.strip_indent) class Test private def test; end end RUBY end end context 'when indentation width is overridden for this cop only' do let(:cop_config) do { 'EnforcedStyle' => 'indent', 'IndentationWidth' => 4 } end it 'accepts properly indented private' do expect_no_offenses(<<-RUBY.strip_indent) class Test private def test; end end RUBY end end end context 'when EnforcedStyle is set to outdent' do let(:cop_config) { { 'EnforcedStyle' => 'outdent' } } let(:indent_msg) { 'Outdent access modifiers like `private`.' } it 'registers offense for private indented to method depth in a class' do inspect_source(<<-RUBY.strip_indent) class Test private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([indent_msg]) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indent') end it 'registers offense for private indented to method depth in a module' do expect_offense(<<-RUBY.strip_indent) module Test private ^^^^^^^ Outdent access modifiers like `private`. def test; end end RUBY end it 'registers offense for module fn indented to method depth in a module' do expect_offense(<<-RUBY.strip_indent) module Test module_function ^^^^^^^^^^^^^^^ Outdent access modifiers like `module_function`. def test; end end RUBY end it 'registers offense for private indented to method depth in singleton' \ 'class' do inspect_source(<<-RUBY.strip_indent) class << self private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([indent_msg]) end it 'registers offense for private indented to method depth in class ' \ 'defined with Class.new' do inspect_source(<<-RUBY.strip_indent) Test = Class.new do private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([indent_msg]) end it 'registers offense for private indented to method depth in module ' \ 'defined with Module.new' do inspect_source(<<-RUBY.strip_indent) Test = Module.new do private def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([indent_msg]) end it 'accepts private indented to the containing class indent level' do expect_no_offenses(<<-RUBY.strip_indent) class Test private def test; end end RUBY end it 'accepts protected indented to the containing class indent level' do expect_no_offenses(<<-RUBY.strip_indent) class Test protected def test; end end RUBY end it 'handles properly nested classes' do expect_offense(<<-RUBY.strip_indent) class Test class Nested private ^^^^^^^ Outdent access modifiers like `private`. def a; end end protected def test; end end RUBY end it 'auto-corrects incorrectly indented access modifiers' do corrected = autocorrect_source(<<-RUBY.strip_indent) module M class Test public private protected def test; end end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) module M class Test public private protected def test; end end end RUBY end it 'auto-corrects private in complicated case' do corrected = autocorrect_source(<<-RUBY.strip_indent) class Hello def foo 'hi' end def bar Module.new do private def hi 'bye' end end end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class Hello def foo 'hi' end def bar Module.new do private def hi 'bye' end end end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/align_array_spec.rb000066400000000000000000000061611322072016200235770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::AlignArray do subject(:cop) { described_class.new } it 'registers an offense for misaligned array elements' do expect_offense(<<-RUBY.strip_indent) array = [ a, b, ^ Align the elements of an array literal if they span more than one line. c, d ^ Align the elements of an array literal if they span more than one line. ] RUBY end it 'accepts aligned array keys' do expect_no_offenses(<<-RUBY.strip_indent) array = [ a, b, c, d ] RUBY end it 'accepts single line array' do expect_no_offenses('array = [ a, b ]') end it 'accepts several elements per line' do expect_no_offenses(<<-RUBY.strip_indent) array = [ a, b, c, d ] RUBY end it 'accepts aligned array with fullwidth characters' do expect_no_offenses(<<-RUBY.strip_indent) puts 'Ruby', [ a, b ] RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) array = [ a, b, c, d ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) array = [ a, b, c, d ] RUBY end it 'does not auto-correct array within array with too much indentation' do original_source = <<-RUBY.strip_indent [:l1, [:l2, [:l3, [:l4]]]] RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(<<-RUBY.strip_indent) [:l1, [:l2, [:l3, [:l4]]]] RUBY end it 'does not auto-correct array within array with too little indentation' do original_source = <<-RUBY.strip_indent [:l1, [:l2, [:l3, [:l4]]]] RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(<<-RUBY.strip_indent) [:l1, [:l2, [:l3, [:l4]]]] RUBY end it 'auto-corrects only elements that begin a line' do original_source = <<-RUBY.strip_indent array = [:bar, { whiz: 2, bang: 3 }, option: 3] RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(original_source) end it 'does not indent heredoc strings in autocorrect' do original_source = <<-RUBY.strip_indent var = [ { :type => 'something', :sql => < 'something', :sql => < 'something', :sql => < 'something', :sql => < 'key', 'EnforcedColonStyle' => 'key' } end shared_examples 'not on separate lines' do it 'accepts single line hash' do expect_no_offenses('func(a: 0, bb: 1)') end it 'accepts several pairs per line' do expect_no_offenses(<<-RUBY.strip_indent) func(a: 1, bb: 2, ccc: 3, dddd: 4) RUBY end it "does not auto-correct pairs that don't start a line" do source = <<-RUBY.strip_indent render :json => {:a => messages, :b => :json}, :status => 404 def example a( b: :c, d: e( f: g ), h: :i) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end end context 'always inspect last argument hash' do let(:cop_config) do { 'EnforcedLastArgumentHashStyle' => 'always_inspect' } end it 'registers offense for misaligned keys in implicit hash' do expect_offense(<<-RUBY.strip_indent) func(a: 0, b: 1) ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end it 'registers offense for misaligned keys in explicit hash' do expect_offense(<<-RUBY.strip_indent) func({a: 0, b: 1}) ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end end context 'always ignore last argument hash' do let(:cop_config) do { 'EnforcedLastArgumentHashStyle' => 'always_ignore' } end it 'accepts misaligned keys in implicit hash' do expect_no_offenses(<<-RUBY.strip_indent) func(a: 0, b: 1) RUBY end it 'accepts misaligned keys in explicit hash' do expect_no_offenses(<<-RUBY.strip_indent) func({a: 0, b: 1}) RUBY end end context 'ignore implicit last argument hash' do let(:cop_config) do { 'EnforcedLastArgumentHashStyle' => 'ignore_implicit' } end it 'accepts misaligned keys in implicit hash' do expect_no_offenses(<<-RUBY.strip_indent) func(a: 0, b: 1) RUBY end it 'registers offense for misaligned keys in explicit hash' do expect_offense(<<-RUBY.strip_indent) func({a: 0, b: 1}) ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end end context 'ignore explicit last argument hash' do let(:cop_config) do { 'EnforcedLastArgumentHashStyle' => 'ignore_explicit' } end it 'registers offense for misaligned keys in implicit hash' do expect_offense(<<-RUBY.strip_indent) func(a: 0, b: 1) ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end it 'accepts misaligned keys in explicit hash' do expect_no_offenses(<<-RUBY.strip_indent) func({a: 0, b: 1}) RUBY end end context 'with default configuration' do it 'registers an offense for misaligned hash keys' do expect_offense(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1 ^^^^^ Align the elements of a hash literal if they span more than one line. } hash2 = { 'ccc' => 2, 'dddd' => 2 ^^^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'registers an offense for misaligned mixed multiline hash keys' do expect_offense(<<-RUBY.strip_indent) hash = { a: 1, b: 2, c: 3 } ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end it 'accepts aligned hash keys' do expect_no_offenses(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, } hash2 = { 'ccc' => 2, 'dddd' => 2 } RUBY end it 'registers an offense for separator alignment' do expect_offense(<<-RUBY.strip_indent) hash = { 'a' => 0, 'bbb' => 1 ^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end context 'with implicit hash as last argument' do it 'registers an offense for misaligned hash keys' do expect_offense(<<-RUBY.strip_indent) func(a: 0, b: 1) ^^^^ Align the elements of a hash literal if they span more than one line. RUBY end it 'registers an offense for right alignment of keys' do expect_offense(<<-RUBY.strip_indent) func(a: 0, bbb: 1) ^^^^^^ Align the elements of a hash literal if they span more than one line. RUBY end it 'accepts aligned hash keys' do expect_no_offenses(<<-RUBY.strip_indent) func(a: 0, b: 1) RUBY end it 'accepts an empty hash' do expect_no_offenses('h = {}') end end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { :a => 0, :bb => 1, :ccc =>2 } RUBY # Separator and value are not corrected in 'key' mode. expect(new_source).to eq(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { :a => 0, :bb => 1, :ccc =>2 } RUBY end it 'auto-corrects alignment for mixed multiline hash keys' do new_sources = autocorrect_source(<<-RUBY.strip_indent) hash = { a: 1, b: 2, c: 3 } RUBY expect(new_sources).to eq(<<-RUBY.strip_indent) hash = { a: 1, b: 2, c: 3 } RUBY end it 'auto-corrects alignment when using double splat ' \ 'in an explicit hash' do new_source = autocorrect_source(<<-RUBY.strip_indent) Hash(foo: 'bar', **extra_params ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) Hash(foo: 'bar', **extra_params ) RUBY end it 'auto-corrects alignment when using double splat in braces' do new_source = autocorrect_source(<<-RUBY.strip_indent) {foo: 'bar', **extra_params } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) {foo: 'bar', **extra_params } RUBY end end include_examples 'not on separate lines' context 'with table alignment configuration' do let(:cop_config) do { 'EnforcedHashRocketStyle' => 'table', 'EnforcedColonStyle' => 'table' } end include_examples 'not on separate lines' it 'accepts aligned hash keys and values' do expect_no_offenses(<<-RUBY.strip_indent) hash1 = { 'a' => 0, 'bbb' => 1 } hash2 = { a: 0, bbb: 1 } RUBY end it 'accepts an empty hash' do expect_no_offenses('h = {}') end it 'accepts a multiline array of single line hashes' do expect_no_offenses(<<-RUBY.strip_indent) def self.scenarios_order [ { before: %w( l k ) }, { ending: %w( m l ) }, { starting: %w( m n ) }, { after: %w( n o ) } ] end RUBY end it 'accepts hashes that use different separators' do expect_no_offenses(<<-RUBY.strip_indent) hash = { a: 1, 'bbb' => 2 } RUBY end it 'accepts hashes that use different separators and double splats' do expect_no_offenses(<<-RUBY.strip_indent) hash = { a: 1, 'bbb' => 2, **foo } RUBY end it 'accepts a symbol only hash followed by a keyword splat' do expect_no_offenses(<<-RUBY.strip_indent) hash = { a: 1, **kw } RUBY end it 'accepts a keyword splat only hash' do expect_no_offenses(<<-RUBY.strip_indent) hash = { **kw } RUBY end it 'registers an offense for misaligned hash values' do expect_offense(<<-RUBY.strip_indent) hash1 = { 'a' => 0, ^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. 'bbb' => 1 } hash2 = { a: 0, bbb:1 ^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'registers an offense for misaligned hash keys' do expect_offense(<<-RUBY.strip_indent) hash1 = { 'a' => 0, ^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. 'bbb' => 1 ^^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } hash2 = { a: 0, ^^^^^ Align the elements of a hash literal if they span more than one line. bbb: 1 ^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'registers an offense for misaligned hash rockets' do expect_offense(<<-RUBY.strip_indent) hash = { 'a' => 0, 'bbb' => 1 ^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { 'a' => 0, 'bb' => 1, 'ccc' =>2 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { 'a' => 0, 'bb' => 1, 'ccc' => 2 } RUBY end end context 'with table+separator alignment configuration' do let(:cop_config) do { 'EnforcedHashRocketStyle' => 'table', 'EnforcedColonStyle' => 'separator' } end it 'accepts a single method argument entry with colon' do expect_no_offenses('merge(parent: nil)') end end context 'with invalid configuration' do let(:cop_config) do { 'EnforcedHashRocketStyle' => 'junk', 'EnforcedColonStyle' => 'junk' } end it 'fails' do src = <<-RUBY.strip_indent hash = { a: 0, bb: 1 } RUBY expect { inspect_source(src) }.to raise_error(RuntimeError) end end context 'with separator alignment configuration' do let(:cop_config) do { 'EnforcedHashRocketStyle' => 'separator', 'EnforcedColonStyle' => 'separator' } end it 'accepts aligned hash keys' do expect_no_offenses(<<-RUBY.strip_indent) hash1 = { a: 0, bbb: 1 } hash2 = { 'a' => 0, 'bbb' => 1 } RUBY end it 'accepts an empty hash' do expect_no_offenses('h = {}') end it 'registers an offense for misaligned hash values' do expect_offense(<<-RUBY.strip_indent) hash = { 'a' => 0, 'bbb' => 1 ^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'registers an offense for misaligned hash rockets' do expect_offense(<<-RUBY.strip_indent) hash = { 'a' => 0, 'bbb' => 1 ^^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'accepts hashes with different separators' do expect_no_offenses(<<-RUBY.strip_indent) {a: 1, 'b' => 2, **params} RUBY end include_examples 'not on separate lines' it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { a => 0, bb => 1, ccc =>2 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) hash1 = { a: 0, bb: 1, ccc: 2 } hash2 = { a => 0, bb => 1, ccc => 2 } RUBY end it "doesn't break code by moving long keys too far left" do # regression test; see GH issue 2582 new_source = autocorrect_source(['{', ' sjtjo: sjtjo,', ' too_ono_ilitjion_tofotono_o: ' \ 'too_ono_ilitjion_tofotono_o,', '}']) expect(new_source).to eq(['{', ' sjtjo: sjtjo,', 'too_ono_ilitjion_tofotono_o: ' \ 'too_ono_ilitjion_tofotono_o,', '}'].join("\n")) end end context 'with different settings for => and :' do let(:cop_config) do { 'EnforcedHashRocketStyle' => 'key', 'EnforcedColonStyle' => 'separator' } end it 'registers offenses for misaligned entries' do expect_offense(<<-RUBY.strip_indent) hash1 = { a: 0, bbb: 1 ^^^^^^ Align the elements of a hash literal if they span more than one line. } hash2 = { 'a' => 0, 'bbb' => 1 ^^^^^^^^^^ Align the elements of a hash literal if they span more than one line. } RUBY end it 'accepts aligned entries' do expect_no_offenses(<<-RUBY.strip_indent) hash1 = { a: 0, bbb: 1 } hash2 = { 'a' => 0, 'bbb' => 1 } RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/align_parameters_spec.rb000066400000000000000000000473261322072016200246340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::AlignParameters do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/AlignParameters' => cop_config, 'Layout/IndentationWidth' => { 'Width' => indentation_width }) end let(:indentation_width) { 2 } context 'aligned with first parameter' do let(:cop_config) do { 'EnforcedStyle' => 'with_first_parameter' } end it 'registers an offense for parameters with single indent' do expect_offense(<<-RUBY.strip_indent) function(a, if b then c else d end) ^^^^^^^^^^^^^^^^^^^^^^ Align the parameters of a method call if they span more than one line. RUBY end it 'registers an offense for parameters with double indent' do expect_offense(<<-RUBY.strip_indent) function(a, if b then c else d end) ^^^^^^^^^^^^^^^^^^^^^^ Align the parameters of a method call if they span more than one line. RUBY end it 'accepts multiline []= method call' do expect_no_offenses(<<-RUBY.strip_indent) Test.config["something"] = true RUBY end it 'accepts correctly aligned parameters' do expect_no_offenses(<<-RUBY.strip_indent) function(a, 0, 1, (x + y), if b then c else d end) RUBY end it 'accepts correctly aligned parameters with fullwidth characters' do expect_no_offenses(<<-RUBY.strip_indent) f 'Ruby', g(a, b) RUBY end it 'accepts calls that only span one line' do expect_no_offenses('find(path, s, @special[sexp[0]])') end it "doesn't get confused by a symbol argument" do expect_no_offenses(<<-RUBY.strip_indent) add_offense(index, MSG % kind) RUBY end it "doesn't get confused by splat operator" do expect_offense(<<-RUBY.strip_indent) func1(*a, *b, c) func2(a, *b, ^^ Align the parameters of a method call if they span more than one line. c) func3(*a) RUBY end it "doesn't get confused by extra comma at the end" do expect_offense(<<-RUBY.strip_indent) func1(a, b,) ^ Align the parameters of a method call if they span more than one line. RUBY end it 'can handle a correctly aligned string literal as first argument' do expect_no_offenses(<<-RUBY.strip_indent) add_offense(x, a) RUBY end it 'can handle a string literal as other argument' do expect_no_offenses(<<-RUBY.strip_indent) add_offense( "", a) RUBY end it "doesn't get confused by a line break inside a parameter" do expect_no_offenses(<<-RUBY.strip_indent) read(path, { headers: true, converters: :numeric }) RUBY end it "doesn't get confused by symbols with embedded expressions" do expect_no_offenses('send(:"#{name}_comments_path")') end it "doesn't get confused by regexen with embedded expressions" do expect_no_offenses('a(/#{name}/)') end it 'accepts braceless hashes' do expect_no_offenses(<<-RUBY.strip_indent) run(collection, :entry_name => label, :paginator => paginator) RUBY end it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) match( a, b ) RUBY end it 'can handle heredoc strings' do expect_no_offenses(<<-'RUBY'.strip_indent) class_eval(<<-EOS, __FILE__, __LINE__ + 1) def run_#{name}_callbacks(*args) a = 1 return value end EOS RUBY end it 'can handle a method call within a method call' do expect_no_offenses(<<-RUBY.strip_indent) a(a1, b(b1, b2), a2) RUBY end it 'can handle a call embedded in a string' do expect_no_offenses('model("#{index(name)}", child)') end it 'can handle do-end' do expect_no_offenses(<<-RUBY.strip_indent) run(lambda do |e| w = e['warden'] end) RUBY end it 'can handle a call with a block inside another call' do expect_no_offenses(<<-'RUBY'.strip_indent) new(table_name, exec_query("info('#{row['name']}')").map { |col| col['name'] }) RUBY end it 'can handle a ternary condition with a block reference' do expect_no_offenses('cond ? a : func(&b)') end it 'can handle parentheses used with no parameters' do expect_no_offenses('func()') end it 'can handle a multiline hash as second parameter' do expect_no_offenses(<<-RUBY.strip_indent) tag(:input, { :value => value }) RUBY end it 'can handle method calls without parentheses' do expect_no_offenses('a(b c, d)') end it 'can handle other method calls without parentheses' do expect_no_offenses(<<-RUBY.strip_indent) chars(Unicode.apply_mapping @wrapped_string, :uppercase) RUBY end it "doesn't crash and burn when there are nested issues" do # regression test; see GH issue 2441 src = <<-RUBY.strip_indent build(:house, :rooms => [ build(:bedroom, :bed => build(:bed, :occupants => [], :size => "king" ) ) ] ) RUBY expect { inspect_source(src) }.not_to raise_error end context 'method definitions' do it 'registers an offense for parameters with single indent' do expect_offense(<<-RUBY.strip_indent) def method(a, b) ^ Align the parameters of a method definition if they span more than one line. end RUBY end it 'registers an offense for parameters with double indent' do expect_offense(<<-RUBY.strip_indent) def method(a, b) ^ Align the parameters of a method definition if they span more than one line. end RUBY end it 'accepts parameter lists on a single line' do expect_no_offenses(<<-RUBY.strip_indent) def method(a, b) end RUBY end it 'accepts proper indentation' do expect_no_offenses(<<-RUBY.strip_indent) def method(a, b) end RUBY end it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) def method( a, b) end RUBY end it 'accepts a method definition without parameters' do expect_no_offenses(<<-RUBY.strip_indent) def method end RUBY end it "doesn't get confused by splat" do expect_offense(<<-RUBY.strip_indent) def func2(a, *b, ^^ Align the parameters of a method definition if they span more than one line. c) end RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(a, b) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(a, b) end RUBY end context 'defining self.method' do it 'registers an offense for parameters with single indent' do expect_offense(<<-RUBY.strip_indent) def self.method(a, b) ^ Align the parameters of a method definition if they span more than one line. end RUBY end it 'accepts proper indentation' do expect_no_offenses(<<-RUBY.strip_indent) def self.method(a, b) end RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) def self.method(a, b) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def self.method(a, b) end RUBY end end end context 'assigned methods' do it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match( a, b, c ) RUBY end it 'accepts the first parameter being on method row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match(a, b, c ) RUBY end end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) func(a, b, c) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) func(a, b, c) RUBY end it 'auto-corrects each line of a multi-line parameter to the right' do new_source = autocorrect_source(<<-RUBY.strip_indent) create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY expect(new_source) .to eq(<<-RUBY.strip_indent) create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY end it 'auto-corrects each line of a multi-line parameter to the left' do new_source = autocorrect_source(<<-RUBY.strip_indent) create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY expect(new_source) .to eq(<<-RUBY.strip_indent) create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY end it 'auto-corrects only parameters that begin a line' do original_source = <<-RUBY.strip_indent foo(:bar, { whiz: 2, bang: 3 }, option: 3) RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(original_source) end it 'does not crash in autocorrect on dynamic string in parameter value' do src = <<-'RUBY'.strip_indent class MyModel < ActiveRecord::Base has_many :other_models, class_name: "legacy_name", order: "#{legacy_name.table_name}.published DESC" end RUBY new_source = autocorrect_source(src) expect(new_source) .to eq <<-'RUBY'.strip_indent class MyModel < ActiveRecord::Base has_many :other_models, class_name: "legacy_name", order: "#{legacy_name.table_name}.published DESC" end RUBY end end context 'aligned with fixed indentation' do let(:cop_config) do { 'EnforcedStyle' => 'with_fixed_indentation' } end let(:correct_source) do <<-RUBY.strip_indent create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY end it 'does not autocorrect correct source' do expect(autocorrect_source(correct_source)) .to eq(correct_source) end it 'autocorrects by outdenting when indented too far' do original_source = <<-RUBY.strip_indent create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY expect(autocorrect_source(original_source)) .to eq(correct_source) end it 'autocorrects by indenting when not indented' do original_source = <<-RUBY.strip_indent create :transaction, :closed, account: account, open_price: 1.29, close_price: 1.30 RUBY expect(autocorrect_source(original_source)) .to eq(correct_source) end it 'autocorrects when first line is indented' do original_source = <<-RUBY.strip_margin('|') | create :transaction, :closed, | account: account, | open_price: 1.29, | close_price: 1.30 RUBY correct_source = <<-RUBY.strip_margin('|') | create :transaction, :closed, | account: account, | open_price: 1.29, | close_price: 1.30 RUBY expect(autocorrect_source(original_source)) .to eq(correct_source) end context 'multi-line method calls' do it 'can handle existing indentation from multi-line method calls' do expect_no_offenses(<<-RUBY.strip_indent) something .method_name( a, b, c ) RUBY end it 'registers offenses for double indentation from relevant method' do expect_offense(<<-RUBY.strip_indent) something .method_name( a, ^ Use one level of indentation for parameters following the first line of a multi-line method call. b, ^ Use one level of indentation for parameters following the first line of a multi-line method call. c ^ Use one level of indentation for parameters following the first line of a multi-line method call. ) RUBY end it 'does not err on method call without a method name' do expect_no_offenses(<<-RUBY.strip_indent) something .( a, b, c ) RUBY end it 'autocorrects relative to position of relevant method call' do original_source = <<-RUBY.strip_margin('|') | something | .method_name( | a, | b, | c | ) RUBY correct_source = <<-RUBY.strip_margin('|') | something | .method_name( | a, | b, | c | ) RUBY expect(autocorrect_source(original_source)) .to eq(correct_source) end end context 'method definitions' do it 'registers an offense for parameters aligned to first param' do expect_offense(<<-RUBY.strip_indent) def method(a, b) ^ Use one level of indentation for parameters following the first line of a multi-line method definition. end RUBY end it 'registers an offense for parameters with double indent' do expect_offense(<<-RUBY.strip_indent) def method(a, b) ^ Use one level of indentation for parameters following the first line of a multi-line method definition. end RUBY end it 'accepts parameter lists on a single line' do expect_no_offenses(<<-RUBY.strip_indent) def method(a, b) end RUBY end it 'accepts proper indentation' do expect_no_offenses(<<-RUBY.strip_indent) def method(a, b) end RUBY end it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) def method( a, b) end RUBY end it 'accepts a method definition without parameters' do expect_no_offenses(<<-RUBY.strip_indent) def method end RUBY end it "doesn't get confused by splat" do expect_offense(<<-RUBY.strip_indent) def func2(a, *b, ^^ Use one level of indentation for parameters following the first line of a multi-line method definition. c) ^ Use one level of indentation for parameters following the first line of a multi-line method definition. end RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(a, b) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(a, b) end RUBY end context 'defining self.method' do it 'registers an offense for parameters aligned to first param' do expect_offense(<<-RUBY.strip_indent) def self.method(a, b) ^ Use one level of indentation for parameters following the first line of a multi-line method definition. end RUBY end it 'accepts proper indentation' do expect_no_offenses(<<-RUBY.strip_indent) def self.method(a, b) end RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) def self.method(a, b) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def self.method(a, b) end RUBY end end end context 'assigned methods' do context 'with IndentationWidth:Width set to 4' do let(:indentation_width) { 4 } it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match( a, b, c ) RUBY end it 'accepts the first parameter being on method row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match(a, b, c ) RUBY end it 'autocorrects even when first argument is in wrong position' do original_source = <<-RUBY.strip_margin('|') | assigned_value = match( | a, | b, | c | ) RUBY correct_source = <<-RUBY.strip_margin('|') | assigned_value = match( | a, | b, | c | ) RUBY expect(autocorrect_source(original_source)) .to eq(correct_source) end end context 'with AlignParameters:IndentationWidth set to 4' do let(:config) do RuboCop::Config.new('Layout/AlignParameters' => cop_config.merge('IndentationWidth' => 4)) end it 'accepts the first parameter being on a new row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match( a, b, c ) RUBY end it 'accepts the first parameter being on method row' do expect_no_offenses(<<-RUBY.strip_indent) assigned_value = match(a, b, c ) RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/layout/block_end_newline_spec.rb000066400000000000000000000031311322072016200247420ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::BlockEndNewline do subject(:cop) { described_class.new } it 'does not register an offense for a one-liner' do expect_no_offenses('test do foo end') end it 'does not register an offense for multiline blocks with newlines before '\ 'the end' do inspect_source(<<-RUBY.strip_indent) test do foo end RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense when multiline block end is not on its own line' do expect_offense(<<-RUBY.strip_indent) test do foo end ^^^ Expression at 2, 7 should be on its own line. RUBY end it 'registers an offense when multiline block } is not on its own line' do expect_offense(<<-RUBY.strip_indent) test { foo } ^ Expression at 2, 7 should be on its own line. RUBY end it 'autocorrects a do/end block where the end is not on its own line' do src = <<-RUBY.strip_indent test do foo end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['test do', ' foo', 'end', ''].join("\n")) end it 'autocorrects a {} block where the } is not on its own line' do src = <<-RUBY.strip_indent test { foo } RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['test {', ' foo', '}', ''].join("\n")) end end rubocop-0.52.1/spec/rubocop/cop/layout/case_indentation_spec.rb000066400000000000000000000411351322072016200246160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::CaseIndentation do subject(:cop) { described_class.new(config) } let(:config) do merged = RuboCop::ConfigLoader .default_configuration['Layout/CaseIndentation'].merge(cop_config) RuboCop::Config.new('Layout/CaseIndentation' => merged, 'Layout/IndentationWidth' => { 'Width' => 2 }) end context 'with EnforcedStyle: case' do context 'with IndentOneStep: false' do let(:cop_config) do { 'EnforcedStyle' => 'case', 'IndentOneStep' => false } end context 'with everything on a single line' do it 'does not register an offense' do expect_no_offenses('case foo; when :bar then 1; else 0; end') end end context 'regarding assignment where the right hand side is a case' do let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'accepts a correctly indented assignment' do expect_no_offenses(<<-RUBY.strip_indent) output = case variable when 'value1' 'output1' else 'output2' end RUBY end context 'an assignment indented as end' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Indent `when` as deep as `case`.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'end') end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end context 'an assignment indented some other way' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Indent `when` as deep as `case`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end context 'correct + opposite' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Indent `when` as deep as `case`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(correct_source) end end end context "a when clause that's deeper than case" do let(:source) do <<-RUBY.strip_indent case a when 0 then return else case b when 1 then return end end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case a when 0 then return ^^^^ Indent `when` as deep as `case`. else case b when 1 then return ^^^^ Indent `when` as deep as `case`. end end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) case a when 0 then return else case b when 1 then return end end RUBY end end it "accepts a when clause that's equally indented with case" do expect_no_offenses(<<-RUBY.strip_indent) y = case a when 0 then break when 0 then return else z = case b when 1 then return when 1 then break end end case c when 2 then encoding end RUBY end it "doesn't get confused by strings with case in them" do expect_no_offenses(<<-RUBY.strip_indent) a = "case" case x when 0 end RUBY end it "doesn't get confused by symbols named case or when" do expect_no_offenses(<<-RUBY.strip_indent) KEYWORDS = { :case => true, :when => true } case type when 0 ParameterNode when 1 MethodCallNode end RUBY end it 'accepts correctly indented whens in complex combinations' do expect_no_offenses(<<-RUBY.strip_indent) each { case state when 0 case name when :a end when 1 loop { case name when :b end } end } case s when Array end RUBY end end context 'with IndentOneStep: true' do let(:cop_config) do { 'EnforcedStyle' => 'case', 'IndentOneStep' => true } end context 'with everything on a single line' do it 'does not register an offense' do expect_no_offenses('case foo; when :bar then 1; else 0; end') end end context 'regarding assignment where the right hand side is a case' do it 'accepts a correctly indented assignment' do expect_no_offenses(<<-RUBY.strip_indent) output = case variable when 'value1' 'output1' else 'output2' end RUBY end context 'an assignment indented some other way' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) output = case variable when 'value1' ^^^^ Indent `when` one step more than `case`. 'output1' else 'output2' end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end end it "accepts a when clause that's 2 spaces deeper than case" do expect_no_offenses(<<-RUBY.strip_indent) case a when 0 then return else case b when 1 then return end end RUBY end context "a when clause that's equally indented with case" do let(:source) do <<-RUBY.strip_indent y = case a when 0 then break when 0 then return z = case b when 1 then return when 1 then break end end case c when 2 then encoding end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) y = case a when 0 then break ^^^^ Indent `when` one step more than `case`. when 0 then return ^^^^ Indent `when` one step more than `case`. z = case b when 1 then return ^^^^ Indent `when` one step more than `case`. when 1 then break ^^^^ Indent `when` one step more than `case`. end end case c when 2 then encoding ^^^^ Indent `when` one step more than `case`. end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) y = case a when 0 then break when 0 then return z = case b when 1 then return when 1 then break end end case c when 2 then encoding end RUBY end end context 'when indentation width is overridden for this cop only' do let(:cop_config) do { 'EnforcedStyle' => 'case', 'IndentOneStep' => true, 'IndentationWidth' => 5 } end it 'respects cop-specific IndentationWidth' do expect_no_offenses(<<-RUBY.strip_indent) output = case variable when 'value1' 'output1' else 'output2' end RUBY end end end end context 'with EnforcedStyle: end' do context 'with IndentOneStep: false' do let(:cop_config) do { 'EnforcedStyle' => 'end', 'IndentOneStep' => false } end context 'with everything on a single line' do it 'does not register an offense' do expect_no_offenses('case foo; when :bar then 1; else 0; end') end end context 'regarding assignment where the right hand side is a case' do it 'accepts a correctly indented assignment' do expect_no_offenses(<<-RUBY.strip_indent) output = case variable when 'value1' 'output1' else 'output2' end RUBY end context 'an assignment indented some other way' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) output = case variable when 'value1' ^^^^ Indent `when` as deep as `end`. 'output1' else 'output2' end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end end end context 'with IndentOneStep: true' do let(:cop_config) do { 'EnforcedStyle' => 'end', 'IndentOneStep' => true } end context 'with everything on a single line' do it 'does not register an offense' do expect_no_offenses('case foo; when :bar then 1; else 0; end') end end context 'regarding assignment where the right hand side is a case' do it 'accepts a correctly indented assignment' do expect_no_offenses(<<-RUBY.strip_indent) output = case variable when 'value1' 'output1' else 'output2' end RUBY end context 'an assignment indented as case' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.messages) .to eq(['Indent `when` one step more than `end`.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'case') end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end context 'an assignment indented some other way' do let(:source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end let(:correct_source) do <<-RUBY.strip_indent output = case variable when 'value1' 'output1' else 'output2' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.messages) .to eq(['Indent `when` one step more than `end`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq correct_source end end end end end context 'when case is preceded by something else than whitespace' do let(:cop_config) { {} } let(:source) do <<-RUBY.strip_indent case test when something end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case test when something ^^^^ Indent `when` as deep as `case`. end RUBY end it "doesn't auto-correct" do expect(autocorrect_source(source)) .to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end end rubocop-0.52.1/spec/rubocop/cop/layout/class_structure_spec.rb000066400000000000000000000074761322072016200245460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::ClassStructure, :config do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( 'Layout/ClassStructure' => { 'ExpectedOrder' => %w[ module_inclusion constants attribute_macros macros public_class_methods initializer public_methods protected_methods private_methods ], 'Categories' => { 'macros' => %w[validates validate], 'module_inclusion' => %w[prepend extend include], 'attribute_macros' => %w[attr_accessor attr_reader attr_writer] } } ) end context 'with a complete ordered example' do it 'does not create offense' do expect_no_offenses <<-RUBY class Person # extend and include go first extend SomeModule include AnotherModule # inner classes CustomError = Class.new(StandardError) # constants are next SOME_CONSTANT = 20 # afterwards we have attribute macros attr_reader :name # followed by other macros (if any) validates :name # public class methods are next in line def self.some_method end # initialization goes between class methods and other instance methods def initialize end # followed by other public instance methods def some_method end # protected and private methods are grouped near the end protected def some_protected_method end private def some_private_method end end RUBY end end context 'simple example' do specify do expect_offense <<-RUBY.strip_indent class Person CONST = 'wrong place' include AnotherModule ^^^^^^^^^^^^^^^^^^^^^ `module_inclusion` is supposed to appear before `constants`. extend SomeModule end RUBY end specify do expect(autocorrect_source_with_loop(<<-RUBY.strip_indent)) class Example CONST = 1 include AnotherModule extend SomeModule end RUBY .to eq(<<-RUBY.strip_indent) class Example include AnotherModule extend SomeModule CONST = 1 end RUBY end end context 'with protected methods declared before private' do let(:code) { <<-RUBY } class MyClass def public_method end private def first_private_method end def second_private_method end protected def first_protected_method ^^^^^^^^^^^^^^^^^^^^^^^^^^ `protected_methods` is supposed to appear before `private_methods`. end def second_protected_method end end RUBY it { expect_offense(code) } end context 'with attribute macros before after validations' do let(:code) { <<-RUBY } class Person include AnotherModule extend SomeModule CustomError = Class.new(StandardError) validates :name attr_reader :name ^^^^^^^^^^^^^^^^^ `attribute_macros` is supposed to appear before `macros`. def self.some_public_class_method end def initialize end def some_public_method end def other_public_method end private :other_public_method private def something_inline end def yet_other_public_method end protected def some_protected_method end private def some_private_method end end RUBY it { expect_offense(code) } end end rubocop-0.52.1/spec/rubocop/cop/layout/closing_parenthesis_indentation_spec.rb000066400000000000000000000145631322072016200277530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::ClosingParenthesisIndentation do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/AlignParameters' => { 'EnforcedStyle' => align_parameters_config }) end let(:align_parameters_config) { 'with_first_parameter' } context 'for method calls' do context 'with line break before 1st parameter' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) some_method( a ) ^ Indent `)` the same as the start of the line where `(` is. RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) some_method( a ) RUBY expect(corrected).to eq <<-RUBY.strip_indent some_method( a ) RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) some_method( a ) RUBY end end context 'with no line break before 1st parameter' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) some_method(a ) ^ Align `)` with `(`. RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) some_method(a ) RUBY expect(corrected).to eq <<-RUBY.strip_indent some_method(a ) RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) some_method(a ) RUBY end it 'accepts empty ()' do expect_no_offenses('some_method()') end context 'with fixed indentation of parameters' do let(:align_parameters_config) { 'with_fixed_indentation' } it 'accepts a correctly indented )' do expect_no_offenses(<<-RUBY.strip_indent) some_method(a, x: 1, y: 2 ) b = some_method(a, ) RUBY end it 'autocorrects misindented )' do corrected = autocorrect_source(<<-RUBY.strip_indent) some_method(a, x: 1, y: 2 ) b = some_method(a, ) RUBY expect(corrected).to eq <<-RUBY.strip_indent some_method(a, x: 1, y: 2 ) b = some_method(a, ) RUBY end end end end context 'for method definitions' do context 'with line break before 1st parameter' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) def some_method( a ) ^ Indent `)` the same as the start of the line where `(` is. end RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) def some_method( a ) end RUBY expect(corrected).to eq <<-RUBY.strip_indent def some_method( a ) end RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) def some_method( a ) end RUBY end end context 'with no line break before 1st parameter' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) def some_method(a ) ^ Align `)` with `(`. end RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) def some_method(a ) end RUBY expect(corrected).to eq <<-RUBY.strip_indent def some_method(a ) end RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) def some_method(a ) end RUBY end it 'accepts empty ()' do expect_no_offenses(<<-RUBY.strip_indent) def some_method() end RUBY end end end context 'for grouped expressions' do context 'with line break before 1st operand' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) w = x * ( y + z ) ^ Indent `)` the same as the start of the line where `(` is. RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) w = x * ( y + z ) RUBY expect(corrected).to eq <<-RUBY.strip_indent w = x * ( y + z ) RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) w = x * ( y + z ) RUBY end end context 'with no line break before 1st operand' do it 'registers an offense for misaligned )' do expect_offense(<<-RUBY.strip_indent) w = x * (y + z ) ^ Align `)` with `(`. RUBY end it 'autocorrects misaligned )' do corrected = autocorrect_source(<<-RUBY.strip_indent) w = x * (y + z ) RUBY expect(corrected).to eq <<-RUBY.strip_indent w = x * (y + z ) RUBY end it 'accepts a correctly aligned )' do expect_no_offenses(<<-RUBY.strip_indent) w = x * (y + z ) RUBY end it 'accepts ) that does not begin its line' do expect_no_offenses(<<-RUBY.strip_indent) w = x * (y + z + a) RUBY end end end it 'accepts begin nodes that are not grouped expressions' do expect_no_offenses(<<-RUBY.strip_indent) def a x y end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/comment_indentation_spec.rb000066400000000000000000000102311322072016200253360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::CommentIndentation do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config .new('Layout/IndentationWidth' => { 'Width' => indentation_width }) end let(:indentation_width) { 2 } context 'on outer level' do it 'accepts a correctly indented comment' do expect_no_offenses('# comment') end it 'accepts a comment that follows code' do expect_no_offenses('hello # comment') end it 'accepts a documentation comment' do expect_offense(<<-RUBY.strip_indent) =begin Doc comment =end hello # ^ Incorrect indentation detected (column 1 instead of 0). hi RUBY end it 'registers an offense for an incorrectly indented (1) comment' do expect_offense(<<-RUBY.strip_margin('|')) | # comment | ^^^^^^^^^ Incorrect indentation detected (column 1 instead of 0). RUBY end it 'registers an offense for an incorrectly indented (2) comment' do expect_offense(<<-RUBY.strip_margin('|')) | # comment | ^^^^^^^^^ Incorrect indentation detected (column 2 instead of 0). RUBY end it 'registers an offense for each incorrectly indented comment' do expect_offense(<<-RUBY.strip_indent) # a ^^^ Incorrect indentation detected (column 0 instead of 2). # b ^^^ Incorrect indentation detected (column 2 instead of 4). # c ^^^ Incorrect indentation detected (column 4 instead of 0). # d def test; end RUBY end end it 'registers offenses before __RUBY__ but not after' do expect_offense(<<-RUBY.strip_indent) # ^ Incorrect indentation detected (column 1 instead of 0). __END__ # RUBY end context 'around program structure keywords' do it 'accepts correctly indented comments' do expect_no_offenses(<<-RUBY.strip_indent) # def m # if a # b # this is accepted elsif aa # this is accepted else # end # case a # this is accepted when 0 # b end # this is accepted rescue # this is accepted ensure # end # RUBY end context 'with a blank line following the comment' do it 'accepts a correctly indented comment' do expect_no_offenses(<<-RUBY.strip_indent) def m # comment end RUBY end end end context 'near various kinds of brackets' do it 'accepts correctly indented comments' do expect_no_offenses(<<-RUBY.strip_indent) # a = { # x: [ 1 # ], # y: func( 1 # ) # } # RUBY end it 'is unaffected by closing bracket that does not begin a line' do expect_no_offenses(<<-RUBY.strip_indent) # result = [] RUBY end end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) # comment hash1 = { a: 0, # comment bb: 1, ccc: 2 } if a # b # this is accepted elsif aa # so is this elsif bb # else # end case a # this is accepted when 0 # so is this when 1 # b end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # comment hash1 = { a: 0, # comment bb: 1, ccc: 2 } if a # b # this is accepted elsif aa # so is this elsif bb # else # end case a # this is accepted when 0 # so is this when 1 # b end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/dot_position_spec.rb000066400000000000000000000113371322072016200240220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::DotPosition, :config do subject(:cop) { described_class.new(config) } context 'Leading dots style' do let(:cop_config) { { 'EnforcedStyle' => 'leading' } } it 'registers an offense for trailing dot in multi-line call' do inspect_source(<<-RUBY.strip_indent) something. method_name RUBY expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(['.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'trailing') end it 'registers an offense for correct + opposite' do inspect_source(<<-RUBY.strip_indent) something .method_name something. method_name RUBY expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts leading do in multi-line method call' do expect_no_offenses(<<-RUBY.strip_indent) something .method_name RUBY end it 'does not err on method call with no dots' do expect_no_offenses('puts something') end it 'does not err on method call without a method name' do expect_offense(<<-RUBY.strip_indent) l. ^ Place the . on the next line, together with the method name. (1) RUBY end it 'does not err on method call on same line' do expect_no_offenses('something.method_name') end it 'auto-corrects trailing dot in multi-line call' do new_source = autocorrect_source(<<-RUBY.strip_indent) something. method_name RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something .method_name RUBY end it 'auto-corrects trailing dot in multi-line call without selector' do new_source = autocorrect_source(<<-RUBY.strip_indent) something. (1) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something .(1) RUBY end it 'auto-corrects correct + opposite style' do new_source = autocorrect_source(<<-RUBY.strip_indent) something .method_name something. method_name RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something .method_name something .method_name RUBY end context 'when there is an intervening line comment' do it 'does not register offense' do expect_no_offenses(<<-RUBY.strip_indent) something. # a comment here method_name RUBY end end context 'when there is an intervening blank line' do it 'does not register offense' do expect_no_offenses(<<-RUBY.strip_indent) something. method_name RUBY end end end context 'Trailing dots style' do let(:cop_config) { { 'EnforcedStyle' => 'trailing' } } it 'registers an offense for leading dot in multi-line call' do inspect_source(<<-RUBY.strip_indent) something .method_name RUBY expect(cop.messages) .to eq(['Place the . on the previous line, together with the method ' \ 'call receiver.']) expect(cop.highlights).to eq(['.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'leading') end it 'accepts trailing dot in multi-line method call' do expect_no_offenses(<<-RUBY.strip_indent) something. method_name RUBY end it 'does not err on method call with no dots' do expect_no_offenses('puts something') end it 'does not err on method call without a method name' do expect_offense(<<-RUBY.strip_indent) l .(1) ^ Place the . on the previous line, together with the method call receiver. RUBY end it 'does not err on method call on same line' do expect_no_offenses('something.method_name') end it 'does not get confused by several lines of chained methods' do expect_no_offenses(<<-RUBY.strip_indent) File.new(something). readlines.map. compact.join("\n") RUBY end it 'auto-corrects leading dot in multi-line call' do new_source = autocorrect_source(<<-RUBY.strip_indent) something .method_name RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something. method_name RUBY end it 'auto-corrects leading dot in multi-line call without selector' do new_source = autocorrect_source(<<-RUBY.strip_indent) something .(1) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something. (1) RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/else_alignment_spec.rb000066400000000000000000000323641322072016200243010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::ElseAlignment do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Lint/EndAlignment' => end_alignment_config) end let(:end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'variable' } end it 'accepts a ternary if' do expect_no_offenses('cond ? func1 : func2') end context 'with if statement' do it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) if cond func1 else ^^^^ Align `else` with `if`. func2 end RUBY end it 'registers an offense for misaligned elsif' do expect_offense(<<-RUBY.strip_indent) if a1 b1 elsif a2 ^^^^^ Align `elsif` with `if`. b2 end RUBY end it 'accepts indentation after else when if is on new line after ' \ 'assignment' do inspect_source(<<-RUBY.strip_indent) Rails.application.config.ideal_postcodes_key = if Rails.env.production? || Rails.env.staging? "AAAA-AAAA-AAAA-AAAA" else "BBBB-BBBB-BBBB-BBBB" end RUBY expect(cop.offenses.empty?).to be(true) end describe '#autocorrect' do it 'corrects bad alignment' do corrected = autocorrect_source(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 else c end RUBY expect(cop.messages).to eq(['Align `elsif` with `if`.', 'Align `else` with `if`.']) expect(corrected) .to eq <<-RUBY.strip_margin('|') | if a1 | b1 | elsif a2 | b2 | else | c | end RUBY end end it 'accepts a one line if statement' do expect_no_offenses('if cond then func1 else func2 end') end it 'accepts a correctly aligned if/elsif/else/end' do expect_no_offenses(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 else c end RUBY end context 'for a file with byte order mark' do let(:bom) { "\xef\xbb\xbf" } it 'accepts a correctly aligned if/elsif/else/end' do expect_no_offenses(<<-RUBY.strip_indent) #{bom}if a1 b1 elsif a2 b2 else c end RUBY end end context 'with assignment' do context 'when alignment style is variable' do context 'and end is aligned with variable' do it 'accepts an if-else with end aligned with setter' do expect_no_offenses(<<-RUBY.strip_indent) foo.bar = if baz derp1 else derp2 end RUBY end it 'accepts an if-elsif-else with end aligned with setter' do expect_no_offenses(<<-RUBY.strip_indent) foo.bar = if baz derp1 elsif meh derp2 else derp3 end RUBY end it 'accepts an if with end aligned with element assignment' do expect_no_offenses(<<-RUBY.strip_indent) foo[bar] = if baz derp end RUBY end it 'accepts an if/else' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else with chaining after the end' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.join("") RUBY end it 'accepts an if/else with chaining with a block after the end' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.tap {} RUBY end end context 'and end is aligned with keyword' do it 'registers offenses for an if with setter' do expect_offense(<<-RUBY.strip_indent) foo.bar = if baz derp1 elsif meh ^^^^^ Align `elsif` with `foo.bar`. derp2 else ^^^^ Align `else` with `foo.bar`. derp3 end RUBY end it 'registers an offense for an if with element assignment' do expect_offense(<<-RUBY.strip_indent) foo[bar] = if baz derp1 else ^^^^ Align `else` with `foo[bar]`. derp2 end RUBY end it 'registers an offense for an if' do expect_offense(<<-RUBY.strip_indent) var = if a 0 else ^^^^ Align `else` with `var`. 1 end RUBY end end end shared_examples 'assignment and if with keyword alignment' do context 'and end is aligned with variable' do it 'registers an offense for an if' do expect_offense(<<-RUBY.strip_indent) var = if a 0 elsif b ^^^^^ Align `elsif` with `if`. 1 end RUBY end it 'autocorrects bad alignment' do corrected = autocorrect_source(<<-RUBY.strip_indent) var = if a b1 else b2 end RUBY expect(corrected).to eq <<-RUBY.strip_indent var = if a b1 else b2 end RUBY end end context 'and end is aligned with keyword' do it 'accepts an if in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 end RUBY end it 'accepts an if/else in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else in assignment on next line' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts a while in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = while a b end RUBY end it 'accepts an until in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = until a b end RUBY end end end context 'when alignment style is keyword by choice' do let(:end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'keyword' } end include_examples 'assignment and if with keyword alignment' end end it 'accepts an if/else branches with rescue clauses' do # Because of how the rescue clauses come out of Parser, these are # special and need to be tested. expect_no_offenses(<<-RUBY.strip_indent) if a a rescue nil else a rescue nil end RUBY end end context 'with unless' do it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) unless cond func1 else ^^^^ Align `else` with `unless`. func2 end RUBY end it 'accepts a correctly aligned else in an otherwise empty unless' do expect_no_offenses(<<-RUBY.strip_indent) unless a else end RUBY end it 'accepts an empty unless' do expect_no_offenses(<<-RUBY.strip_indent) unless a end RUBY end end context 'with case' do it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) case a when b c when d e else ^^^^ Align `else` with `when`. f end RUBY end it 'accepts correctly aligned case/when/else' do expect_no_offenses(<<-RUBY.strip_indent) case a when b c c when d else f end RUBY end it 'accepts case without else' do expect_no_offenses(<<-'RUBY'.strip_indent) case superclass when /\A(#{NAMESPACEMATCH})(?:\s|\Z)/ $1 when "self" namespace.path end RUBY end it 'accepts else aligned with when but not with case' do # "Indent when as deep as case" is the job of another cop, and this is # one of the possible styles supported by configuration. expect_no_offenses(<<-RUBY.strip_indent) case code_type when 'ruby', 'sql', 'plain' code_type when 'erb' 'ruby; html-script: true' when "html" 'xml' else 'plain' end RUBY end end context 'with def/defs' do it 'accepts an empty def body' do expect_no_offenses(<<-RUBY.strip_indent) def test end RUBY end it 'accepts an empty defs body' do expect_no_offenses(<<-RUBY.strip_indent) def self.test end RUBY end context 'when modifier and def are on the same line' do it 'accepts a correctly aligned body' do expect_no_offenses(<<-RUBY.strip_indent) private def test something rescue handling else something_else end RUBY end it 'registers an offense for else not aligned with private' do expect_offense(<<-RUBY.strip_indent) private def test something rescue handling else ^^^^ Align `else` with `private`. something_else end RUBY end end end context 'with begin/rescue/else/ensure/end' do it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) def my_func puts 'do something outside block' begin puts 'do something error prone' rescue SomeException, SomeOther => e puts 'wrongly intended error handling' rescue puts 'wrongly intended error handling' else ^^^^ Align `else` with `begin`. puts 'wrongly intended normal case handling' ensure puts 'wrongly intended common handling' end end RUBY end it 'accepts a correctly aligned else' do expect_no_offenses(<<-RUBY.strip_indent) begin raise StandardError.new('Fail') if rand(2).odd? rescue StandardError => error $stderr.puts error.message else $stdout.puts 'Lucky you!' end RUBY end end context 'with def/rescue/else/ensure/end' do it 'accepts a correctly aligned else' do expect_no_offenses(<<-RUBY.strip_indent) def my_func(string) puts string rescue => e puts e else puts e ensure puts 'I love methods that print' end RUBY end it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) def my_func(string) puts string rescue => e puts e else ^^^^ Align `else` with `def`. puts e ensure puts 'I love methods that print' end RUBY end end context 'with def/rescue/else/end' do it 'accepts a correctly aligned else' do expect_no_offenses(<<-RUBY.strip_indent) def my_func puts 'do something error prone' rescue SomeException puts 'error handling' rescue puts 'error handling' else puts 'normal handling' end RUBY end it 'registers an offense for misaligned else' do expect_offense(<<-RUBY.strip_indent) def my_func puts 'do something error prone' rescue SomeException puts 'error handling' rescue puts 'error handling' else ^^^^ Align `else` with `def`. puts 'normal handling' end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_line_after_magic_comment_spec.rb000066400000000000000000000037501322072016200275200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLineAfterMagicComment do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense for code that immediately follows comment' do expect_offense(<<-RUBY.strip_indent) # frozen_string_literal: true class Foo; end ^ Add an empty line after magic comments. RUBY end it 'registers an offense for documentation immediately following comment' do expect_offense(<<-RUBY.strip_indent) # frozen_string_literal: true # Documentation for Foo ^ Add an empty line after magic comments. class Foo; end RUBY end it 'registers an offense when multiple magic comments without empty line' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true class Foo; end ^ Add an empty line after magic comments. RUBY end it 'accepts code that separates the comment from the code with a newline' do expect_no_offenses(<<-RUBY.strip_indent) # frozen_string_literal: true class Foo; end RUBY end it 'accepts an empty source file' do expect_no_offenses('') end it 'accepts a source file with only a magic comment' do expect_no_offenses('# frozen_string_literal: true') end it 'autocorrects by adding a newline' do new_source = autocorrect_source(<<-RUBY.strip_indent) # frozen_string_literal: true class Foo; end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # frozen_string_literal: true\n class Foo; end RUBY end it 'autocorrects by adding a newline above the documentation' do new_source = autocorrect_source(<<-RUBY.strip_indent) # frozen_string_literal: true # Documentation for Foo class Foo; end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # frozen_string_literal: true # Documentation for Foo class Foo; end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_line_between_defs_spec.rb000066400000000000000000000230151322072016200261630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLineBetweenDefs, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowAdjacentOneLineDefs' => false } } it 'finds offenses in inner classes' do source = <<-RUBY.strip_indent class K def m end class J def n end def o end end # checks something def p end end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line).sort).to eq([7]) end context 'when there are only comments between defs' do let(:source) do <<-RUBY.strip_indent class J def n end # n-related # checks something o-related # and more def o end end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class J def n end # n-related # checks something o-related # and more def o ^^^ Use empty lines between method definitions. end end RUBY end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) class J def n end # n-related # checks something o-related # and more def o end end RUBY end end context 'conditional method definitions' do it 'accepts defs inside a conditional without blank lines in between' do expect_no_offenses(<<-RUBY.strip_indent) if condition def foo true end else def foo false end end RUBY end it 'registers an offense for consecutive defs inside a conditional' do source = <<-RUBY.strip_indent if condition def foo true end def bar true end else def foo false end end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end end context 'class methods' do context 'adjacent class methods' do let(:offending_source) do <<-RUBY.strip_indent class Test def self.foo true end def self.bar true end end RUBY end it 'registers an offense for missing blank line between methods' do expect_offense(<<-RUBY.strip_indent) class Test def self.foo true end def self.bar ^^^ Use empty lines between method definitions. true end end RUBY end it 'autocorrects it' do corrected = autocorrect_source(offending_source) expect(corrected).to eq(<<-RUBY.strip_indent) class Test def self.foo true end def self.bar true end end RUBY end end context 'mixed instance and class methods' do let(:offending_source) do <<-RUBY.strip_indent class Test def foo true end def self.bar true end end RUBY end it 'registers an offense for missing blank line between methods' do expect_offense(<<-RUBY.strip_indent) class Test def foo true end def self.bar ^^^ Use empty lines between method definitions. true end end RUBY end it 'autocorrects it' do corrected = autocorrect_source(offending_source) expect(corrected).to eq(<<-RUBY.strip_indent) class Test def foo true end def self.bar true end end RUBY end end end # Only one def, so rule about empty line *between* defs does not # apply. it 'accepts a def that follows a line with code' do expect_no_offenses(<<-RUBY.strip_indent) x = 0 def m end RUBY end # Only one def, so rule about empty line *between* defs does not # apply. it 'accepts a def that follows code and a comment' do expect_no_offenses(<<-RUBY.strip_indent) x = 0 # 123 def m end RUBY end it 'accepts the first def without leading empty line in a class' do expect_no_offenses(<<-RUBY.strip_indent) class K def m end end RUBY end it 'accepts a def that follows an empty line and then a comment' do expect_no_offenses(<<-RUBY.strip_indent) class A # calculates value def m end private # calculates size def n end end RUBY end it 'accepts a def that is the first of a module' do expect_no_offenses(<<-RUBY.strip_indent) module Util public # def html_escape(s) end end RUBY end it 'accepts a nested def' do expect_no_offenses(<<-RUBY.strip_indent) def mock_model(*attributes) Class.new do def initialize(attrs) end end end RUBY end it 'registers an offense for adjacent one-liners by default' do source = <<-RUBY.strip_indent def a; end def b; end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects adjacent one-liners by default' do corrected = autocorrect_source(<<-RUBY.strip_indent) def a; end def b; end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) def a; end def b; end RUBY end it 'auto-corrects when there are too many new lines' do corrected = autocorrect_source(<<-RUBY.strip_indent) def a; end def b; end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) def a; end def b; end RUBY end it 'treats lines with whitespaces as blank' do expect_no_offenses(<<-RUBY.strip_indent) class J def n end def o end end RUBY end it "doesn't allow more than the required number of newlines" do source = <<-RUBY.strip_indent class A def n end def o end end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end context 'when AllowAdjacentOneLineDefs is enabled' do let(:cop_config) { { 'AllowAdjacentOneLineDefs' => true } } it 'accepts adjacent one-liners' do expect_no_offenses(<<-RUBY.strip_indent) def a; end def b; end RUBY end it 'registers an offense for adjacent defs if some are multi-line' do source = <<-RUBY.strip_indent def a; end def b; end def c # Not a one-liner, so this is an offense. end def d; end # Also an offense since previous was multi-line: RUBY inspect_source(source) expect(cop.offenses.map(&:line)).to eq([3, 5]) end end context 'when a maximum of empty lines is specified' do let(:cop_config) { { 'NumberOfEmptyLines' => [0, 1] } } it 'finds no offense for no empty line' do expect_no_offenses(<<-RUBY.strip_indent) def n end def o end RUBY end it 'finds no offense for one empty line' do expect_no_offenses(<<-RUBY.strip_indent) def n end def o end RUBY end it 'finds an offense for two empty lines' do source = <<-RUBY.strip_indent def n end def o end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects' do source = <<-RUBY.strip_indent def n end def o end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) def n end def o end RUBY end end context 'when multiple lines between defs are allowed' do let(:cop_config) { { 'NumberOfEmptyLines' => 2 } } it 'treats lines with whitespaces as blank' do source = <<-RUBY.strip_indent def n end def o end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects when there are no new lines' do source = <<-RUBY.strip_indent def n end def o end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) def n end def o end RUBY end it 'auto-corrects when there are too few new lines' do source = <<-RUBY.strip_indent def n end def o end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) def n end def o end RUBY end it 'auto-corrects when there are too many new lines' do source = <<-RUBY.strip_indent def n end def o end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) def n end def o end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_access_modifier_spec.rb000066400000000000000000000137101322072016200304040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundAccessModifier do subject(:cop) { described_class.new } %w[private protected public module_function].each do |access_modifier| it "requires blank line before #{access_modifier}" do inspect_source(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Keep a blank line before and after `#{access_modifier}`."]) end it "requires blank line after #{access_modifier}" do inspect_source(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Keep a blank line before and after `#{access_modifier}`."]) end it "ignores comment line before #{access_modifier}" do inspect_source(<<-RUBY.strip_indent) class Test something # This comment is fine #{access_modifier} def test; end end RUBY expect(cop.offenses.empty?).to be(true) end it "ignores #{access_modifier} inside a method call" do inspect_source(<<-RUBY.strip_indent) class Test def #{access_modifier}? #{access_modifier} end end RUBY expect(cop.offenses.empty?).to be(true) end it "ignores #{access_modifier} deep inside a method call" do inspect_source(<<-RUBY.strip_indent) class Test def #{access_modifier}? if true #{access_modifier} end end end RUBY expect(cop.offenses.empty?).to be(true) end it "ignores #{access_modifier} with a right-hand-side condition" do inspect_source(<<-RUBY.strip_indent) class Test def #{access_modifier}? #{access_modifier} if true end end RUBY expect(cop.offenses.empty?).to be(true) end it "autocorrects blank line before #{access_modifier}" do corrected = autocorrect_source(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY end it 'autocorrects blank line after #{access_modifier}' do corrected = autocorrect_source(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class Test something #{access_modifier} def test; end end RUBY end it 'autocorrects blank line after #{access_modifier} with comment' do corrected = autocorrect_source(<<-RUBY.strip_indent) class Test something #{access_modifier} # let's modify the rest def test; end end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class Test something #{access_modifier} # let's modify the rest def test; end end RUBY end it 'accepts missing blank line when at the beginning of class/module' do expect_no_offenses(<<-RUBY.strip_indent) class Test #{access_modifier} def test; end end RUBY end it "requires blank line after, but not before, #{access_modifier} " \ 'when at the beginning of class/module' do inspect_source(<<-RUBY.strip_indent) class Test #{access_modifier} def test end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Keep a blank line after `#{access_modifier}`."]) end context 'at the beginning of block' do context 'for blocks defined with do' do it 'accepts missing blank line' do expect_no_offenses(<<-RUBY.strip_indent) included do #{access_modifier} def test; end end RUBY end it 'accepts missing blank line with arguments' do expect_no_offenses(<<-RUBY.strip_indent) included do |foo| #{access_modifier} def test; end end RUBY end it "requires blank line after, but not before, #{access_modifier}" do inspect_source(<<-RUBY.strip_indent) included do #{access_modifier} def test end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Keep a blank line after `#{access_modifier}`."]) end end context 'for blocks defined with {}' do it 'accepts missing blank line' do expect_no_offenses(<<-RUBY.strip_indent) included { #{access_modifier} def test; end } RUBY end it 'accepts missing blank line with arguments' do expect_no_offenses(<<-RUBY.strip_indent) included { |foo| #{access_modifier} def test; end } RUBY end end end it 'accepts missing blank line when at the end of block' do expect_no_offenses(<<-RUBY.strip_indent) class Test def test; end #{access_modifier} end RUBY end it 'recognizes blank lines with DOS style line endings' do expect_no_offenses(<<-RUBY.strip_indent) class Test\r \r #{access_modifier}\r \r def test; end\r end\r RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_arguments_spec.rb000066400000000000000000000164471322072016200273040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundArguments, :config do subject(:cop) { described_class.new(config) } context 'when extra lines' do it 'registers offense for empty line before arg' do inspect_source(<<-RUBY.strip_indent) foo( bar ) RUBY expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offense for empty line after arg' do inspect_source(<<-RUBY.strip_indent) bar( [baz, qux] ) RUBY expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offense for empty line between args' do inspect_source(<<-RUBY.strip_indent) foo.do_something( baz, qux: 0 ) RUBY expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offense for empty line in-between one arg' do inspect_source(<<-RUBY.strip_indent) do_stuff([ "some text", "some more text" ]) RUBY expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offenses when multiple empty lines are detected' do inspect_source(<<-RUBY.strip_indent) foo( baz, qux, biz, ) RUBY expect(cop.offenses.size).to eq 3 expect(cop.messages.uniq) .to eq(['Empty line detected around arguments.']) end it 'registers offense when args start on definition line' do inspect_source(<<-RUBY.strip_indent) foo(biz, baz: 0) RUBY expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offense when empty line between normal arg & block arg' do inspect_source(<<-RUBY.strip_indent) Foo.prepend( a, Module.new do def something; end def anything; end end ) RUBY expect(cop.offenses.size).to eq 1 expect(cop.messages) .to eq(['Empty line detected around arguments.']) end it 'registers offense on correct line for single offense example' do inspect_source(<<-RUBY.strip_indent) class Foo include Bar def baz(qux) fizz( qux, 10 ) end end RUBY expect(cop.offenses.size).to eq 1 expect(cop.offenses.first.location.line).to eq 8 expect(cop.messages.uniq) .to eq(['Empty line detected around arguments.']) end it 'registers offense on correct lines for multi-offense example' do inspect_source(<<-RUBY.strip_indent) something(1, 5) something_else foo(biz, qux) quux.map do end.another.thing( [baz] ) RUBY expect(cop.offenses.size).to eq 2 expect(cop.offenses[0].location.line).to eq 5 expect(cop.offenses[1].location.line).to eq 11 expect(cop.messages.uniq) .to eq(['Empty line detected around arguments.']) end it 'autocorrects empty line detected at top' do corrected = autocorrect_source(['foo(', '', ' bar', ')'].join("\n")) expect(corrected).to eq ['foo(', ' bar', ')'].join("\n") end it 'autocorrects empty line detected at bottom' do corrected = autocorrect_source(['foo(', ' baz: 1', '', ')'].join("\n")) expect(corrected).to eq ['foo(', ' baz: 1', ')'].join("\n") end it 'autocorrects empty line detected in the middle' do corrected = autocorrect_source(['do_something(', ' [baz],', '', ' qux: 0', ')'].join("\n")) expect(corrected).to eq ['do_something(', ' [baz],', ' qux: 0', ')'].join("\n") end it 'autocorrects empty line in-between one arg' do corrected = autocorrect_source(['do_stuff([', " 'some text',", '', " 'some more text'", '])'].join("\n")) expect(corrected).to eq ['do_stuff([', " 'some text',", " 'some more text'", '])'].join("\n") end it 'autocorrects multiple empty lines' do corrected = autocorrect_source(['do_stuff(', ' baz,', '', ' qux,', '', ' bar: 0,', '', ')'].join("\n")) expect(corrected).to eq ['do_stuff(', ' baz,', ' qux,', ' bar: 0,', ')'].join("\n") end it 'autocorrects args that start on definition line' do corrected = autocorrect_source(['bar(qux,', '', ' 78)'].join("\n")) expect(corrected).to eq ['bar(qux,', ' 78)'].join("\n") end end context 'when no extra lines' do it 'accpets one line methods' do inspect_source(<<-RUBY.strip_indent) foo(bar) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts multiple listed mixed args' do inspect_source(<<-RUBY.strip_indent) foo( bar, [], baz = nil, qux: 2 ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts listed args starting on defintion line' do inspect_source(<<-RUBY.strip_indent) foo(bar, [], qux: 2) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts block argument with empty line' do inspect_source(<<-RUBY.strip_indent) Foo.prepend(Module.new do def something; end def anything; end end) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts method with argument that trails off block' do inspect_source(<<-RUBY.strip_indent) fred.map do <<-EOT bar foo EOT end.join("\n") RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts method with no arguments that trails off block' do inspect_source(<<-RUBY.strip_indent) foo.baz do bar end.compact RUBY expect(cop.offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_begin_body_spec.rb000066400000000000000000000071751322072016200273760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundBeginBody do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples :offense do |name, message, code, correction| it "registers an offense for #{name} with a blank" do inspect_source(code.strip_indent) message = "Extra empty line detected at `begin` body #{message}." expect(cop.messages).to eq([message]) end it "autocorrects for #{name} with a blank" do corrected = autocorrect_source(code.strip_indent) expect(corrected).to eq(correction.strip_indent) end end shared_examples :accepts do |name, code| it "accepts #{name}" do inspect_source(code) expect(cop.offenses.empty?).to be(true) end end include_examples :offense, 'begin body starting', 'beginning', <<-CODE, <<-CORRECTION begin foo end CODE begin foo end CORRECTION include_examples :offense, 'begin body ending', 'end', <<-CODE, <<-CORRECTION begin foo end CODE begin foo end CORRECTION include_examples :offense, 'begin body starting in method', 'beginning', <<-CODE, <<-CORRECTION def bar begin foo end end CODE def bar begin foo end end CORRECTION include_examples :offense, 'begin body ending in method', 'end', <<-CODE, <<-CORRECTION def bar begin foo end end CODE def bar begin foo end end CORRECTION include_examples :offense, 'begin body starting with rescue', 'beginning', <<-CODE, <<-CORRECTION begin foo rescue bar end CODE begin foo rescue bar end CORRECTION include_examples :offense, 'rescue body ending', 'end', <<-CODE, <<-CORRECTION begin foo rescue bar end CODE begin foo rescue bar end CORRECTION include_examples :offense, 'else body ending', 'end', <<-CODE, <<-CORRECTION begin foo rescue bar else baz end CODE begin foo rescue bar else baz end CORRECTION include_examples :offense, 'ensure body ending', 'end', <<-CODE, <<-CORRECTION begin foo ensure bar end CODE begin foo ensure bar end CORRECTION context 'with complex begin-end' do let(:source) { <<-RUBY.strip_indent } begin do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY let(:correction) { <<-RUBY.strip_indent } begin do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY it 'registers many offenses' do inspect_source(source) expect(cop.offenses.size).to eq(2) end it 'autocorrects' do corrected = autocorrect_source(source) expect(corrected).to eq correction end end include_examples :accepts, 'begin block without empty line', <<-RUBY begin foo end RUBY include_examples :accepts, 'begin block without empty line in a method', <<-RUBY def foo begin bar end end RUBY end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_block_body_spec.rb000066400000000000000000000063751322072016200274050ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundBlockBody, :config do subject(:cop) { described_class.new(config) } # Test blocks using both {} and do..end [%w[{ }], %w[do end]].each do |open, close| context "when EnforcedStyle is no_empty_lines for #{open} #{close} block" do let(:cop_config) { { 'EnforcedStyle' => 'no_empty_lines' } } it 'registers an offense for block body starting with a blank' do inspect_source(["some_method #{open}", '', ' do_something', close]) expect(cop.messages) .to eq(['Extra empty line detected at block body beginning.']) end it 'autocorrects block body containing only a blank' do corrected = autocorrect_source(["some_method #{open}", '', close]) expect(corrected).to eq ["some_method #{open}", close].join("\n") end it 'registers an offense for block body ending with a blank' do inspect_source(["some_method #{open}", ' do_something', '', close]) expect(cop.messages) .to eq(['Extra empty line detected at block body end.']) end it 'accepts block body starting with a line with spaces' do inspect_source(["some_method #{open}", ' ', ' do_something', close]) expect(cop.offenses.empty?).to be(true) end it 'is not fooled by single line blocks' do expect_no_offenses(<<-RUBY.strip_indent) some_method #{open} do_something #{close} something_else RUBY end end context "when EnforcedStyle is empty_lines for #{open} #{close} block" do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines' } } it 'registers an offense for block body not starting or ending with a ' \ 'blank' do inspect_source(["some_method #{open}", ' do_something', close]) expect(cop.messages).to eq(['Empty line missing at block body '\ 'beginning.', 'Empty line missing at block body end.']) end it 'ignores block with an empty body' do source = "some_method #{open}\n#{close}" corrected = autocorrect_source(source) expect(corrected).to eq(source) end it 'autocorrects beginning and end' do new_source = autocorrect_source(["some_method #{open}", ' do_something', close]) expect(new_source).to eq(["some_method #{open}", '', ' do_something', '', close].join("\n")) end it 'is not fooled by single line blocks' do expect_no_offenses(<<-RUBY.strip_indent) some_method #{open} do_something #{close} something_else RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_class_body_spec.rb000066400000000000000000000175621322072016200274200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundClassBody, :config do subject(:cop) { described_class.new(config) } let(:extra_begin) { 'Extra empty line detected at class body beginning.' } let(:extra_end) { 'Extra empty line detected at class body end.' } let(:missing_begin) { 'Empty line missing at class body beginning.' } let(:missing_end) { 'Empty line missing at class body end.' } let(:missing_def) { 'Empty line missing before first def definition' } let(:missing_type) { 'Empty line missing before first class definition' } context 'when EnforcedStyle is no_empty_lines' do let(:cop_config) { { 'EnforcedStyle' => 'no_empty_lines' } } it 'registers an offense for class body starting with a blank' do inspect_source(<<-RUBY.strip_indent) class SomeClass do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at class body beginning.']) end it 'autocorrects class body containing only a blank' do corrected = autocorrect_source(<<-RUBY.strip_indent) class SomeClass end RUBY expect(corrected).to eq <<-RUBY.strip_indent class SomeClass end RUBY end it 'registers an offense for class body ending with a blank' do inspect_source(<<-RUBY.strip_indent) class SomeClass do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at class body end.']) end it 'registers an offense for singleton class body starting with a blank' do inspect_source(<<-RUBY.strip_indent) class << self do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at class body beginning.']) end it 'autocorrects singleton class body containing only a blank' do corrected = autocorrect_source(<<-RUBY.strip_indent) class << self end RUBY expect(corrected).to eq <<-RUBY.strip_indent class << self end RUBY end it 'registers an offense for singleton class body ending with a blank' do inspect_source(<<-RUBY.strip_indent) class << self do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at class body end.']) end end context 'when EnforcedStyle is empty_lines' do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines' } } it 'registers an offense for class body not starting or ending with a ' \ 'blank' do inspect_source(<<-RUBY.strip_indent) class SomeClass do_something end RUBY expect(cop.messages).to eq(['Empty line missing at class body beginning.', 'Empty line missing at class body end.']) end it 'ignores classes with an empty body' do source = "class SomeClass\nend" corrected = autocorrect_source(source) expect(corrected).to eq(source) end it 'autocorrects beginning and end' do new_source = autocorrect_source(<<-RUBY.strip_indent) class SomeClass do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class SomeClass do_something end RUBY end it 'registers an offense for singleton class body not starting or ending ' \ 'with a blank' do inspect_source(<<-RUBY.strip_indent) class << self do_something end RUBY expect(cop.messages).to eq(['Empty line missing at class body beginning.', 'Empty line missing at class body end.']) end it 'ignores singleton classes with an empty body' do source = "class << self\nend" corrected = autocorrect_source(source) expect(corrected).to eq(source) end it 'autocorrects beginning and end for `class << self`' do new_source = autocorrect_source(<<-RUBY.strip_indent) class << self do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class << self do_something end RUBY end end context 'when EnforcedStyle is empty_lines_except_namespace' do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines_except_namespace' } } context 'when only child is class' do it 'requires no empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) class Parent < Base class Child do_something end end RUBY end it 'registers offence for namespace body starting with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent class Child do_something end end RUBY expect(cop.messages).to eq([extra_begin]) end it 'registers offence for namespace body ending with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent class Child do_something end end RUBY expect(cop.messages).to eq([extra_end]) end it 'registers offences for namespaced class body not starting '\ 'with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent class Child do_something end end RUBY expect(cop.messages).to eq([missing_begin]) end it 'registers offences for namespaced class body not ending '\ 'with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent class Child do_something end end RUBY expect(cop.messages).to eq([missing_end]) end it 'autocorrects beginning and end' do new_source = autocorrect_source(<<-RUBY.strip_indent) class Parent < Base class Child do_something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class Parent < Base class Child do_something end end RUBY end end context 'when only child is module' do it 'requires no empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) class Parent module Child do_something end end RUBY end it 'registers offence for namespace body starting with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent module Child do_something end end RUBY expect(cop.messages).to eq([extra_begin]) end it 'registers offence for namespace body ending with a blank' do inspect_source(<<-RUBY.strip_indent) class Parent module Child do_something end end RUBY expect(cop.messages).to eq([extra_end]) end end context 'when has multiple child classes' do it 'requires empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) class Parent class Mom do_something end class Dad end end RUBY end it 'registers offences for namespace body starting '\ 'and ending without a blank' do inspect_source(<<-RUBY.strip_indent) class Parent class Mom do_something end class Dad end end RUBY expect(cop.messages).to eq([missing_begin, missing_end]) end end end include_examples 'empty_lines_around_class_or_module_body', 'class' end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_exception_handling_keywords_spec.rb000066400000000000000000000103031322072016200330510ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundExceptionHandlingKeywords do # rubocop:disable Metrics/LineLength subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples :offense do |name, message, code, correction| it "registers an offense for #{name} with a blank" do inspect_source(code.strip_indent) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(["Extra empty line detected #{message}."]) end it "autocorrects for #{name} with a blank" do corrected = autocorrect_source(code.strip_indent) expect(corrected).to eq(correction.strip_indent) end end shared_examples :accepts do |name, code| it "accepts #{name}" do inspect_source(code) expect(cop.offenses.empty?).to be(true) end end include_examples :offense, 'above rescue keyword', 'before the `rescue`', <<-CODE, <<-CORRECTION begin f1 rescue f2 end CODE begin f1 rescue f2 end CORRECTION include_examples :offense, 'rescue section starting', 'after the `rescue`', <<-CODE, <<-CORRECTION begin f1 rescue f2 end CODE begin f1 rescue f2 end CORRECTION include_examples :offense, 'rescue section ending', 'before the `else`', <<-CODE, <<-CORRECTION begin f1 rescue f2 else f3 end CODE begin f1 rescue f2 else f3 end CORRECTION include_examples :offense, 'rescue section ending for method definition', 'before the `else`', <<-CODE, <<-CORRECTION def foo f1 rescue f2 else f3 end CODE def foo f1 rescue f2 else f3 end CORRECTION include_examples :accepts, 'no empty line', <<-RUBY begin f1 rescue f2 else f3 ensure f4 end RUBY include_examples :accepts, 'empty lines around begin body', <<-RUBY begin f1 end RUBY include_examples :accepts, 'empty begin', <<-RUBY begin end RUBY include_examples :accepts, 'empty method definition', <<-RUBY def foo end RUBY context 'with complex begin-end' do let(:source) { <<-RUBY.strip_indent } begin do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY let(:correction) { <<-RUBY.strip_indent } begin do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY it 'registers many offenses' do inspect_source(source) expect(cop.offenses.size).to eq(10) end it 'autocorrects' do corrected = autocorrect_source(source) expect(corrected).to eq correction end end context 'with complex method definition' do let(:source) { <<-RUBY.strip_indent } def foo do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY let(:correction) { <<-RUBY.strip_indent } def foo do_something1 rescue RuntimeError do_something2 rescue ArgumentError => ex do_something3 rescue do_something3 else do_something4 ensure do_something4 end RUBY it 'registers many offenses' do inspect_source(source) expect(cop.offenses.size).to eq(10) end it 'autocorrects' do corrected = autocorrect_source(source) expect(corrected).to eq correction end end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_method_body_spec.rb000066400000000000000000000047751322072016200275750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundMethodBody do subject(:cop) { described_class.new } it 'registers an offense for method body starting with a blank' do inspect_source(<<-RUBY.strip_indent) def some_method do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at method body beginning.']) end # The cop only registers an offense if the extra line is completely empty. If # there is trailing whitespace, then that must be dealt with first. Having # two cops registering offense for the line with only spaces would cause # havoc in auto-correction. it 'accepts method body starting with a line with spaces' do expect_no_offenses([ 'def some_method', ' ', ' do_something', 'end' ]) end it 'autocorrects method body starting with a blank' do corrected = autocorrect_source(<<-RUBY.strip_indent) def some_method do_something end RUBY expect(corrected).to eq <<-RUBY.strip_indent def some_method do_something end RUBY end it 'registers an offense for class method body starting with a blank' do inspect_source(<<-RUBY.strip_indent) def Test.some_method do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at method body beginning.']) end it 'autocorrects class method body starting with a blank' do corrected = autocorrect_source(<<-RUBY.strip_indent) def Test.some_method do_something end RUBY expect(corrected).to eq <<-RUBY.strip_indent def Test.some_method do_something end RUBY end it 'registers an offense for method body ending with a blank' do inspect_source(<<-RUBY.strip_indent) def some_method do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at method body end.']) end it 'registers an offense for class method body ending with a blank' do inspect_source(<<-RUBY.strip_indent) def Test.some_method do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at method body end.']) end it 'is not fooled by single line methods' do expect_no_offenses(<<-RUBY.strip_indent) def some_method; do_something; end something_else RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_around_module_body_spec.rb000066400000000000000000000147011322072016200275700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLinesAroundModuleBody, :config do subject(:cop) { described_class.new(config) } let(:extra_begin) { 'Extra empty line detected at module body beginning.' } let(:extra_end) { 'Extra empty line detected at module body end.' } let(:missing_begin) { 'Empty line missing at module body beginning.' } let(:missing_end) { 'Empty line missing at module body end.' } let(:missing_def) { 'Empty line missing before first def definition' } let(:missing_type) { 'Empty line missing before first module definition' } context 'when EnforcedStyle is no_empty_lines' do let(:cop_config) { { 'EnforcedStyle' => 'no_empty_lines' } } it 'registers an offense for module body starting with a blank' do inspect_source(<<-RUBY.strip_indent) module SomeModule do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at module body beginning.']) end it 'registers an offense for module body ending with a blank' do inspect_source(<<-RUBY.strip_indent) module SomeModule do_something end RUBY expect(cop.messages) .to eq(['Extra empty line detected at module body end.']) end it 'autocorrects beginning and end' do new_source = autocorrect_source(<<-RUBY.strip_indent) module SomeModule do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) module SomeModule do_something end RUBY end end context 'when EnforcedStyle is empty_lines' do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines' } } it 'registers an offense for module body not starting or ending with a ' \ 'blank' do inspect_source(<<-RUBY.strip_indent) module SomeModule do_something end RUBY expect(cop.messages) .to eq(['Empty line missing at module body beginning.', 'Empty line missing at module body end.']) end it 'registers an offense for module body not ending with a blank' do expect_offense(<<-RUBY.strip_indent) module SomeModule do_something end ^ Empty line missing at module body end. RUBY end it 'autocorrects beginning and end' do new_source = autocorrect_source(<<-RUBY.strip_indent) module SomeModule do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) module SomeModule do_something end RUBY end it 'ignores modules with an empty body' do source = "module A\nend" corrected = autocorrect_source(source) expect(corrected).to eq(source) end end context 'when EnforcedStyle is empty_lines_except_namespace' do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines_except_namespace' } } context 'when only child is class' do it 'requires no empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY end it 'registers offence for namespace body starting with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY expect(cop.messages).to eq([extra_begin]) end it 'registers offence for namespace body ending with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY expect(cop.messages).to eq([extra_end]) end it 'registers offences for namespaced module body not starting '\ 'with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY expect(cop.messages).to eq([missing_begin]) end it 'registers offences for namespaced module body not ending '\ 'with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY expect(cop.messages).to eq([missing_end]) end it 'autocorrects beginning and end' do new_source = autocorrect_source(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) module Parent module Child do_something end end RUBY end end context 'when only child is class' do it 'requires no empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) module Parent class SomeClass do_something end end RUBY end it 'registers offence for namespace body starting with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent class SomeClass do_something end end RUBY expect(cop.messages).to eq([extra_begin]) end it 'registers offence for namespace body ending with a blank' do inspect_source(<<-RUBY.strip_indent) module Parent class SomeClass do_something end end RUBY expect(cop.messages).to eq([extra_end]) end end context 'when has multiple child modules' do it 'requires empty lines for namespace' do expect_no_offenses(<<-RUBY.strip_indent) module Parent module Mom do_something end module Dad end end RUBY end it 'registers offences for namespace body starting '\ 'and ending without a blank' do inspect_source(<<-RUBY.strip_indent) module Parent module Mom do_something end module Dad end end RUBY expect(cop.messages).to eq([missing_begin, missing_end]) end end end include_examples 'empty_lines_around_class_or_module_body', 'module' end rubocop-0.52.1/spec/rubocop/cop/layout/empty_lines_spec.rb000066400000000000000000000021001322072016200236240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EmptyLines do subject(:cop) { described_class.new } it 'registers an offense for consecutive empty lines' do inspect_source(['test = 5', '', '', '', 'top']) expect(cop.offenses.size).to eq(2) end it 'auto-corrects consecutive empty lines' do corrected = autocorrect_source(['test = 5', '', '', '', 'top']) expect(corrected).to eq ['test = 5', '', 'top'].join("\n") end it 'works when there are no tokens' do expect_no_offenses('#comment') end it 'handles comments' do expect_no_offenses(<<-RUBY.strip_indent) test #comment top RUBY end it 'does not register an offense for empty lines in a string' do expect_no_offenses(<<-RUBY.strip_indent) result = "test string" RUBY end it 'does not register an offense for heredocs with empty lines inside' do expect_no_offenses(<<-RUBY.strip_indent) str = <<-TEXT line 1 line 2 TEXT puts str RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/end_of_line_spec.rb000066400000000000000000000121471322072016200235510ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::EndOfLine, :config do subject(:cop) { described_class.new(config) } shared_examples 'all configurations' do it 'accepts an empty file' do inspect_source_file('') expect(cop.offenses.empty?).to be(true) end end shared_examples 'iso-8859-15' do |eol| it 'can inspect non-UTF-8 encoded source with proper encoding comment' do inspect_source_file(["# coding: ISO-8859-15#{eol}", "# Euro symbol: \xa4#{eol}"]) expect(cop.offenses.size).to eq(1) end end context 'when EnforcedStyle is native' do let(:cop_config) { { 'EnforcedStyle' => 'native' } } let(:messages) do ['Carriage return character ' \ "#{RuboCop::Platform.windows? ? 'missing' : 'detected'}."] end it 'registers an offense for an incorrect EOL' do inspect_source_file(['x=0', '', "y=1\r"]) expect(cop.messages).to eq(messages) expect(cop.offenses.map(&:line)) .to eq([RuboCop::Platform.windows? ? 1 : 3]) end end context 'when EnforcedStyle is crlf' do let(:cop_config) { { 'EnforcedStyle' => 'crlf' } } let(:messages) { ['Carriage return character missing.'] } include_examples 'all configurations' it 'registers an offense for CR+LF' do inspect_source_file(['x=0', '', "y=1\r"]) expect(cop.messages).to eq(messages) expect(cop.offenses.map(&:line)).to eq([1]) end it 'highlights the whole offending line' do inspect_source_file(['x=0', '', "y=1\r"]) expect(cop.highlights).to eq(["x=0\n"]) end it 'does not register offense for no CR at end of file' do inspect_source_file('x=0') expect(cop.offenses.empty?).to be(true) end it 'does not register offenses after __END__' do inspect_source(["x=0\r", '__END__', 'x=0']) expect(cop.offenses.empty?).to be(true) end context 'and there are many lines ending with LF' do it 'registers only one offense' do inspect_source_file(['x=0', '', 'y=1'].join("\n")) expect(cop.messages.size).to eq(1) end include_examples 'iso-8859-15', '' end context 'and the default external encoding is US_ASCII' do around do |example| orig_encoding = Encoding.default_external Encoding.default_external = Encoding::US_ASCII example.run Encoding.default_external = orig_encoding end it 'does not crash on UTF-8 encoded non-ascii characters' do source = ['# encoding: UTF-8', 'class Epd::ReportsController < EpdAreaController', " 'terecht bij uw ROM-coördinator.'", 'end'].join("\r\n") inspect_source_file(source) expect(cop.offenses.empty?).to be(true) end include_examples 'iso-8859-15', '' end context 'and source is a string' do it 'registers an offense' do inspect_source("x=0\ny=1") expect(cop.messages).to eq(['Carriage return character missing.']) end end end context 'when EnforcedStyle is lf' do let(:cop_config) { { 'EnforcedStyle' => 'lf' } } include_examples 'all configurations' it 'registers an offense for CR+LF' do inspect_source_file(['x=0', '', "y=1\r"]) expect(cop.messages).to eq(['Carriage return character detected.']) expect(cop.offenses.map(&:line)).to eq([3]) end it 'highlights the whole offending line' do inspect_source_file(['x=0', '', "y=1\r"]) expect(cop.highlights).to eq(["y=1\r"]) end it 'registers an offense for CR at end of file' do inspect_source_file("x=0\r") expect(cop.messages).to eq(['Carriage return character detected.']) end it 'does not register offenses after __END__' do inspect_source(['x=0', '__END__', "x=0\r"]) expect(cop.offenses.empty?).to be(true) end context 'and there are many lines ending with CR+LF' do it 'registers only one offense' do inspect_source_file(['x=0', '', 'y=1'].join("\r\n")) expect(cop.messages.size).to eq(1) end include_examples 'iso-8859-15', "\r" end context 'and the default external encoding is US_ASCII' do around do |example| orig_encoding = Encoding.default_external Encoding.default_external = Encoding::US_ASCII example.run Encoding.default_external = orig_encoding end it 'does not crash on UTF-8 encoded non-ascii characters' do source = ['# encoding: UTF-8', 'class Epd::ReportsController < EpdAreaController', " 'terecht bij uw ROM-coördinator.'", 'end'].join("\n") inspect_source_file(source) expect(cop.offenses.empty?).to be(true) end include_examples 'iso-8859-15', "\r" end context 'and source is a string' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) x=0\r ^^^ Carriage return character detected. RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/extra_spacing_spec.rb000066400000000000000000000253111322072016200241340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::ExtraSpacing, :config do subject(:cop) { described_class.new(config) } shared_examples 'common behavior' do it 'registers an offense for alignment with token not preceded by space' do # The = and the ( are on the same column, but this is not for alignment, # it's just a mistake. inspect_source(<<-RUBY.strip_indent) website("example.org") name = "Jill" RUBY expect(cop.offenses.size).to eq(1) end it 'accepts aligned values of an implicit hash literal' do source = <<-RUBY.strip_indent register(street1: '1 Market', street2: '#200', :city => 'Some Town', state: 'CA', postal_code:'99999-1111') RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'accepts space between key and value in a hash with hash rockets' do source = <<-RUBY.strip_indent ospf_h = { 'ospfTest' => { 'foo' => { area: '0.0.0.0', cost: 10, hello: 30, pass: true }, 'longname' => { area: '1.1.1.38', pass: false }, 'vlan101' => { area: '2.2.2.101', cost: 5, hello: 20, pass: true } }, 'TestOspfInt' => { 'x' => { area: '0.0.0.19' }, 'vlan290' => { area: '2.2.2.29', cost: 200, hello: 30, pass: true }, 'port-channel100' => { area: '3.2.2.29', cost: 25, hello: 50, pass: false } } } RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'when spaces are present in a single-line hash literal' do it 'registers an offense for hashes with symbol keys' do inspect_source('hash = {a: 1, b: 2}') expect(cop.offenses.size).to eq(3) end it 'registers an offense for hashes with hash rockets' do source = <<-RUBY.strip_indent let(:single_line_hash) { {"a" => "1", "b" => "2"} } RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(2) end end it 'can handle extra space before a float' do source = <<-RUBY.strip_indent {:a => "a", :b => [nil, 2.5]} RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'can handle unary plus in an argument list' do source = <<-RUBY.strip_indent assert_difference(MyModel.count, +2, 3, +3, # Extra spacing only here. 4,+4) RUBY inspect_source(source) expect(cop.offenses.map { |o| o.location.line }).to eq([2]) end it 'gives the correct line' do inspect_source(<<-RUBY.strip_indent) class A < String end RUBY expect(cop.offenses.first.location.line).to eq(1) end it 'registers an offense for double extra spacing on variable assignment' do inspect_source('m = "hello"') expect(cop.offenses.size).to eq(1) end it 'ignores whitespace at the beginning of the line' do expect_no_offenses(' m = "hello"') end it 'ignores whitespace inside a string' do expect_no_offenses('m = "hello this"') end it 'ignores trailing whitespace' do inspect_source([' class Benchmarker < Performer ', ' end']) expect(cop.offenses.empty?).to be(true) end it 'registers an offense on class inheritance' do inspect_source(<<-RUBY.strip_indent) class A < String end RUBY expect(cop.offenses.size).to eq(1) end it 'auto-corrects a line indented with mixed whitespace' do new_source = autocorrect_source(<<-RUBY.strip_indent) website("example.org") name = "Jill" RUBY expect(new_source).to eq(<<-RUBY.strip_indent) website("example.org") name = "Jill" RUBY end it 'auto-corrects the class inheritance' do new_source = autocorrect_source(<<-RUBY.strip_indent) class A < String end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class A < String end RUBY end end sources = { 'lining up assignments' => <<-RUBY.strip_indent, website = "example.org" name = "Jill" RUBY 'lining up assignments with empty lines and comments in between' => <<-RUBY.strip_indent, a += 1 # Comment aa = 2 bb = 3 a ||= 1 RUBY 'aligning with the same character' => <<-RUBY.strip_margin('|'), | y, m = (year * 12 + (mon - 1) + n).divmod(12) | m, = (m + 1) .divmod(1) RUBY 'lining up different kinds of assignments' => <<-RUBY.strip_indent, type_name ||= value.class.name if value type_name = type_name.to_s if type_name type_name = value.class.name if value type_name += type_name.to_s unless type_name a += 1 aa -= 2 RUBY 'aligning comments on non-adjacent lines' => <<-RUBY.strip_indent, include_examples 'aligned', 'var = until', 'test' include_examples 'unaligned', "var = if", 'test' RUBY 'aligning = on lines where there are trailing comments' => <<-RUBY.strip_indent, a_long_var_name = 100 # this is 100 short_name1 = 2 clear short_name2 = 2 a_long_var_name = 100 # this is 100 clear short_name3 = 2 # this is 2 a_long_var_name = 100 # this is 100 RUBY 'aligning tokens with empty line between' => <<-RUBY.strip_indent, unless nochdir Dir.chdir "/" # Release old working directory. end File.umask 0000 # Ensure sensible umask. RUBY 'aligning long assignment expressions that include line breaks' => <<-RUBY.strip_indent size_attribute_name = FactoryGirl.create(:attribute, name: 'Size', values: %w{small large}) carrier_attribute_name = FactoryGirl.create(:attribute, name: 'Carrier', values: %w{verizon}) RUBY }.freeze context 'when AllowForAlignment is true' do let(:cop_config) do { 'AllowForAlignment' => true, 'ForceEqualSignAlignment' => false } end include_examples 'common behavior' context 'with extra spacing for alignment purposes' do sources.each do |reason, src| context "such as #{reason}" do it 'allows it' do inspect_source(src) expect(cop.offenses.empty?).to be(true) end end end end end context 'when AllowForAlignment is false' do let(:cop_config) do { 'AllowForAlignment' => false, 'ForceEqualSignAlignment' => false } end include_examples 'common behavior' context 'with extra spacing for alignment purposes' do sources.each do |reason, src| context "such as #{reason}" do it 'registers offense(s)' do inspect_source(src) expect(cop.offenses.empty?).to be(false) end end end end end context 'when ForceEqualSignAlignment is true' do let(:cop_config) do { 'AllowForAlignment' => true, 'ForceEqualSignAlignment' => true } end it 'registers an offense if consecutive assignments are not aligned' do inspect_source(<<-RUBY.strip_indent) a = 1 bb = 2 ccc = 3 RUBY expect(cop.offenses.size).to eq(3) expect(cop.messages).to eq( ['`=` is not aligned with the following assignment.', '`=` is not aligned with the preceding assignment.', '`=` is not aligned with the preceding assignment.'] ) end it 'does not register an offense if assignments are separated by blanks' do expect_no_offenses(<<-RUBY.strip_indent) a = 1 bb = 2 ccc = 3 RUBY end it 'does not register an offense if assignments are aligned' do expect_no_offenses(<<-RUBY.strip_indent) a = 1 bb = 2 ccc = 3 RUBY end it 'aligns the first assignment with the following assignment' do expect_no_offenses(<<-RUBY.strip_indent) # comment a = 1 bb = 2 RUBY end it 'autocorrects consecutive assignments which are not aligned' do new_source = autocorrect_source(<<-RUBY.strip_indent) a = 1 bb = 2 ccc = 3 abcde = 1 a = 2 abc = 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = 1 bb = 2 ccc = 3 abcde = 1 a = 2 abc = 3 RUBY end it 'autocorrects consecutive operator assignments which are not aligned' do new_source = autocorrect_source(<<-RUBY.strip_indent) a += 1 bb = 2 ccc <<= 3 abcde = 1 a *= 2 abc ||= 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a += 1 bb = 2 ccc <<= 3 abcde = 1 a *= 2 abc ||= 3 RUBY end it 'autocorrects consecutive aref assignments which are not aligned' do new_source = autocorrect_source(<<-RUBY.strip_indent) a[1] = 1 bb[2,3] = 2 ccc[:key] = 3 abcde[0] = 1 a = 2 abc += 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a[1] = 1 bb[2,3] = 2 ccc[:key] = 3 abcde[0] = 1 a = 2 abc += 3 RUBY end it 'autocorrects consecutive attribute assignments which are not aligned' do new_source = autocorrect_source(<<-RUBY.strip_indent) a.attr = 1 bb &&= 2 ccc.s = 3 abcde.blah = 1 a.attribute_name = 2 abc[1] = 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a.attr = 1 bb &&= 2 ccc.s = 3 abcde.blah = 1 a.attribute_name = 2 abc[1] = 3 RUBY end it 'does not register an offense when optarg equals is not aligned with ' \ 'assignment equals sign' do inspect_source(<<-RUBY.strip_indent) def method(arg = 1) var = arg end RUBY expect(cop.offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/layout/first_array_element_line_break_spec.rb000066400000000000000000000066331322072016200275240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::FirstArrayElementLineBreak do subject(:cop) { described_class.new } context 'elements listed on the first line' do let(:source) do <<-RUBY.strip_indent a = [:a, :b] RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq([':a']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) # Alignment for the first element is set by IndentationWidth cop, # the rest of the elements should be aligned using the AlignArray cop. expect(new_source).to eq(<<-RUBY.strip_indent) a = [ :a, :b] RUBY end end context 'word arrays' do let(:source) do <<-RUBY.strip_indent %w(a b c d) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['a']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) %w( a b c d) RUBY end end context 'array nested in a method call' do let(:source) do <<-RUBY.strip_indent method([:foo, :bar]) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq([':foo']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) method([ :foo, :bar]) RUBY end end context 'masgn implicit arrays' do let(:source) do <<-RUBY.strip_indent a, b, c = 1, 2, 3 RUBY end let(:correct_source) do ['a, b,', 'c = ', '1,', '2, 3', ''].join("\n") end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['1']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq(correct_source) end end context 'send implicit arrays' do let(:source) do <<-RUBY.strip_indent a .c = 1, 2, 3 RUBY end let(:correct_source) do ['a', '.c = ', '1,', '2, 3', ''].join("\n") end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['1']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq(correct_source) end end it 'ignores properly formatted implicit arrays' do expect_no_offenses(<<-RUBY.strip_indent) a, b, c = 1, 2, 3 RUBY end it 'ignores elements listed on a single line' do expect_no_offenses(<<-RUBY.strip_indent) b = [ :a, :b] RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/first_hash_element_line_break_spec.rb000066400000000000000000000040011322072016200273140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::FirstHashElementLineBreak do subject(:cop) { described_class.new } context 'elements listed on the first line' do let(:source) do <<-RUBY.strip_indent a = { a: 1, b: 2} RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['a: 1']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'a = { ', 'a: 1,', ' b: 2}', '' ].join("\n")) end end context 'hash nested in a method call' do let(:source) do <<-RUBY.strip_indent method({ foo: 1, bar: 2 }) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['foo: 1']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'method({ ', 'foo: 1,', ' bar: 2 })', '' ].join("\n")) end end it 'ignores implicit hashes in method calls with parens' do expect_no_offenses(<<-RUBY.strip_indent) method( foo: 1, bar: 2) RUBY end it 'ignores implicit hashes in method calls without parens' do expect_no_offenses(<<-RUBY.strip_indent) method foo: 1, bar:2 RUBY end it 'ignores implicit hashes in method calls that are improperly formatted' do # These are covered by Style/FirstMethodArgumentLineBreak expect_no_offenses(<<-RUBY.strip_indent) method(foo: 1, bar: 2) RUBY end it 'ignores elements listed on a single line' do expect_no_offenses(<<-RUBY.strip_indent) b = { a: 1, b: 2} RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/first_method_argument_line_break_spec.rb000066400000000000000000000042531322072016200300530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::FirstMethodArgumentLineBreak do subject(:cop) { described_class.new } context 'args listed on the first line' do let(:source) do <<-RUBY.strip_indent foo(bar, baz) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['bar']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'foo(', 'bar,', ' baz)', '' ].join("\n")) end end context 'hash arg spanning multiple lines' do let(:source) do <<-RUBY.strip_indent something(3, bar: 1, baz: 2) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['3']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'something(', '3, bar: 1,', 'baz: 2)', '' ].join("\n")) end end context 'hash arg without a line break before the first pair' do let(:source) do <<-RUBY.strip_indent something(bar: 1, baz: 2) RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['bar: 1']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'something(', 'bar: 1,', 'baz: 2)', '' ].join("\n")) end end it 'ignores arguments listed on a single line' do expect_no_offenses('foo(bar, baz, bing)') end it 'ignores arguments without parens' do expect_no_offenses(<<-RUBY.strip_indent) foo bar, baz RUBY end it 'ignores methods without arguments' do expect_no_offenses('foo') end end rubocop-0.52.1/spec/rubocop/cop/layout/first_method_parameter_line_break_spec.rb000066400000000000000000000052471322072016200302150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::FirstMethodParameterLineBreak do subject(:cop) { described_class.new } context 'params listed on the first line' do let(:source) do <<-RUBY.strip_indent def foo(bar, baz) do_something end RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['bar']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'def foo(', 'bar,', ' baz)', ' do_something', 'end', '' ].join("\n")) end end context 'params on first line of singleton method' do let(:source) do <<-RUBY.strip_indent def self.foo(bar, baz) do_something end RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['bar']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'def self.foo(', 'bar,', ' baz)', ' do_something', 'end', '' ].join("\n")) end end it 'ignores params listed on a single line' do expect_no_offenses(<<-RUBY.strip_indent) def foo(bar, baz, bing) do_something end RUBY end it 'ignores params without parens' do expect_no_offenses(<<-RUBY.strip_indent) def foo bar, baz do_something end RUBY end it 'ignores single-line methods' do expect_no_offenses('def foo(bar, baz) ; bing ; end') end it 'ignores methods without params' do expect_no_offenses(<<-RUBY.strip_indent) def foo bing end RUBY end context 'params with default values' do let(:source) do <<-RUBY.strip_indent def foo(bar = [], baz = 2) do_something end RUBY end it 'detects the offense' do inspect_source(source) expect(cop.offenses.length).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['bar = []']) end it 'autocorrects the offense' do new_source = autocorrect_source(source) expect(new_source).to eq([ 'def foo(', 'bar = [],', ' baz = 2)', ' do_something', 'end', '' ].join("\n")) end end end rubocop-0.52.1/spec/rubocop/cop/layout/first_parameter_indentation_spec.rb000066400000000000000000000313521322072016200270720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::FirstParameterIndentation do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config .new('Layout/FirstParameterIndentation' => { 'EnforcedStyle' => style, 'SupportedStyles' => %w[consistent special_for_inner_method_call special_for_inner_method_call_in_parentheses] }, 'Layout/IndentationWidth' => { 'Width' => indentation_width }) end shared_examples 'common behavior' do context 'when IndentationWidth:Width is 2' do let(:indentation_width) { 2 } it 'registers an offense for an over-indented first parameter' do inspect_source(<<-RUBY.strip_indent) run( :foo, bar: 3 ) RUBY expect(cop.messages).to eq(['Indent the first parameter one step ' \ 'more than the start of the ' \ 'previous line.']) expect(cop.highlights).to eq([':foo']) end it 'registers an offense for an under-indented first parameter' do inspect_source(<<-RUBY.strip_indent) run( :foo, bar: 3 ) RUBY expect(cop.highlights).to eq([':foo']) end it 'registers an offense on lines affected by another offense' do inspect_source(<<-RUBY.strip_indent) foo( bar( 7 ) ) RUBY expect(cop.highlights).to eq([['bar(', ' 7', ')'].join("\n"), '7']) expect(cop.messages) .to eq(['Indent the first parameter one step more than ' \ 'the start of the previous line.', 'Bad indentation of the first parameter.']) end it 'auto-corrects nested offenses' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo( bar( 7 ) ) RUBY # The first `)` Will be corrected by IndentationConsistency. expect(new_source).to eq(<<-RUBY.strip_indent) foo( bar( 7 ) ) RUBY end context 'for assignment' do it 'accepts a correctly indented first parameter and does not care ' \ 'about the second parameter' do inspect_source(<<-RUBY.strip_indent) x = run( :foo, bar: 3 ) RUBY expect(cop.offenses.empty?).to be(true) end context 'with line break' do it 'accepts a correctly indented first parameter' do expect_no_offenses(<<-RUBY.strip_indent) x = run( :foo) RUBY end it 'registers an offense for an under-indented first parameter' do inspect_source(<<-RUBY.strip_indent) @x = run( :foo) RUBY expect(cop.highlights).to eq([':foo']) end end end it 'accepts a first parameter that is not preceded by a line break' do expect_no_offenses(<<-RUBY.strip_indent) run :foo, bar: 3 RUBY end context 'when the receiver contains a line break' do it 'accepts a correctly indented first parameter' do expect_no_offenses(<<-RUBY.strip_indent) puts x. merge( b: 2 ) RUBY end it 'registers an offense for an over-indented first parameter' do inspect_source(<<-RUBY.strip_indent) puts x. merge( b: 2 ) RUBY expect(cop.messages).to eq(['Indent the first parameter one step ' \ 'more than the start of the ' \ 'previous line.']) expect(cop.highlights).to eq(['b: 2']) end it 'accepts a correctly indented first parameter preceded by an ' \ 'empty line' do inspect_source(<<-RUBY.strip_indent) puts x. merge( b: 2 ) RUBY expect(cop.offenses.empty?).to be(true) end context 'when preceded by a comment line' do it 'accepts a correctly indented first parameter' do expect_no_offenses(<<-RUBY.strip_indent) puts x. merge( # EOL comment # comment b: 2 ) RUBY end it 'registers an offense for an under-indented first parameter' do inspect_source(<<-RUBY.strip_indent) puts x. merge( # comment b: 2 ) RUBY expect(cop.messages).to eq(['Indent the first parameter one step ' \ 'more than the start of the previous ' \ 'line (not counting the comment).']) expect(cop.highlights).to eq(['b: 2']) end end end it 'accepts method calls with no parameters' do expect_no_offenses(<<-RUBY.strip_indent) run() run_again RUBY end it 'accepts operator calls' do expect_no_offenses(<<-RUBY.strip_indent) params = default_cfg.keys - %w(Description) - cfg.keys RUBY end it 'does not view []= as an outer method call' do expect_no_offenses(<<-RUBY.strip_indent) @subject_results[subject] = original.update( mutation_results: (dup << mutation_result), tests: test_result.tests ) RUBY end it 'does not view chained call as an outer method call' do inspect_source(<<-'RUBY'.strip_margin('|')) | A = Regexp.union( | /[A-Za-z_][A-Za-z\d_]*[!?=]?/, | *AST::Types::OPERATOR_METHODS.map(&:to_s) | ).freeze RUBY expect(cop.offenses.empty?).to be(true) end it 'auto-corrects an under-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) x = run( :foo, bar: 3 ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) x = run( :foo, bar: 3 ) RUBY end end context 'when IndentationWidth:Width is 4' do let(:indentation_width) { 4 } it 'auto-corrects an over-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) run( :foo, bar: 3) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) run( :foo, bar: 3) RUBY end end context 'when indentation width is overridden for this cop only' do let(:config) do RuboCop::Config .new('Layout/FirstParameterIndentation' => { 'EnforcedStyle' => style, 'SupportedStyles' => %w[consistent special_for_inner_method_call special_for_inner_method_call_in_parentheses], 'IndentationWidth' => 4 }, 'Layout/IndentationWidth' => { 'Width' => 2 }) end it 'accepts a correctly indented first parameter' do expect_no_offenses(<<-RUBY.strip_indent) run( :foo, bar: 3 ) RUBY end it 'auto-corrects an over-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) run( :foo, bar: 3) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) run( :foo, bar: 3) RUBY end end end context 'when EnforcedStyle is special_for_inner_method_call' do let(:style) { 'special_for_inner_method_call' } let(:indentation_width) { 2 } include_examples 'common behavior' context 'for method calls within method calls' do context 'with outer parentheses' do it 'registers an offense for an over-indented first parameter' do expect_offense(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) ^^^^^^ Indent the first parameter one step more than `defaults.merge(`. RUBY end end context 'without outer parentheses' do it 'accepts a first parameter with special indentation' do expect_no_offenses(<<-RUBY.strip_indent) run :foo, defaults.merge( bar: 3) RUBY end end it 'auto-corrects an over-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY end end end context 'when EnforcedStyle is ' \ 'special_for_inner_method_call_in_parentheses' do let(:style) { 'special_for_inner_method_call_in_parentheses' } let(:indentation_width) { 2 } include_examples 'common behavior' context 'for method calls within method calls' do context 'with outer parentheses' do it 'registers an offense for an over-indented first parameter' do expect_offense(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) ^^^^^^ Indent the first parameter one step more than `defaults.merge(`. RUBY end it 'registers an offense for an under-indented first parameter' do expect_offense(<<-RUBY.strip_indent) run(:foo, defaults. merge( bar: 3)) ^^^^^^ Indent the first parameter one step more than the start of the previous line. RUBY end it 'accepts a correctly indented first parameter in interpolation' do expect_no_offenses(<<-'RUBY'.strip_indent) puts %(

#{Array( 42 )}

) RUBY end it 'accepts a correctly indented first parameter with fullwidth ' \ 'characters' do inspect_source(<<-RUBY.strip_indent) puts('Ruby', f( a)) RUBY expect(cop.offenses.empty?).to be(true) end end context 'without outer parentheses' do it 'accepts a first parameter with consistent style indentation' do expect_no_offenses(<<-RUBY.strip_indent) run :foo, defaults.merge( bar: 3) RUBY end end it 'auto-corrects an over-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY end end end context 'when EnforcedStyle is consistent' do let(:style) { 'consistent' } let(:indentation_width) { 2 } include_examples 'common behavior' context 'for method calls within method calls' do it 'registers an offense for an over-indented first parameter' do expect_offense(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) ^^^^^^ Indent the first parameter one step more than the start of the previous line. RUBY end it 'accepts first parameter indented relative to previous line' do expect_no_offenses(<<-RUBY.strip_indent) @diagnostics.process(Diagnostic.new( :error, :token, { :token => name }, location)) RUBY end it 'auto-corrects an over-indented first parameter' do new_source = autocorrect_source(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) run(:foo, defaults.merge( bar: 3)) RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/indent_array_spec.rb000066400000000000000000000322221322072016200237630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::IndentArray do subject(:cop) { described_class.new(config) } let(:config) do supported_styles = { 'SupportedStyles' => %w[special_inside_parentheses consistent align_brackets] } RuboCop::Config.new('Layout/IndentArray' => cop_config.merge(supported_styles).merge( 'IndentationWidth' => cop_indent ), 'Layout/IndentationWidth' => { 'Width' => 2 }) end let(:cop_config) { { 'EnforcedStyle' => 'special_inside_parentheses' } } let(:cop_indent) { nil } # use indent from Layout/IndentationWidth context 'when array is operand' do it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) a << [ 1 ] RUBY end it 'registers an offense for incorrectly indented first element' do inspect_source(<<-RUBY.strip_indent) a << [ 1 ] RUBY expect(cop.highlights).to eq(['1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects incorrectly indented first element' do corrected = autocorrect_source(<<-RUBY.strip_indent) a << [ 1 ] RUBY expect(corrected).to eq <<-RUBY.strip_indent a << [ 1 ] RUBY end it 'registers an offense for incorrectly indented ]' do inspect_source(<<-RUBY.strip_indent) a << [ ] RUBY expect(cop.highlights).to eq([']']) expect(cop.messages) .to eq(['Indent the right bracket the same as the start of the line ' \ 'where the left bracket is.']) expect(cop.config_to_allow_offenses.empty?).to be(true) end context 'when indentation width is overridden for this cop' do let(:cop_indent) { 4 } it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) a << [ 1 ] RUBY end it 'registers an offense for incorrectly indented first element' do inspect_source(<<-RUBY.strip_indent) a << [ 1 ] RUBY expect(cop.highlights).to eq(['1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end end context 'when array is argument to setter' do it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) config.rack_cache = [ "rails:/", "rails:/", false ] RUBY end it 'registers an offense for incorrectly indented first element' do inspect_source(<<-RUBY.strip_margin('|')) | config.rack_cache = [ | "rails:/", | "rails:/", | false | ] RUBY expect(cop.highlights).to eq(['"rails:/"']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'when array is right hand side in assignment' do it 'registers an offense for incorrectly indented first element' do inspect_source(<<-RUBY.strip_indent) a = [ 1, 2, 3 ] RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to the ' \ 'start of the line where the left square bracket is.']) expect(cop.highlights).to eq(['1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects incorrectly indented first element' do corrected = autocorrect_source(<<-RUBY.strip_indent) a = [ 1, 2, 3 ] RUBY expect(corrected).to eq <<-RUBY.strip_indent a = [ 1, 2, 3 ] RUBY end it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1 ] RUBY end it 'accepts several elements per line' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1, 2 ] RUBY end it 'accepts a first element on the same line as the left bracket' do expect_no_offenses(<<-RUBY.strip_indent) a = [1, 2] RUBY end it 'accepts single line array' do expect_no_offenses('a = [1, 2]') end it 'accepts an empty array' do expect_no_offenses('a = []') end it 'accepts multi-assignments with brackets' do expect_no_offenses('a, b = [b, a]') end it 'accepts multi-assignments with no brackets' do expect_no_offenses('a, b = b, a') end end context 'when array is method argument' do context 'and arguments are surrounded by parentheses' do context 'and EnforcedStyle is special_inside_parentheses' do it 'accepts special indentation for first argument' do expect_no_offenses(<<-RUBY.strip_indent) h = [ 1 ] func([ 1 ]) func(x, [ 1 ]) h = [1 ] func([1 ]) func(x, [1 ]) RUBY end it "registers an offense for 'consistent' indentation" do inspect_source(<<-RUBY.strip_indent) func([ 1 ]) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to ' \ 'the first position after the preceding left parenthesis.', 'Indent the right bracket the same as the first position ' \ 'after the preceding left parenthesis.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'consistent') end it "registers an offense for 'align_brackets' indentation" do inspect_source(<<-RUBY.strip_indent) var = [ 1 ] RUBY # since there are no parens, warning message is for 'consistent' style expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to ' \ 'the start of the line where the left square bracket is.', 'Indent the right bracket the same as the start of the ' \ 'line where the left bracket is.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'align_brackets') end it 'auto-corrects incorrectly indented first element' do corrected = autocorrect_source(<<-RUBY.strip_indent) func([ 1 ]) RUBY expect(corrected).to eq <<-RUBY.strip_indent func([ 1 ]) RUBY end it 'accepts special indentation for second argument' do expect_no_offenses(<<-RUBY.strip_indent) body.should have_tag("input", [ :name]) RUBY end it 'accepts normal indentation for array within array' do expect_no_offenses(<<-RUBY.strip_indent) puts( [ [1, 2] ] ) RUBY end end context 'and EnforcedStyle is consistent' do let(:cop_config) { { 'EnforcedStyle' => 'consistent' } } it 'accepts normal indentation for first argument' do expect_no_offenses(<<-RUBY.strip_indent) h = [ 1 ] func([ 1 ]) func(x, [ 1 ]) h = [1 ] func([1 ]) func(x, [1 ]) RUBY end it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) func([ 1 ]) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to ' \ 'the start of the line where the left square bracket is.', 'Indent the right bracket the same as the start of the ' \ 'line where the left bracket is.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'special_inside_parentheses') end it 'accepts normal indentation for second argument' do expect_no_offenses(<<-RUBY.strip_indent) body.should have_tag("input", [ :name]) RUBY end end end context 'and argument are not surrounded by parentheses' do it 'accepts bracketless array' do expect_no_offenses('func 1, 2') end it 'accepts single line array with brackets' do expect_no_offenses('func x, [1, 2]') end it 'accepts a correctly indented multi-line array with brackets' do expect_no_offenses(<<-RUBY.strip_indent) func x, [ 1, 2] RUBY end it 'registers an offense for incorrectly indented multi-line array ' \ 'with brackets' do inspect_source(<<-RUBY.strip_indent) func x, [ 1, 2] RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to the ' \ 'start of the line where the left square bracket is.']) expect(cop.highlights).to eq(['1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end end context 'when EnforcedStyle is align_brackets' do let(:cop_config) { { 'EnforcedStyle' => 'align_brackets' } } it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1 ] RUBY end it 'accepts several elements per line' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1, 2 ] RUBY end it 'accepts a first element on the same line as the left bracket' do expect_no_offenses(<<-RUBY.strip_indent) a = [1, 2] RUBY end it 'accepts single line array' do expect_no_offenses('a = [1, 2]') end it 'accepts an empty array' do expect_no_offenses('a = []') end it 'accepts multi-assignments with brackets' do expect_no_offenses('a, b = [b, a]') end it 'accepts multi-assignments with no brackets' do expect_no_offenses('a, b = b, a') end context "when 'consistent' style is used" do it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) func([ 1 ]) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to the' \ ' position of the opening bracket.', 'Indent the right bracket the same as the left bracket.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'consistent') end it 'auto-corrects incorrectly indented first element' do corrected = autocorrect_source(<<-RUBY.strip_indent) var = [ 1 ] RUBY expect(corrected).to eq <<-RUBY.strip_indent var = [ 1 ] RUBY end end context "when 'special_inside_parentheses' style is used" do it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) var = [ 1 ] func([ 1 ]) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in an array, relative to the' \ ' position of the opening bracket.', 'Indent the right bracket the same as the left bracket.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'special_inside_parentheses') end end it 'registers an offense for incorrectly indented ]' do inspect_source(<<-RUBY.strip_indent) a << [ ] RUBY expect(cop.highlights).to eq([']']) expect(cop.messages) .to eq(['Indent the right bracket the same as the left bracket.']) expect(cop.config_to_allow_offenses.empty?).to be(true) end context 'when indentation width is overridden for this cop' do let(:cop_indent) { 4 } it 'accepts correctly indented first element' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1 ] RUBY end it 'autocorrects indentation which does not match IndentationWidth' do new_source = autocorrect_source(<<-RUBY.strip_indent) a = [ 1 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = [ 1 ] RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/indent_assignment_spec.rb000066400000000000000000000047271322072016200250260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::IndentAssignment, :config do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentAssignment' => { 'IndentationWidth' => cop_indent }, 'Layout/IndentationWidth' => { 'Width' => 2 }) end let(:cop_indent) { nil } # use indentation with from Layout/IndentationWidth let(:message) do 'Indent the first line of the right-hand-side of a multi-line assignment.' end it 'registers an offense for incorrectly indented rhs' do inspect_source(<<-RUBY.strip_indent) a = if b ; end RUBY expect(cop.offenses.length).to eq(1) expect(cop.highlights).to eq(['if b ; end']) expect(cop.message).to eq(message) end it 'allows assignments that do not start on a newline' do expect_no_offenses(<<-RUBY.strip_indent) a = if b foo end RUBY end it 'allows a properly indented rhs' do expect_no_offenses(<<-RUBY.strip_indent) a = if b ; end RUBY end it 'allows a properly indented rhs with fullwidth characters' do expect_no_offenses(<<-RUBY.strip_indent) f 'Ruby', a = b RUBY end it 'registers an offense for multi-lhs' do inspect_source(<<-RUBY.strip_indent) a, b = if b ; end RUBY expect(cop.offenses.length).to eq(1) expect(cop.highlights).to eq(['if b ; end']) expect(cop.message).to eq(message) end it 'ignores comparison operators' do expect_no_offenses(<<-RUBY.strip_indent) a === if b ; end RUBY end it 'auto-corrects indentation' do new_source = autocorrect_source( <<-RUBY.strip_indent a = if b ; end RUBY ) expect(new_source) .to eq(<<-RUBY.strip_indent) a = if b ; end RUBY end context 'when indentation width is overridden for this cop only' do let(:cop_indent) { 7 } it 'allows a properly indented rhs' do expect_no_offenses(<<-RUBY.strip_indent) a = if b ; end RUBY end it 'auto-corrects indentation' do new_source = autocorrect_source( <<-RUBY.strip_indent a = if b ; end RUBY ) expect(new_source) .to eq(<<-RUBY.strip_indent) a = if b ; end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/indent_hash_spec.rb000066400000000000000000000345261322072016200236010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::IndentHash do subject(:cop) { described_class.new(config) } let(:config) do supported_styles = { 'SupportedStyles' => %w[special_inside_parentheses consistent align_braces] } RuboCop::Config.new('Layout/AlignHash' => align_hash_config, 'Layout/IndentHash' => cop_config.merge(supported_styles).merge( 'IndentationWidth' => cop_indent ), 'Layout/IndentationWidth' => { 'Width' => 2 }) end let(:align_hash_config) do { 'Enabled' => true, 'EnforcedColonStyle' => 'key', 'EnforcedHashRocketStyle' => 'key' } end let(:cop_config) { { 'EnforcedStyle' => 'special_inside_parentheses' } } let(:cop_indent) { nil } # use indentation width from Layout/IndentationWidth shared_examples 'right brace' do it 'registers an offense for incorrectly indented }' do inspect_source(<<-RUBY.strip_indent) a << { } RUBY expect(cop.highlights).to eq(['}']) expect(cop.messages) .to eq(['Indent the right brace the same as the start of the line ' \ 'where the left brace is.']) expect(cop.config_to_allow_offenses.empty?).to be(true) end end context 'when the AlignHash style is separator for :' do let(:align_hash_config) do { 'Enabled' => true, 'EnforcedColonStyle' => 'separator', 'EnforcedHashRocketStyle' => 'key' } end it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a << { a: 1, aaa: 222 } RUBY end it 'registers an offense for incorrectly indented first pair with :' do inspect_source(<<-RUBY.strip_indent) a << { a: 1, aaa: 222 } RUBY expect(cop.highlights).to eq(['a: 1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end include_examples 'right brace' end context 'when the AlignHash style is separator for =>' do let(:align_hash_config) do { 'Enabled' => true, 'EnforcedColonStyle' => 'key', 'EnforcedHashRocketStyle' => 'separator' } end it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a << { 'a' => 1, 'aaa' => 222 } RUBY end it 'registers an offense for incorrectly indented first pair with =>' do inspect_source(<<-RUBY.strip_indent) a << { 'a' => 1, 'aaa' => 222 } RUBY expect(cop.highlights).to eq(["'a' => 1"]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end include_examples 'right brace' end context 'when hash is operand' do it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a << { a: 1 } RUBY end it 'registers an offense for incorrectly indented first pair' do inspect_source(<<-RUBY.strip_indent) a << { a: 1 } RUBY expect(cop.highlights).to eq(['a: 1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects incorrectly indented first pair' do corrected = autocorrect_source(<<-RUBY.strip_indent) a << { a: 1 } RUBY expect(corrected).to eq <<-RUBY.strip_indent a << { a: 1 } RUBY end include_examples 'right brace' end context 'when hash is argument to setter' do it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) config.rack_cache = { :metastore => "rails:/", :entitystore => "rails:/", :verbose => false } RUBY end it 'registers an offense for incorrectly indented first pair' do inspect_source(<<-RUBY.strip_margin('|')) | config.rack_cache = { | :metastore => "rails:/", | :entitystore => "rails:/", | :verbose => false | } RUBY expect(cop.highlights).to eq([':metastore => "rails:/"']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'when hash is right hand side in assignment' do it 'registers an offense for incorrectly indented first pair' do inspect_source(<<-RUBY.strip_indent) a = { a: 1, b: 2, c: 3 } RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the ' \ 'start of the line where the left curly brace is.']) expect(cop.highlights).to eq(['a: 1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects incorrectly indented first pair' do corrected = autocorrect_source(<<-RUBY.strip_indent) a = { a: 1, b: 2, c: 3 } RUBY expect(corrected).to eq <<-RUBY.strip_indent a = { a: 1, b: 2, c: 3 } RUBY end it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a = { a: 1 } RUBY end it 'accepts several pairs per line' do expect_no_offenses(<<-RUBY.strip_indent) a = { a: 1, b: 2 } RUBY end it 'accepts a first pair on the same line as the left brace' do expect_no_offenses(<<-RUBY.strip_indent) a = { "a" => 1, "b" => 2 } RUBY end it 'accepts single line hash' do expect_no_offenses('a = { a: 1, b: 2 }') end it 'accepts an empty hash' do expect_no_offenses('a = {}') end context 'when indentation width is overridden for this cop' do let(:cop_indent) { 3 } it 'auto-corrects incorrectly indented first pair' do corrected = autocorrect_source(<<-RUBY.strip_indent) a = { a: 1, b: 2, c: 3 } RUBY expect(corrected).to eq <<-RUBY.strip_indent a = { a: 1, b: 2, c: 3 } RUBY end it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a = { a: 1 } RUBY end end end context 'when hash is method argument' do context 'and arguments are surrounded by parentheses' do context 'and EnforcedStyle is special_inside_parentheses' do it 'accepts special indentation for first argument' do expect_no_offenses(<<-RUBY.strip_indent) h = { a: 1 } func({ a: 1 }) func(x, { a: 1 }) h = { a: 1 } func({ a: 1 }) func(x, { a: 1 }) RUBY end it "registers an offense for 'consistent' indentation" do inspect_source(<<-RUBY.strip_indent) func({ a: 1 }) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the' \ ' first position after the preceding left parenthesis.', 'Indent the right brace the same as the first position ' \ 'after the preceding left parenthesis.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'consistent') end it "registers an offense for 'align_braces' indentation" do inspect_source(<<-RUBY.strip_indent) var = { a: 1 } RUBY # since there are no parens, warning message is for 'consistent' style expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the' \ ' start of the line where the left curly brace is.', 'Indent the right brace the same as the start of the ' \ 'line where the left brace is.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'align_braces') end it 'auto-corrects incorrectly indented first pair' do corrected = autocorrect_source(<<-RUBY.strip_indent) func({ a: 1 }) RUBY expect(corrected).to eq <<-RUBY.strip_indent func({ a: 1 }) RUBY end it 'accepts special indentation for second argument' do expect_no_offenses(<<-'RUBY'.strip_indent) body.should have_tag("input", :attributes => { :name => /q\[(id_eq)\]/ }) RUBY end it 'accepts normal indentation for hash within hash' do expect_no_offenses(<<-RUBY.strip_indent) scope = scope.where( klass.table_name => { reflection.type => model.base_class.sti_name } ) RUBY end end context 'and EnforcedStyle is consistent' do let(:cop_config) { { 'EnforcedStyle' => 'consistent' } } it 'accepts normal indentation for first argument' do expect_no_offenses(<<-RUBY.strip_indent) h = { a: 1 } func({ a: 1 }) func(x, { a: 1 }) h = { a: 1 } func({ a: 1 }) func(x, { a: 1 }) RUBY end it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) func({ a: 1 }) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the' \ ' start of the line where the left curly brace is.', 'Indent the right brace the same as the start of the ' \ 'line where the left brace is.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'special_inside_parentheses') end it 'accepts normal indentation for second argument' do expect_no_offenses(<<-'RUBY'.strip_indent) body.should have_tag("input", :attributes => { :name => /q\[(id_eq)\]/ }) RUBY end end end context 'and argument are not surrounded by parentheses' do it 'accepts braceless hash' do expect_no_offenses('func a: 1, b: 2') end it 'accepts single line hash with braces' do expect_no_offenses('func x, { a: 1, b: 2 }') end it 'accepts a correctly indented multi-line hash with braces' do expect_no_offenses(<<-RUBY.strip_indent) func x, { a: 1, b: 2 } RUBY end it 'registers an offense for incorrectly indented multi-line hash ' \ 'with braces' do inspect_source(<<-RUBY.strip_indent) func x, { a: 1, b: 2 } RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the ' \ 'start of the line where the left curly brace is.']) expect(cop.highlights).to eq(['a: 1']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end end context 'when EnforcedStyle is align_braces' do let(:cop_config) { { 'EnforcedStyle' => 'align_braces' } } it 'accepts correctly indented first pair' do expect_no_offenses(<<-RUBY.strip_indent) a = { a: 1 } RUBY end it 'accepts several pairs per line' do expect_no_offenses(<<-RUBY.strip_indent) a = { a: 1, b: 2 } RUBY end it 'accepts a first pair on the same line as the left brace' do expect_no_offenses(<<-RUBY.strip_indent) a = { "a" => 1, "b" => 2 } RUBY end it 'accepts single line hash' do expect_no_offenses('a = { a: 1, b: 2 }') end it 'accepts an empty hash' do expect_no_offenses('a = {}') end context "when 'consistent' style is used" do it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) func({ a: 1 }) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the' \ ' position of the opening brace.', 'Indent the right brace the same as the left brace.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'consistent') end it 'auto-corrects incorrectly indented first pair' do corrected = autocorrect_source(<<-RUBY.strip_indent) var = { a: 1 } RUBY expect(corrected).to eq <<-RUBY.strip_indent var = { a: 1 } RUBY end end context "when 'special_inside_parentheses' style is used" do it 'registers an offense for incorrect indentation' do inspect_source(<<-RUBY.strip_indent) var = { a: 1 } func({ a: 1 }) RUBY expect(cop.messages) .to eq(['Use 2 spaces for indentation in a hash, relative to the' \ ' position of the opening brace.', 'Indent the right brace the same as the left brace.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'special_inside_parentheses') end end it 'registers an offense for incorrectly indented }' do inspect_source(<<-RUBY.strip_indent) a << { } RUBY expect(cop.highlights).to eq(['}']) expect(cop.messages) .to eq(['Indent the right brace the same as the left brace.']) expect(cop.config_to_allow_offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/layout/indent_heredoc_spec.rb000066400000000000000000000211131322072016200242530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::IndentHeredoc, :config do subject(:cop) { described_class.new(config) } let(:allow_heredoc) { true } let(:other_cops) do { 'Metrics/LineLength' => { 'Max' => 5, 'AllowHeredoc' => allow_heredoc } } end shared_examples :offense do |name, code, correction = nil| it "registers an offense for #{name}" do inspect_source(code.strip_indent) expect(cop.offenses.size).to eq(1) end it "autocorrects for #{name}" do corrected = autocorrect_source_with_loop(code.strip_indent) expect(corrected).to eq(correction.strip_indent) end end shared_examples :accept do |name, code| it "accepts for #{name}" do inspect_source(code.strip_indent) expect(cop.offenses.empty?).to be(true) end end shared_examples :check_message do |name, message| it "displays a message with #{name}" do inspect_source(<<-RUBY.strip_indent) <<-RUBY2 foo RUBY2 RUBY expect(cop.messages).to eq(message) end end shared_examples :warning do |message| it 'warns' do correct = lambda do autocorrect_source(<<-RUBY.strip_indent) <<-RUBY2 foo RUBY2 RUBY end expect(&correct).to raise_error(RuboCop::Warning, message) end end shared_examples :all_heredoc_type do |quote| context "quoted by #{quote}" do let(:cop_config) do { 'EnforcedStyle' => :powerpack } end include_examples :offense, 'not indented', <<-RUBY, <<-CORRECTION <<#{quote}RUBY2#{quote} \#{foo} bar RUBY2 RUBY <<#{quote}RUBY2#{quote}.strip_indent \#{foo} bar RUBY2 CORRECTION include_examples :offense, 'minus level indented', <<-RUBY, <<-CORRECTION def foo <<#{quote}RUBY2#{quote} \#{foo} bar RUBY2 end RUBY def foo <<#{quote}RUBY2#{quote}.strip_indent \#{foo} bar RUBY2 end CORRECTION include_examples :offense, 'not indented, with `-`', <<-RUBY, <<-CORRECTION <<-#{quote}RUBY2#{quote} \#{foo} bar RUBY2 RUBY <<-#{quote}RUBY2#{quote}.strip_indent \#{foo} bar RUBY2 CORRECTION include_examples :offense, 'minus level indented, with `-`', <<-RUBY, <<-CORRECTION def foo <<-#{quote}RUBY2#{quote} \#{foo} bar RUBY2 end RUBY def foo <<-#{quote}RUBY2#{quote}.strip_indent \#{foo} bar RUBY2 end CORRECTION include_examples :accept, 'not indented but with whitespace, with `-`', <<-RUBY def foo <<-#{quote}RUBY2#{quote} something RUBY2 end RUBY include_examples :accept, 'indented, but with `-`', <<-RUBY def foo <<-#{quote}RUBY2#{quote} something RUBY2 end RUBY include_examples :accept, 'not indented but with whitespace', <<-RUBY def foo <<#{quote}RUBY2#{quote} something RUBY2 end RUBY include_examples :accept, 'indented, but without `~`', <<-RUBY def foo <<#{quote}RUBY2#{quote} something RUBY2 end RUBY include_examples :accept, 'an empty line', <<-RUBY <<-#{quote}RUBY2#{quote} RUBY2 RUBY context 'when Metrics/LineLength is configured' do let(:allow_heredoc) { false } include_examples :offense, 'short heredoc', <<-RUBY, <<-CORRECTION <<#{quote}RUBY2#{quote} 12 RUBY2 RUBY <<#{quote}RUBY2#{quote}.strip_indent 12 RUBY2 CORRECTION include_examples :accept, 'long heredoc', <<-RUBY <<#{quote}RUBY2#{quote} 12345678 RUBY2 RUBY end include_examples :check_message, 'suggestion powerpack', [ 'Use 2 spaces for indentation in a heredoc by using ' \ '`String#strip_indent`.' ] context 'EnforcedStyle is `auto_detection`' do let(:cop_config) do { 'EnforcedStyle' => :auto_detection } end message = 'Use 2 spaces for indentation in a heredoc by using ' \ "some library(e.g. ActiveSupport's `String#strip_heredoc`)." include_examples :check_message, 'some library', [message] warning = 'Auto-correction does not work for Layout/IndentHeredoc. ' \ 'Please configure EnforcedStyle.' include_examples :warning, warning context 'Ruby 2.3', :ruby23 do message = 'Use 2 spaces for indentation in a heredoc by using ' \ '`<<~` instead of `<<-`.' include_examples :check_message, 'squiggly heredoc', [message] include_examples :offense, 'not indented', <<-RUBY, <<-CORRECTION <<#{quote}RUBY2#{quote} \#{foo} bar RUBY2 RUBY <<~#{quote}RUBY2#{quote} \#{foo} bar RUBY2 CORRECTION end context 'Rails', :enabled_rails do message = 'Use 2 spaces for indentation in a heredoc by using ' \ '`String#strip_heredoc`.' include_examples :check_message, 'suggestion ActiveSupport', [message] include_examples :offense, 'not indented', <<-RUBY, <<-CORRECTION <<#{quote}RUBY2#{quote} \#{foo} bar RUBY2 RUBY <<#{quote}RUBY2#{quote}.strip_heredoc \#{foo} bar RUBY2 CORRECTION end end context 'EnforcedStyle is `squiggly`', :ruby23 do let(:cop_config) do { 'EnforcedStyle' => :squiggly } end include_examples :offense, 'not indented', <<-RUBY, <<-CORRECTION <<~#{quote}RUBY2#{quote} something RUBY2 RUBY <<~#{quote}RUBY2#{quote} something RUBY2 CORRECTION include_examples :offense, 'minus level indented', <<-RUBY, <<-CORRECTION def foo <<~#{quote}RUBY2#{quote} something RUBY2 end RUBY def foo <<~#{quote}RUBY2#{quote} something RUBY2 end CORRECTION include_examples :offense, 'too deep indented', <<-RUBY, <<-CORRECTION <<~#{quote}RUBY2#{quote} something RUBY2 RUBY <<~#{quote}RUBY2#{quote} something RUBY2 CORRECTION include_examples :offense, 'not indented, without `~`', <<-RUBY, <<-CORRECTION <<#{quote}RUBY2#{quote} foo RUBY2 RUBY <<~#{quote}RUBY2#{quote} foo RUBY2 CORRECTION include_examples :accept, 'indentaed, with `~`', <<-RUBY <<~#{quote}RUBY2#{quote} something RUBY2 RUBY include_examples :accept, 'include empty lines', <<-RUBY <<~#{quote}MSG#{quote} foo bar MSG RUBY it 'displays message to use `<<~` instead of `<<`' do inspect_source(<<-RUBY.strip_indent) < 'normal' } } context 'with if statement' do it 'registers an offense for bad indentation in an if body' do expect_offense(<<-RUBY.strip_indent) if cond func func ^^^^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in an else body' do expect_offense(<<-RUBY.strip_indent) if cond func1 else func2 func2 ^^^^^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in an elsif body' do expect_offense(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 b3 ^^ Inconsistent indentation detected. else c end RUBY end it 'autocorrects bad indentation' do corrected = autocorrect_source(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 b3 else c end RUBY expect(corrected).to eq <<-RUBY.strip_indent if a1 b1 elsif a2 b2 b3 else c end RUBY end it 'accepts a one line if statement' do expect_no_offenses('if cond then func1 else func2 end') end it 'accepts a correctly aligned if/elsif/else/end' do expect_no_offenses(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 else c end RUBY end it 'accepts if/elsif/else/end laid out as a table' do expect_no_offenses(<<-RUBY.strip_indent) if @io == $stdout then str << "$stdout" elsif @io == $stdin then str << "$stdin" elsif @io == $stderr then str << "$stderr" else str << @io.class.to_s end RUBY end it 'accepts if/then/else/end laid out as another table' do expect_no_offenses(<<-RUBY.strip_indent) if File.exist?('config.save') then ConfigTable.load else ConfigTable.new end RUBY end it 'accepts if/elsif/else/end with fullwidth characters' do expect_no_offenses(<<-RUBY.strip_indent) p 'Ruby', if a then b c end RUBY end it 'accepts an empty if' do expect_no_offenses(<<-RUBY.strip_indent) if a else end RUBY end it 'accepts an if in assignment with end aligned with variable' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 end @var = if a 0 end $var = if a 0 end var ||= if a 0 end var &&= if a 0 end var -= if a 0 end VAR = if a 0 end RUBY end it 'accepts an if/else in assignment with end aligned with variable' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else in assignment with end aligned with variable ' \ 'and chaining after the end' do inspect_source(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.join("") RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts an if/else in assignment with end aligned with variable ' \ 'and chaining with a block after the end' do inspect_source(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.tap {} RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts an if in assignment with end aligned with if' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 end RUBY end it 'accepts an if/else in assignment with end aligned with if' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else in assignment on next line with end aligned ' \ 'with if' do inspect_source(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts an if/else branches with rescue clauses' do # Because of how the rescue clauses come out of Parser, these are # special and need to be tested. expect_no_offenses(<<-RUBY.strip_indent) if a a rescue nil else a rescue nil end RUBY end end context 'with unless' do it 'registers an offense for bad indentation in an unless body' do expect_offense(<<-RUBY.strip_indent) unless cond func func ^^^^ Inconsistent indentation detected. end RUBY end it 'accepts an empty unless' do expect_no_offenses(<<-RUBY.strip_indent) unless a else end RUBY end end context 'with case' do it 'registers an offense for bad indentation in a case/when body' do expect_offense(<<-RUBY.strip_indent) case a when b c d ^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in a case/else body' do expect_offense(<<-RUBY.strip_indent) case a when b c when d e else f g ^ Inconsistent indentation detected. end RUBY end it 'accepts correctly indented case/when/else' do expect_no_offenses(<<-RUBY.strip_indent) case a when b c c when d else f end RUBY end it 'accepts case/when/else laid out as a table' do expect_no_offenses(<<-RUBY.strip_indent) case sexp.loc.keyword.source when 'if' then cond, body, _else = *sexp when 'unless' then cond, _else, body = *sexp else cond, body = *sexp end RUBY end it 'accepts case/when/else with then beginning a line' do expect_no_offenses(<<-RUBY.strip_indent) case sexp.loc.keyword.source when 'if' then cond, body, _else = *sexp end RUBY end it 'accepts indented when/else plus indented body' do # "Indent when as deep as case" is the job of another cop. expect_no_offenses(<<-RUBY.strip_indent) case code_type when 'ruby', 'sql', 'plain' code_type when 'erb' 'ruby; html-script: true' when "html" 'xml' else 'plain' end RUBY end end context 'with while/until' do it 'registers an offense for bad indentation in a while body' do expect_offense(<<-RUBY.strip_indent) while cond func func ^^^^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in begin/end/while' do expect_offense(<<-RUBY.strip_indent) something = begin func1 func2 ^^^^^ Inconsistent indentation detected. end while cond RUBY end it 'registers an offense for bad indentation in an until body' do expect_offense(<<-RUBY.strip_indent) until cond func func ^^^^ Inconsistent indentation detected. end RUBY end it 'accepts an empty while' do expect_no_offenses(<<-RUBY.strip_indent) while a end RUBY end end context 'with for' do it 'registers an offense for bad indentation in a for body' do expect_offense(<<-RUBY.strip_indent) for var in 1..10 func func ^^^^ Inconsistent indentation detected. end RUBY end it 'accepts an empty for' do expect_no_offenses(<<-RUBY.strip_indent) for var in 1..10 end RUBY end end context 'with def/defs' do it 'registers an offense for bad indentation in a def body' do expect_offense(<<-RUBY.strip_indent) def test func1 func2 ^^^^^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in a defs body' do expect_offense(<<-RUBY.strip_indent) def self.test func func ^^^^ Inconsistent indentation detected. end RUBY end it 'accepts an empty def body' do expect_no_offenses(<<-RUBY.strip_indent) def test end RUBY end it 'accepts an empty defs body' do expect_no_offenses(<<-RUBY.strip_indent) def self.test end RUBY end end context 'with class' do context 'with rails style configured' do let(:cop_config) { { 'EnforcedStyle' => 'rails' } } it 'accepts different indentation in different visibility sections' do expect_no_offenses(<<-RUBY.strip_indent) class Cat def meow puts('Meow!') end protected def can_we_be_friends?(another_cat) # some logic end def related_to?(another_cat) # some logic end private # Here we go back an indentation level again. This is a # violation of the Rails style, but it's not for this # cop to report. Layout/IndentationWidth will handle it. def meow_at_3am? rand < 0.8 end # As long as the indentation of this method is # consistent with that of the last one, we're fine. def meow_at_4am? rand < 0.8 end end RUBY end end context 'with normal style configured' do it 'registers an offense for bad indentation in a class body' do expect_offense(<<-RUBY.strip_indent) class Test def func1 end def func2 ^^^^^^^^^ Inconsistent indentation detected. end end RUBY end it 'accepts an empty class body' do expect_no_offenses(<<-RUBY.strip_indent) class Test end RUBY end it 'accepts indented public, protected, and private' do expect_no_offenses(<<-RUBY.strip_indent) class Test public def e end protected def f end private def g end end RUBY end it 'registers an offense for bad indentation in def but not for ' \ 'outdented public, protected, and private' do inspect_source(<<-RUBY.strip_indent) class Test public def e end protected def f end private def g end end RUBY expect(cop.messages).to eq(['Inconsistent indentation detected.']) expect(cop.highlights).to eq(["def g\n end"]) end end end context 'with module' do it 'registers an offense for bad indentation in a module body' do expect_offense(<<-RUBY.strip_indent) module Test def func1 end def func2 ^^^^^^^^^ Inconsistent indentation detected. end end RUBY end it 'accepts an empty module body' do expect_no_offenses(<<-RUBY.strip_indent) module Test end RUBY end end context 'with block' do it 'registers an offense for bad indentation in a do/end body' do expect_offense(<<-RUBY.strip_indent) a = func do b c ^ Inconsistent indentation detected. end RUBY end it 'registers an offense for bad indentation in a {} body' do expect_offense(<<-RUBY.strip_indent) func { b c ^ Inconsistent indentation detected. } RUBY end it 'accepts a correctly indented block body' do expect_no_offenses(<<-RUBY.strip_indent) a = func do b c end RUBY end it 'accepts an empty block body' do expect_no_offenses(<<-RUBY.strip_indent) a = func do end RUBY end it 'does not auto-correct an offense within another offense' do corrected = autocorrect_source(<<-RUBY.strip_indent) require 'spec_helper' describe ArticlesController do render_views describe "GET \'index\'" do it "returns success" do end describe "admin user" do before(:each) do end end end end RUBY expect(cop.offenses.map(&:line)).to eq [4, 7] # Two offenses are found. # The offense on line 4 is corrected, affecting lines 4 to 11. expect(corrected).to eq <<-RUBY.strip_indent require 'spec_helper' describe ArticlesController do render_views describe \"GET 'index'\" do it "returns success" do end describe "admin user" do before(:each) do end end end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/indentation_width_spec.rb000066400000000000000000000775211322072016200250320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::IndentationWidth do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => cop_config, 'Layout/IndentationConsistency' => consistency_config, 'Lint/EndAlignment' => end_alignment_config, 'Lint/DefEndAlignment' => def_end_alignment_config) end let(:consistency_config) { { 'EnforcedStyle' => 'normal' } } let(:end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'variable' } end let(:def_end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'start_of_line' } end context 'with Width set to 4' do let(:cop_config) { { 'Width' => 4 } } context 'for a file with byte order mark' do let(:bom) { "\xef\xbb\xbf" } it 'accepts correctly indented method definition' do expect_no_offenses(<<-RUBY.strip_indent) #{bom}class Test def method end end RUBY end end context 'with ignored patterns set' do let(:cop_config) do { 'Width' => 4, 'IgnoredPatterns' => ['^\s*module', '^\s*(els)?if.*[A-Z][a-z]+'] } end it 'accepts unindented lines for those keywords' do expect_no_offenses(<<-RUBY.strip_indent) module Foo class Test if blah if blah == Apple puts "sweet" elsif blah == Lemon puts "sour" elsif blah == popcorn puts "salty" end end end end RUBY end end context 'with if statement' do it 'registers an offense for bad indentation of an if body' do expect_offense(<<-RUBY.strip_indent) if cond func ^ Use 4 (not 1) spaces for indentation. end RUBY end end describe '#autocorrect' do it 'corrects bad indentation' do corrected = autocorrect_source(<<-RUBY.strip_indent) if a1 b1 b1 elsif a2 b2 else c end RUBY # The second `b1` will be corrected by IndentationConsistency. expect(corrected).to eq <<-RUBY.strip_indent if a1 b1 b1 elsif a2 b2 else c end RUBY end end end context 'with Width set to 2' do let(:cop_config) { { 'Width' => 2 } } context 'with if statement' do it 'registers an offense for bad indentation of an if body' do expect_offense(<<-RUBY.strip_indent) if cond func ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of an else body' do expect_offense(<<-RUBY.strip_indent) if cond func1 else func2 ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of an elsif body' do expect_offense(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 ^ Use 2 (not 1) spaces for indentation. else c end RUBY end it 'registers offense for bad indentation of ternary inside else' do expect_offense(<<-RUBY.strip_indent) if a b else x ? y : z ^^^^^ Use 2 (not 5) spaces for indentation. end RUBY end it 'registers offense for bad indentation of modifier if in else' do expect_offense(<<-RUBY.strip_indent) if a b else x if y ^^^ Use 2 (not 3) spaces for indentation. end RUBY end it 'accepts indentation after if on new line after assignment' do expect_no_offenses(<<-RUBY.strip_indent) Rails.application.config.ideal_postcodes_key = if Rails.env.production? || Rails.env.staging? "AAAA-AAAA-AAAA-AAAA" end RUBY end it 'accepts `rescue` after an empty body' do expect_no_offenses(<<-RUBY.strip_indent) begin rescue handle_error end RUBY end it 'accepts `ensure` after an empty body' do expect_no_offenses(<<-RUBY.strip_indent) begin ensure something end RUBY end describe '#autocorrect' do it 'corrects bad indentation' do corrected = autocorrect_source(<<-RUBY.strip_indent) if a1 b1 b1 elsif a2 b2 else c end RUBY # The second `b1` will be corrected by IndentationConsistency. expect(corrected).to eq <<-RUBY.strip_indent if a1 b1 b1 elsif a2 b2 else c end RUBY end it 'does not correct in scopes that contain block comments' do source = <<-RUBY.strip_indent module Foo # The class has a block comment within, so it's not corrected. class Bar =begin This is a nice long comment which spans a few lines =end # The method has no block comment inside, # but it's within a class that has a block # comment, so it's not corrected either. def baz do_something end end end RUBY expect(autocorrect_source(source)).to eq source end it 'does not indent heredoc strings' do corrected = autocorrect_source(<<-'RUBY'.strip_indent) module Foo module Bar SOMETHING = < attr, :attr2 => Other.get_value(), :attr3 => Another.get_value()) } RUBY corrected = autocorrect_source(src) expect(corrected).to eq src end it 'handles lines with only whitespace' do corrected = autocorrect_source(['def x', ' y', ' ', 'rescue', 'end']) expect(corrected).to eq ['def x', ' y', ' ', 'rescue', 'end'].join("\n") end end it 'accepts a one line if statement' do expect_no_offenses('if cond then func1 else func2 end') end it 'accepts a correctly aligned if/elsif/else/end' do expect_no_offenses(<<-RUBY.strip_indent) if a1 b1 elsif a2 b2 else c end RUBY end it 'accepts a correctly aligned if/elsif/else/end as a method argument' do expect_no_offenses(<<-RUBY.strip_indent) foo( if a1 b1 elsif a2 b2 else c end ) RUBY end it 'accepts if/elsif/else/end laid out as a table' do expect_no_offenses(<<-RUBY.strip_indent) if @io == $stdout then str << "$stdout" elsif @io == $stdin then str << "$stdin" elsif @io == $stderr then str << "$stderr" else str << @io.class.to_s end RUBY end it 'accepts if/then/else/end laid out as another table' do expect_no_offenses(<<-RUBY.strip_indent) if File.exist?('config.save') then ConfigTable.load else ConfigTable.new end RUBY end it 'accepts an empty if' do expect_no_offenses(<<-RUBY.strip_indent) if a else end RUBY end context 'with assignment' do context 'when alignment style is variable' do context 'and end is aligned with variable' do it 'accepts an if with end aligned with setter' do expect_no_offenses(<<-RUBY.strip_indent) foo.bar = if baz derp end RUBY end it 'accepts an if with end aligned with element assignment' do expect_no_offenses(<<-RUBY.strip_indent) foo[bar] = if baz derp end RUBY end it 'accepts an if with end aligned with variable' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 end @var = if a 0 end $var = if a 0 end var ||= if a 0 end var &&= if a 0 end var -= if a 0 end VAR = if a 0 end RUBY end it 'accepts an if/else' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else with chaining after the end' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.join("") RUBY end it 'accepts an if/else with chaining with a block after the end' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end.abc.tap {} RUBY end end context 'and end is aligned with keyword' do it 'registers an offense for an if with setter' do expect_offense(<<-RUBY.strip_indent) foo.bar = if baz derp ^^^^^^^^^^^^ Use 2 (not 12) spaces for indentation. end RUBY end it 'registers an offense for an if with element assignment' do expect_offense(<<-RUBY.strip_indent) foo[bar] = if baz derp ^^^^^^^^^^^^^ Use 2 (not 13) spaces for indentation. end RUBY end it 'registers an offense for an if' do expect_offense(<<-RUBY.strip_indent) var = if a 0 ^^^^^^^^ Use 2 (not 8) spaces for indentation. end RUBY end it 'registers an offense for a while' do expect_offense(<<-RUBY.strip_indent) var = while a b ^^^^^^^^ Use 2 (not 8) spaces for indentation. end RUBY end it 'registers an offense for an until' do expect_offense(<<-RUBY.strip_indent) var = until a b ^^^^^^^^ Use 2 (not 8) spaces for indentation. end RUBY end end context 'and end is aligned randomly' do it 'registers an offense for an if' do expect_offense(<<-RUBY.strip_indent) var = if a 0 ^^^^^^^^^^ Use 2 (not 10) spaces for indentation. end RUBY end it 'registers an offense for a while' do expect_offense(<<-RUBY.strip_indent) var = while a b ^^^^^^^^^^ Use 2 (not 10) spaces for indentation. end RUBY end it 'registers an offense for an until' do expect_offense(<<-RUBY.strip_indent) var = until a b ^^^^^^^^^^ Use 2 (not 10) spaces for indentation. end RUBY end end end shared_examples 'assignment and if with keyword alignment' do context 'and end is aligned with variable' do it 'registers an offense for an if' do inspect_source(<<-RUBY.strip_indent) var = if a 0 end RUBY expect(cop.messages) .to eq(['Use 2 (not -4) spaces for indentation.']) end it 'registers an offense for a while' do inspect_source(<<-RUBY.strip_indent) var = while a b end RUBY expect(cop.messages) .to eq(['Use 2 (not -4) spaces for indentation.']) end it 'autocorrects bad indentation' do corrected = autocorrect_source(<<-RUBY.strip_indent) var = if a b end var = while a b end RUBY # Not this cop's job to fix the `end`. expect(corrected).to eq <<-RUBY.strip_indent var = if a b end var = while a b end RUBY end end context 'and end is aligned with keyword' do it 'accepts an if in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 end RUBY end it 'accepts an if/else in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts an if/else in assignment on next line' do expect_no_offenses(<<-RUBY.strip_indent) var = if a 0 else 1 end RUBY end it 'accepts a while in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = while a b end RUBY end it 'accepts an until in assignment' do expect_no_offenses(<<-RUBY.strip_indent) var = until a b end RUBY end end end context 'when alignment style is keyword by choice' do let(:end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'keyword' } end include_examples 'assignment and if with keyword alignment' end end it 'accepts an if/else branches with rescue clauses' do # Because of how the rescue clauses come out of Parser, these are # special and need to be tested. expect_no_offenses(<<-RUBY.strip_indent) if a a rescue nil else a rescue nil end RUBY end end context 'with unless' do it 'registers an offense for bad indentation of an unless body' do expect_offense(<<-RUBY.strip_indent) unless cond func ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'accepts an empty unless' do expect_no_offenses(<<-RUBY.strip_indent) unless a else end RUBY end end context 'with case' do it 'registers an offense for bad indentation in a case/when body' do expect_offense(<<-RUBY.strip_indent) case a when b c ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indentation in a case/else body' do expect_offense(<<-RUBY.strip_indent) case a when b c when d e else f ^^^ Use 2 (not 3) spaces for indentation. end RUBY end it 'accepts correctly indented case/when/else' do expect_no_offenses(<<-RUBY.strip_indent) case a when b c c when d else f end RUBY end it 'accepts aligned values in when clause' do expect_no_offenses(<<-'RUBY'.strip_indent) case superclass when /\A(#{NAMESPACEMATCH})(?:\s|\Z)/, /\A(Struct|OStruct)\.new/, /\ADelegateClass\((.+?)\)\s*\Z/, /\A(#{NAMESPACEMATCH})\(/ $1 when "self" namespace.path end RUBY end it 'accepts case/when/else laid out as a table' do expect_no_offenses(<<-RUBY.strip_indent) case sexp.loc.keyword.source when 'if' then cond, body, _else = *sexp when 'unless' then cond, _else, body = *sexp else cond, body = *sexp end RUBY end it 'accepts case/when/else with then beginning a line' do expect_no_offenses(<<-RUBY.strip_indent) case sexp.loc.keyword.source when 'if' then cond, body, _else = *sexp end RUBY end it 'accepts indented when/else plus indented body' do # "Indent when as deep as case" is the job of another cop. expect_no_offenses(<<-RUBY.strip_indent) case code_type when 'ruby', 'sql', 'plain' code_type when 'erb' 'ruby; html-script: true' when "html" 'xml' else 'plain' end RUBY end end context 'with while/until' do it 'registers an offense for bad indentation of a while body' do expect_offense(<<-RUBY.strip_indent) while cond func ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of begin/end/while' do expect_offense(<<-RUBY.strip_indent) something = begin func1 ^ Use 2 (not 1) spaces for indentation. func2 end while cond RUBY end it 'registers an offense for bad indentation of an until body' do expect_offense(<<-RUBY.strip_indent) until cond func ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'accepts an empty while' do expect_no_offenses(<<-RUBY.strip_indent) while a end RUBY end end context 'with for' do it 'registers an offense for bad indentation of a for body' do expect_offense(<<-RUBY.strip_indent) for var in 1..10 func ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'accepts an empty for' do expect_no_offenses(<<-RUBY.strip_indent) for var in 1..10 end RUBY end end context 'with def/defs' do shared_examples 'without modifier on the same line' do it 'registers an offense for bad indentation of a def body' do inspect_source(<<-RUBY.strip_indent) def test func1 func2 # No offense registered for this. end RUBY expect(cop.messages).to eq(['Use 2 (not 4) spaces for indentation.']) end it 'registers an offense for bad indentation of a defs body' do inspect_source(<<-RUBY.strip_indent) def self.test func end RUBY expect(cop.messages).to eq(['Use 2 (not 3) spaces for indentation.']) end it 'accepts an empty def body' do expect_no_offenses(<<-RUBY.strip_indent) def test end RUBY end it 'accepts an empty defs body' do expect_no_offenses(<<-RUBY.strip_indent) def self.test end RUBY end it 'with an assignment' do expect_no_offenses(<<-RUBY.strip_indent) something = def self.foo end RUBY end end context 'when end is aligned with start of line' do let(:def_end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'start_of_line' } end include_examples 'without modifier on the same line' context 'when modifier and def are on the same line' do it 'accepts a correctly aligned body' do expect_no_offenses(<<-RUBY.strip_indent) foo def test something end RUBY end it 'registers an offense for bad indentation of a def body' do expect_offense(<<-RUBY.strip_indent) foo def test something ^^^^^^ Use 2 (not 6) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of a defs body' do expect_offense(<<-RUBY.strip_indent) foo def self.test something ^^^^^^ Use 2 (not 6) spaces for indentation. end RUBY end end end context 'when end is aligned with def' do let(:def_end_alignment_config) do { 'Enabled' => true, 'EnforcedStyleAlignWith' => 'def' } end include_examples 'without modifier on the same line' context 'when modifier and def are on the same line' do it 'accepts a correctly aligned body' do expect_no_offenses(<<-RUBY.strip_indent) foo def test something end RUBY end it 'registers an offense for bad indentation of a def body' do expect_offense(<<-RUBY.strip_indent) foo def test something ^^ Use 2 (not -2) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of a defs body' do expect_offense(<<-RUBY.strip_indent) foo def self.test something ^^ Use 2 (not -2) spaces for indentation. end RUBY end end end end context 'with class' do it 'registers an offense for bad indentation of a class body' do expect_offense(<<-RUBY.strip_indent) class Test def func ^^^^ Use 2 (not 4) spaces for indentation. end end RUBY end it 'accepts an empty class body' do expect_no_offenses(<<-RUBY.strip_indent) class Test end RUBY end context 'when consistency style is normal' do it 'accepts indented public, protected, and private' do expect_no_offenses(<<-RUBY.strip_indent) class Test public def e end protected def f end private def g end end RUBY end end context 'when consistency style is rails' do let(:consistency_config) { { 'EnforcedStyle' => 'rails' } } it 'registers an offense for normal non-rails indentation' do inspect_source(<<-RUBY.strip_indent) class Test public def e end protected def f end private def g end end RUBY expect(cop.messages) .to eq(['Use 2 (not 0) spaces for rails indentation.'] * 2) expect(cop.offenses.map(&:line)).to eq([9, 14]) end end end context 'with module' do context 'when consistency style is normal' do it 'registers an offense for bad indentation of a module body' do expect_offense(<<-RUBY.strip_indent) module Test def func ^^^^ Use 2 (not 4) spaces for indentation. end end RUBY end it 'accepts an empty module body' do expect_no_offenses(<<-RUBY.strip_indent) module Test end RUBY end end context 'when consistency style is rails' do let(:consistency_config) { { 'EnforcedStyle' => 'rails' } } it 'registers an offense for bad indentation of a module body' do expect_offense(<<-RUBY.strip_indent) module Test def func1 ^^^ Use 2 (not 3) spaces for indentation. end private def func2 ^ Use 2 (not -1) spaces for rails indentation. end end RUBY end it 'accepts normal non-rails indentation of module functions' do expect_no_offenses(<<-RUBY.strip_indent) module Test module_function def func end end RUBY end end end context 'with begin/rescue/else/ensure/end' do it 'registers an offense for bad indentation of bodies' do inspect_source(<<-RUBY.strip_indent) def my_func puts 'do something outside block' begin puts 'do something error prone' rescue SomeException, SomeOther => e puts 'wrongly intended error handling' rescue puts 'wrongly intended error handling' else puts 'wrongly intended normal case handling' ensure puts 'wrongly intended common handling' end end RUBY expect(cop.messages).to eq(['Use 2 (not 0) spaces for indentation.', 'Use 2 (not 1) spaces for indentation.', 'Use 2 (not 1) spaces for indentation.', 'Use 2 (not 3) spaces for indentation.', 'Use 2 (not 4) spaces for indentation.']) end end context 'with def/rescue/end' do it 'registers an offense for bad indentation of bodies' do expect_offense(<<-RUBY.strip_indent) def my_func puts 'do something error prone' rescue SomeException puts 'wrongly intended error handling' ^ Use 2 (not 1) spaces for indentation. rescue puts 'wrongly intended error handling' ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indent of defs bodies with a modifier' do expect_offense(<<-RUBY.strip_indent) foo def self.my_func puts 'do something error prone' rescue SomeException puts 'wrongly intended error handling' ^ Use 2 (not 1) spaces for indentation. rescue puts 'wrongly intended error handling' ^ Use 2 (not 1) spaces for indentation. end RUBY end end context 'with block' do context 'when consistency style is rails' do let(:consistency_config) { { 'EnforcedStyle' => 'rails' } } it 'registers an offense for bad indentation in a do/end body' do inspect_source(<<-RUBY.strip_indent) concern :Authenticatable do def foo puts "foo" end private def bar puts "bar" end end RUBY expect(cop.messages) .to eq(['Use 2 (not 0) spaces for rails indentation.']) end end it 'registers an offense for bad indentation of a do/end body' do expect_offense(<<-RUBY.strip_indent) a = func do b ^ Use 2 (not 1) spaces for indentation. end RUBY end it 'registers an offense for bad indentation of a {} body' do expect_offense(<<-RUBY.strip_indent) func { b ^^^ Use 2 (not 3) spaces for indentation. } RUBY end it 'accepts a correctly indented block body' do expect_no_offenses(<<-RUBY.strip_indent) a = func do b end RUBY end it 'accepts an empty block body' do expect_no_offenses(<<-RUBY.strip_indent) a = func do end RUBY end # The cop uses the block end/} as the base for indentation, so if it's not # on its own line, all bets are off. it 'accepts badly indented code if block end is not on separate line' do expect_no_offenses(<<-RUBY.strip_indent) foo { def baz end } RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/initial_indentation_spec.rb000066400000000000000000000036751322072016200253430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::InitialIndentation do subject(:cop) { described_class.new } it 'registers an offense for indented method definition ' do expect_offense(<<-RUBY.strip_margin('|')) | def f | ^^^ Indentation of first line in file detected. | end RUBY end it 'accepts unindented method definition' do expect_no_offenses(<<-RUBY.strip_indent) def f end RUBY end context 'for a file with byte order mark' do it 'accepts unindented method call' do expect_no_offenses('puts 1') end it 'registers an offense for indented method call' do expect_offense(<<-RUBY.strip_indent)  puts 1 ^^^^ Indentation of first line in file detected. RUBY end it 'registers an offense for indented method call after comment' do expect_offense(<<-RUBY.strip_indent) # comment puts 1 ^^^^ Indentation of first line in file detected. RUBY end end it 'accepts empty file' do expect_no_offenses('') end it 'registers an offense for indented assignment disregarding comment' do expect_offense(<<-RUBY.strip_margin('|')) | # comment | x = 1 | ^ Indentation of first line in file detected. RUBY end it 'accepts unindented comment + assignment' do expect_no_offenses(<<-RUBY.strip_indent) # comment x = 1 RUBY end it 'auto-corrects indented method definition' do corrected = autocorrect_source(<<-RUBY.strip_margin('|')) | def f | end RUBY expect(corrected).to eq <<-RUBY.strip_indent def f end RUBY end it 'auto-corrects indented assignment but not comment' do corrected = autocorrect_source(<<-RUBY.strip_margin('|')) | # comment | x = 1 RUBY expect(corrected).to eq <<-RUBY.strip_indent # comment x = 1 RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/leading_comment_space_spec.rb000066400000000000000000000047411322072016200256110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::LeadingCommentSpace do subject(:cop) { described_class.new } it 'registers an offense for comment without leading space' do expect_offense(<<-RUBY.strip_indent) #missing space ^^^^^^^^^^^^^^ Missing space after `#`. RUBY end it 'does not register an offense for # followed by no text' do expect_no_offenses('#') end it 'does not register an offense for more than one space' do expect_no_offenses('# heavily indented') end it 'does not register an offense for more than one #' do expect_no_offenses('###### heavily indented') end it 'does not register an offense for only #s' do expect_no_offenses('######') end it 'does not register an offense for #! on first line' do expect_no_offenses(<<-RUBY.strip_indent) #!/usr/bin/ruby test RUBY end it 'registers an offense for #! after the first line' do expect_offense(<<-RUBY.strip_indent) test #!/usr/bin/ruby ^^^^^^^^^^^^^^^ Missing space after `#`. RUBY end context 'file named config.ru' do it 'does not register an offense for #\ on first line' do expect_no_offenses(<<-'RUBY'.strip_indent, 'config.ru') #\ -w -p 8765 test RUBY end it 'registers an offense for #\ after the first line' do expect_offense(<<-'RUBY'.strip_indent, 'config.ru') test #\ -w -p 8765 ^^^^^^^^^^^^^ Missing space after `#`. RUBY end end context 'file not named config.ru' do it 'registers an offense for #\ on first line' do expect_offense(<<-'RUBY'.strip_indent, 'test/test_case.rb') #\ -w -p 8765 ^^^^^^^^^^^^^ Missing space after `#`. test RUBY end it 'registers an offense for #\ after the first line' do expect_offense(<<-'RUBY'.strip_indent, 'test/test_case.rb') test #\ -w -p 8765 ^^^^^^^^^^^^^ Missing space after `#`. RUBY end end it 'accepts rdoc syntax' do expect_no_offenses(<<-RUBY.strip_indent) #++ #-- #:nodoc: RUBY end it 'accepts sprockets directives' do expect_no_offenses('#= require_tree .') end it 'auto-corrects missing space' do new_source = autocorrect_source('#comment') expect(new_source).to eq('# comment') end it 'accepts =begin/=end comments' do expect_no_offenses(<<-RUBY.strip_indent) =begin #blahblah =end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_array_brace_layout_spec.rb000066400000000000000000000013151322072016200272340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineArrayBraceLayout, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } it 'ignores implicit arrays' do expect_no_offenses(<<-RUBY.strip_indent) foo = a, b RUBY end it 'ignores single-line arrays' do expect_no_offenses('[a, b, c]') end it 'ignores empty arrays' do expect_no_offenses('[]') end include_examples 'multiline literal brace layout' do let(:open) { '[' } let(:close) { ']' } end include_examples 'multiline literal brace layout trailing comma' do let(:open) { '[' } let(:close) { ']' } end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_assignment_layout_spec.rb000066400000000000000000000077761322072016200271530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineAssignmentLayout, :config do subject(:cop) { described_class.new(config) } let(:supported_types) { %w[if] } let(:cop_config) do { 'EnforcedStyle' => enforced_style, 'SupportedTypes' => supported_types } end context 'new_line style' do let(:enforced_style) { 'new_line' } it 'registers an offense when the rhs is on the same line' do inspect_source(<<-RUBY.strip_indent) blarg = if true end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["blarg = if true\nend"]) expect(cop.messages).to eq([described_class::NEW_LINE_OFFENSE]) end it 'auto-corrects offenses' do new_source = autocorrect_source(<<-RUBY.strip_indent) blarg = if true end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) blarg = if true end RUBY end it 'ignores arrays' do expect_no_offenses(<<-RUBY.strip_indent) a, b = 4, 5 RUBY end context 'configured supported types' do let(:supported_types) { %w[array] } it 'allows supported types to be configured' do inspect_source(<<-RUBY.strip_indent) a, b = 4, 5 RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["a, b = 4,\n5"]) expect(cop.messages).to eq([described_class::NEW_LINE_OFFENSE]) end end it 'allows multi-line assignments on separate lines' do expect_no_offenses(<<-RUBY.strip_indent) blarg= if true end RUBY end it 'registers an offense for masgn with multi-line lhs' do inspect_source(<<-RUBY.strip_indent) a, b = if foo end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["a,\nb = if foo\nend"]) expect(cop.messages).to eq([described_class::NEW_LINE_OFFENSE]) end end context 'same_line style' do let(:enforced_style) { 'same_line' } it 'registers an offense when the rhs is a different line' do inspect_source(<<-RUBY.strip_indent) blarg = if true end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["blarg =\nif true\nend"]) expect(cop.messages).to eq([described_class::SAME_LINE_OFFENSE]) end it 'auto-corrects offenses' do new_source = autocorrect_source(<<-RUBY.strip_indent) blarg = if true end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) blarg = if true end RUBY end it 'ignores arrays' do expect_no_offenses(<<-RUBY.strip_indent) a, b = 4, 5 RUBY end context 'configured supported types' do let(:supported_types) { %w[array] } it 'allows supported types to be configured' do inspect_source(<<-RUBY.strip_indent) a, b = 4, 5 RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["a, b =\n4,\n5"]) expect(cop.messages).to eq([described_class::SAME_LINE_OFFENSE]) end end it 'allows multi-line assignments on the same line' do expect_no_offenses(<<-RUBY.strip_indent) blarg= if true end RUBY end it 'registers an offense for masgn with multi-line lhs' do inspect_source(<<-RUBY.strip_indent) a, b = if foo end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(["a,\nb =\nif foo\nend"]) expect(cop.messages).to eq([described_class::SAME_LINE_OFFENSE]) end end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_block_layout_spec.rb000066400000000000000000000141361322072016200260610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineBlockLayout do subject(:cop) { described_class.new } it 'registers an offense for missing newline in do/end block w/o params' do expect_offense(<<-RUBY.strip_indent) test do foo ^^^ Block body expression is on the same line as the block start. end RUBY end it 'registers an offense for missing newline in {} block w/o params' do expect_offense(<<-RUBY.strip_indent) test { foo ^^^ Block body expression is on the same line as the block start. } RUBY end it 'registers an offense for missing newline in do/end block with params' do expect_offense(<<-RUBY.strip_indent) test do |x| foo ^^^ Block body expression is on the same line as the block start. end RUBY end it 'registers an offense for missing newline in {} block with params' do expect_offense(<<-RUBY.strip_indent) test { |x| foo ^^^ Block body expression is on the same line as the block start. } RUBY end it 'does not register an offense for one-line do/end blocks' do expect_no_offenses('test do foo end') end it 'does not register an offense for one-line {} blocks' do expect_no_offenses('test { foo }') end it 'does not register offenses when there is a newline for do/end block' do expect_no_offenses(<<-RUBY.strip_indent) test do foo end RUBY end it 'does not error out when the block is empty' do expect_no_offenses(<<-RUBY.strip_indent) test do |x| end RUBY end it 'does not register offenses when there is a newline for {} block' do expect_no_offenses(<<-RUBY.strip_indent) test { foo } RUBY end it 'registers offenses for lambdas as expected' do expect_offense(<<-RUBY.strip_indent) -> (x) do foo ^^^ Block body expression is on the same line as the block start. bar end RUBY end it 'registers offenses for new lambda literal syntax as expected' do expect_offense(<<-RUBY.strip_indent) -> x do foo ^^^ Block body expression is on the same line as the block start. bar end RUBY end it 'registers an offense for line-break before arguments' do expect_offense(<<-RUBY.strip_indent) test do |x| play_with(x) ^^^ Block argument expression is not on the same line as the block start. end RUBY end it 'registers an offense for line-break before arguments with empty block' do expect_offense(<<-RUBY.strip_indent) test do |x| ^^^ Block argument expression is not on the same line as the block start. end RUBY end it 'registers an offense for line-break within arguments' do expect_offense(<<-RUBY.strip_indent) test do |x, ^^^ Block argument expression is not on the same line as the block start. y| end RUBY end it 'auto-corrects a do/end block with params that is missing newlines' do src = <<-RUBY.strip_indent test do |foo| bar end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['test do |foo| ', ' bar', 'end', ''].join("\n")) end it 'auto-corrects a do/end block with a mult-line body' do src = <<-RUBY.strip_indent test do |foo| bar test end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['test do |foo| ', ' bar', ' test', 'end', ''].join("\n")) end it 'auto-corrects a {} block with params that is missing newlines' do src = <<-RUBY.strip_indent test { |foo| bar } RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['test { |foo| ', ' bar', '}', ''].join("\n")) end it 'autocorrects in more complex case with lambda and assignment, and '\ 'aligns the next line two spaces out from the start of the block' do src = <<-RUBY.strip_indent x = -> (y) { foo bar } RUBY new_source = autocorrect_source(src) expect(new_source).to eq(['x = -> (y) { ', ' foo', ' bar', '}', ''].join("\n")) end it 'auto-corrects a line-break before arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do |x| play_with(x) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do |x| play_with(x) end RUBY end it 'auto-corrects a line-break before arguments with empty block' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do |x| end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do |x| end RUBY end it 'auto-corrects a line-break within arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do |x, y| play_with(x, y) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do |x, y| play_with(x, y) end RUBY end it 'auto-corrects a line break within destructured arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do |(x, y)| play_with(x, y) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do |(x, y)| play_with(x, y) end RUBY end it "doesn't move end keyword in a way which causes infinite loop " \ 'in combination with Style/BlockEndNewLine' do new_source = autocorrect_source(<<-RUBY.strip_indent) def f X.map do |(a, b)| end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def f X.map do |(a, b)| end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_hash_brace_layout_spec.rb000066400000000000000000000015651322072016200270500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineHashBraceLayout, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } it 'ignores implicit hashes' do expect_no_offenses(<<-RUBY.strip_indent) foo(a: 1, b: 2) RUBY end it 'ignores single-line hashes' do expect_no_offenses('{a: 1, b: 2}') end it 'ignores empty hashes' do expect_no_offenses('{}') end include_examples 'multiline literal brace layout' do let(:open) { '{' } let(:close) { '}' } let(:a) { 'a: 1' } let(:b) { 'b: 2' } let(:multi_prefix) { 'b: ' } let(:multi) { ['[', '1', ']'] } end include_examples 'multiline literal brace layout trailing comma' do let(:open) { '{' } let(:close) { '}' } let(:a) { 'a: 1' } let(:b) { 'b: 2' } end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_method_call_brace_layout_spec.rb000066400000000000000000000027531322072016200304000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineMethodCallBraceLayout, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } it 'ignores implicit calls' do expect_no_offenses(<<-RUBY.strip_indent) foo 1, 2 RUBY end it 'ignores single-line calls' do expect_no_offenses('foo(1,2)') end it 'ignores calls without arguments' do expect_no_offenses('puts') end it 'ignores calls with an empty brace' do expect_no_offenses('puts()') end it 'ignores calls with a multiline empty brace ' do expect_no_offenses(<<-RUBY.strip_indent) puts( ) RUBY end include_examples 'multiline literal brace layout' do let(:open) { 'foo(' } let(:close) { ')' } end include_examples 'multiline literal brace layout trailing comma' do let(:open) { 'foo(' } let(:close) { ')' } end context 'when EnforcedStyle is new_line' do let(:cop_config) { { 'EnforcedStyle' => 'new_line' } } it 'still ignores single-line calls' do expect_no_offenses('puts("Hello world!")') end it 'ignores single-line calls with multi-line receiver' do expect_no_offenses(<<-RUBY.strip_indent) [ ].join(" ") RUBY end it 'ignores single-line calls with multi-line receiver with leading dot' do expect_no_offenses(<<-RUBY.strip_indent) [ ] .join(" ") RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_method_call_indentation_spec.rb000066400000000000000000000651411322072016200302430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineMethodCallIndentation do subject(:cop) { described_class.new(config) } let(:config) do merged = RuboCop::ConfigLoader .default_configuration['Layout/MultilineMethodCallIndentation'] .merge(cop_config) .merge('IndentationWidth' => cop_indent) RuboCop::Config .new('Layout/MultilineMethodCallIndentation' => merged, 'Layout/IndentationWidth' => { 'Width' => indentation_width }) end let(:indentation_width) { 2 } let(:cop_indent) { nil } # use indentation width from Layout/IndentationWidth shared_examples 'common' do it 'accepts indented methods in LHS of []= assignment' do expect_no_offenses(<<-RUBY.strip_indent) a .b[c] = 0 RUBY end it 'accepts indented methods inside and outside a block' do inspect_source(<<-RUBY.strip_indent) a = b.map do |c| c .b .d do x .y end end RUBY expect(cop.messages.empty?).to be(true) end it 'accepts indentation relative to first receiver' do expect_no_offenses(<<-RUBY.strip_indent) node .children.map { |n| string_source(n) }.compact .any? { |s| preferred.any? { |d| s.include?(d) } } RUBY end it 'accepts indented methods in ordinary statement' do inspect_source(<<-RUBY.strip_indent) a. b RUBY expect(cop.messages.empty?).to be(true) end it 'accepts no extra indentation of third line' do inspect_source(<<-RUBY.strip_margin('|')) | a. | b. | c RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts indented methods in for body' do inspect_source(<<-RUBY.strip_indent) for x in a something. something_else end RUBY expect(cop.highlights.empty?).to be(true) end it 'accepts alignment inside a grouped expression' do inspect_source(<<-RUBY.strip_indent) (a. b) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts an expression where the first method spans multiple lines' do inspect_source(<<-RUBY.strip_indent) subject.each do |item| result = resolve(locale) and return result end.a RUBY expect(cop.messages.empty?).to be(true) end it 'accepts any indentation of parameters to #[]' do inspect_source(<<-RUBY.strip_indent) payment = Models::IncomingPayments[ id: input['incoming-payment-id'], user_id: @user[:id]] RUBY expect(cop.messages.empty?).to be(true) end it "doesn't fail on unary operators" do inspect_source(<<-RUBY.strip_indent) def foo !0 .nil? end RUBY expect(cop.offenses.size).to eq(1) end it "doesn't crash on unaligned multiline lambdas" do expect_no_offenses(<<-RUBY.strip_indent) MyClass.(my_args) .my_method RUBY end end shared_examples 'common for aligned and indented' do it 'accepts even indentation of consecutive lines in typical RSpec code' do inspect_source(<<-RUBY.strip_indent) expect { Foo.new }. to change { Bar.count }. from(1).to(2) RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense for no indentation of second line' do inspect_source(<<-RUBY.strip_indent) a. b RUBY expect(cop.messages) .to eq(['Use 2 (not 0) spaces for indenting an expression spanning ' \ 'multiple lines.']) expect(cop.highlights).to eq(['b']) end it 'registers an offense for 3 spaces indentation of second line' do inspect_source(<<-RUBY.strip_indent) a. b c. d RUBY expect(cop.messages) .to eq(['Use 2 (not 3) spaces for indenting an expression spanning ' \ 'multiple lines.'] * 2) expect(cop.highlights).to eq(%w[b d]) end it 'registers an offense for extra indentation of third line' do inspect_source(<<-RUBY.strip_margin('|')) | a. | b. | c RUBY expect(cop.messages) .to eq(['Use 2 (not 4) spaces for indenting an expression spanning ' \ 'multiple lines.']) expect(cop.highlights).to eq(['c']) end it 'registers an offense for the emacs ruby-mode 1.1 indentation of an ' \ 'expression in an array' do inspect_source(<<-RUBY.strip_margin('|')) | [ | a. | b | ] RUBY expect(cop.messages) .to eq(['Use 2 (not 0) spaces for indenting an expression spanning ' \ 'multiple lines.']) expect(cop.highlights).to eq(['b']) end it 'registers an offense for extra indentation of 3rd line in typical ' \ 'RSpec code' do inspect_source(<<-RUBY.strip_indent) expect { Foo.new }. to change { Bar.count }. from(1).to(2) RUBY expect(cop.messages).to eq(['Use 2 (not 6) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['from']) end it 'registers an offense for proc call without a selector' do inspect_source(<<-RUBY.strip_indent) a .(args) RUBY expect(cop.messages).to eq(['Use 2 (not 1) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['.(']) end it 'registers an offense for one space indentation of second line' do inspect_source(<<-RUBY.strip_indent) a .b RUBY expect(cop.messages).to eq(['Use 2 (not 1) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['.b']) end end context 'when EnforcedStyle is aligned' do let(:cop_config) { { 'EnforcedStyle' => 'aligned' } } include_examples 'common' include_examples 'common for aligned and indented' # We call it semantic alignment when a dot is aligned with the first dot in # a chain of calls, and that first dot does not begin its line. context 'for semantic alignment' do it 'accepts method being aligned with method' do expect_no_offenses(<<-RUBY.strip_indent) User.all.first .age.to_s RUBY end it 'accepts method being aligned with method that is an argument' do expect_no_offenses(<<-RUBY.strip_indent) authorize scope.includes(:user) .order(:name) RUBY end it 'accepts method being aligned with method that is an argument in ' \ 'assignment' do inspect_source(['user = authorize scope.includes(:user)', ' .order(:name)']) expect(cop.offenses.empty?).to be(true) end it 'accepts method being aligned with method in assignment' do expect_no_offenses(<<-RUBY.strip_indent) age = User.all.first .age.to_s RUBY end it 'accepts aligned method even when an aref is in the chain' do expect_no_offenses(<<-RUBY.strip_indent) foo = '123'.a .b[1] .c RUBY end it 'accepts aligned method even when an aref is first in the chain' do expect_no_offenses(<<-RUBY.strip_indent) foo = '123'[1].a .b .c RUBY end it "doesn't fail on a chain of aref calls" do expect_no_offenses('a[1][2][3]') end it 'accepts aligned method with blocks in operation assignment' do expect_no_offenses(<<-RUBY.strip_indent) @comment_lines ||= src.comments .select { |c| begins_its_line?(c) } .map { |c| c.loc.line } RUBY end it 'accepts 3 aligned methods' do expect_no_offenses(<<-RUBY.strip_indent) a_class.new(severity, location, 'message', 'CopName') .severity .level RUBY end it 'registers an offense for unaligned methods' do expect_offense(<<-RUBY.strip_indent) User.a .b ^^ Align `.b` with `.a` on line 1. .c ^^ Align `.c` with `.a` on line 1. RUBY end it 'registers an offense for unaligned method in block body' do expect_offense(<<-RUBY.strip_indent) a do b.c .d ^^ Align `.d` with `.c` on line 2. end RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) User.all.first .age.to_s RUBY expect(new_source).to eq(<<-RUBY.strip_indent) User.all.first .age.to_s RUBY end end it 'accepts correctly aligned methods in operands' do expect_no_offenses(<<-RUBY.strip_indent) 1 + a .b .c + d. e RUBY end it 'accepts correctly aligned methods in assignment' do expect_no_offenses(<<-RUBY.strip_indent) def investigate(processed_source) @modifier = processed_source .tokens .select { |t| t.type == :k } .map(&:pos) end RUBY end it 'accepts aligned methods in if + assignment' do expect_no_offenses(<<-RUBY.strip_indent) KeyMap = Hash.new do |map, key| value = if key.respond_to?(:to_str) key else key.to_s.split('_'). each { |w| w.capitalize! }. join('-') end keymap_mutex.synchronize { map[key] = value } end RUBY end it 'accepts indented method when there is nothing to align with' do expect_no_offenses(<<-RUBY.strip_indent) expect { custom_formatter_class('NonExistentClass') } .to raise_error(NameError) RUBY end it 'registers an offense for one space indentation of third line' do expect_offense(<<-RUBY.strip_indent) a .b .c ^^ Use 2 (not 1) spaces for indenting an expression spanning multiple lines. RUBY end it 'accepts indented and aligned methods in binary operation' do # b is indented relative to a # .d is aligned with c expect_no_offenses(<<-RUBY.strip_indent) a. b + c .d RUBY end it 'accepts aligned methods in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a. b something end RUBY end it 'accepts aligned methods in a begin..end block' do expect_no_offenses(<<-RUBY.strip_indent) @dependencies ||= begin DEFAULT_DEPRUBYENCIES .reject { |e| e } .map { |e| e } end RUBY end it 'registers an offense for misaligned methods in if condition' do inspect_source(<<-RUBY.strip_indent) if a. b something end RUBY expect(cop.messages).to eq(['Align `b` with `a.` on line 1.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does not check binary operations when string wrapped with backslash' do expect_no_offenses(<<-RUBY.strip_indent) flash[:error] = 'Here is a string ' \ 'That spans' << 'multiple lines' RUBY end it 'does not check binary operations when string wrapped with +' do expect_no_offenses(<<-RUBY.strip_indent) flash[:error] = 'Here is a string ' + 'That spans' << 'multiple lines' RUBY end it 'registers an offense for misaligned method in []= call' do expect_offense(<<-RUBY.strip_indent) flash[:error] = here_is_a_string. that_spans. multiple_lines ^^^^^^^^^^^^^^ Align `multiple_lines` with `here_is_a_string.` on line 1. RUBY end it 'registers an offense for misaligned methods in unless condition' do inspect_source(<<-RUBY.strip_indent) unless a .b something end RUBY expect(cop.messages).to eq(['Align `.b` with `a` on line 1.']) expect(cop.highlights).to eq(['.b']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for misaligned methods in while condition' do expect_offense(<<-RUBY.strip_indent) while a. b ^ Align `b` with `a.` on line 1. something end RUBY end it 'registers an offense for misaligned methods in until condition' do expect_offense(<<-RUBY.strip_indent) until a. b ^ Align `b` with `a.` on line 1. something end RUBY end it 'accepts aligned method in return' do expect_no_offenses(<<-RUBY.strip_indent) def a return b. c end RUBY end it 'accepts aligned method in assignment + block + assignment' do expect_no_offenses(<<-RUBY.strip_indent) a = b do c.d = e. f end RUBY end it 'accepts aligned methods in assignment' do expect_no_offenses(<<-RUBY.strip_indent) formatted_int = int_part .to_s .reverse .gsub(/...(?=.)/, '&_') RUBY end it 'registers an offense for misaligned methods in local variable ' \ 'assignment' do inspect_source(<<-RUBY.strip_indent) a = b.c. d RUBY expect(cop.messages).to eq(['Align `d` with `b.c.` on line 1.']) expect(cop.highlights).to eq(['d']) end it 'accepts aligned methods in constant assignment' do expect_no_offenses(<<-RUBY.strip_indent) A = b .c RUBY end it 'accepts aligned methods in operator assignment' do expect_no_offenses(<<-RUBY.strip_indent) a += b .c RUBY end it 'registers an offense for unaligned methods in assignment' do expect_offense(<<-RUBY.strip_indent) bar = Foo .a ^^ Align `.a` with `Foo` on line 1. .b(c) RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a. b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a. b something end RUBY end end shared_examples 'both indented* styles' do # We call it semantic alignment when a dot is aligned with the first dot in # a chain of calls, and that first dot does not begin its line. But for the # indented style, it doesn't come into play. context 'for possible semantic alignment' do it 'accepts indented methods' do inspect_source(<<-RUBY.strip_indent) User.a .c .b RUBY expect(cop.messages.empty?).to be(true) expect(cop.highlights.empty?).to be(true) expect(cop.offenses.empty?).to be(true) end end end context 'when EnforcedStyle is indented_relative_to_receiver' do let(:cop_config) { { 'EnforcedStyle' => 'indented_relative_to_receiver' } } include_examples 'common' include_examples 'both indented* styles' it 'accepts correctly indented methods in operation' do inspect_source(<<-RUBY.strip_margin('|')) | 1 + a | .b | .c RUBY expect(cop.highlights.empty?).to be(true) expect(cop.offenses.empty?).to be(true) end it 'accepts indentation of consecutive lines in typical RSpec code' do expect_no_offenses(<<-RUBY.strip_indent) expect { Foo.new }.to change { Bar.count } .from(1).to(2) RUBY end it 'registers an offense for no indentation of second line' do expect_offense(<<-RUBY.strip_indent) a. b ^ Indent `b` 2 spaces more than `a` on line 1. RUBY end it 'registers an offense for extra indentation of 3rd line in typical ' \ 'RSpec code' do inspect_source(<<-RUBY.strip_indent) expect { Foo.new }. to change { Bar.count }. from(1).to(2) RUBY expect(cop.messages).to eq(['Indent `from` 2 spaces more than `change ' \ '{ Bar.count }` on line 2.']) expect(cop.highlights).to eq(['from']) end it 'registers an offense for proc call without a selector' do expect_offense(<<-RUBY.strip_indent) a .(args) ^^ Indent `.(` 2 spaces more than `a` on line 1. RUBY end it 'registers an offense for one space indentation of second line' do expect_offense(<<-RUBY.strip_indent) a .b ^^ Indent `.b` 2 spaces more than `a` on line 1. RUBY end it 'registers an offense for 3 spaces indentation of second line' do expect_offense(<<-RUBY.strip_indent) a. b ^ Indent `b` 2 spaces more than `a` on line 1. c. d ^ Indent `d` 2 spaces more than `c` on line 3. RUBY end it 'registers an offense for extra indentation of third line' do expect_offense(<<-RUBY.strip_indent) a. b. c ^ Indent `c` 2 spaces more than `a` on line 1. RUBY end it 'registers an offense for the emacs ruby-mode 1.1 indentation of an ' \ 'expression in an array' do inspect_source(<<-RUBY.strip_margin('|')) | [ | a. | b | ] RUBY expect(cop.messages) .to eq(['Indent `b` 2 spaces more than `a` on line 2.']) expect(cop.highlights).to eq(['b']) end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a. b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a. b something end RUBY end end context 'when EnforcedStyle is indented' do let(:cop_config) { { 'EnforcedStyle' => 'indented' } } include_examples 'common' include_examples 'common for aligned and indented' include_examples 'both indented* styles' it 'accepts correctly indented methods in operation' do inspect_source(<<-RUBY.strip_margin('|')) | 1 + a | .b | .c RUBY expect(cop.offenses.empty?).to be(true) expect(cop.highlights.empty?).to be(true) end it 'registers an offense for one space indentation of third line' do expect_offense(<<-RUBY.strip_indent) a .b .c ^^ Use 2 (not 1) spaces for indenting an expression spanning multiple lines. RUBY end it 'accepts indented methods in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a. b something end RUBY end it 'registers an offense for aligned methods in if condition' do inspect_source(<<-RUBY.strip_indent) if a. b something end RUBY expect(cop.messages).to eq(['Use 4 (not 3) spaces for indenting a ' \ 'condition in an `if` statement spanning ' \ 'multiple lines.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts normal indentation of method parameters' do expect_no_offenses(<<-RUBY.strip_indent) Parser::Source::Range.new(expr.source_buffer, begin_pos, begin_pos + line.length) RUBY end it 'accepts any indentation of method parameters' do expect_no_offenses(<<-RUBY.strip_indent) a(b. c .d) RUBY end it 'accepts normal indentation inside grouped expression' do expect_no_offenses(<<-RUBY.strip_indent) arg_array.size == a.size && ( arg_array == a || arg_array.map(&:children) == a.map(&:children) ) RUBY end [ %w[an if], %w[an unless], %w[a while], %w[an until] ].each do |article, keyword| it "accepts double indentation of #{keyword} condition" do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver. nil? && !args.empty? end RUBY expect(cop.messages.empty?).to be(true) end it "registers an offense for a 2 space indentation of #{keyword} " \ 'condition' do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver .nil? && !args.empty? end RUBY expect(cop.highlights).to eq(['.nil?']) expect(cop.messages).to eq(['Use 4 (not 2) spaces for indenting a ' \ "condition in #{article} `#{keyword}` " \ 'statement spanning multiple lines.']) end it "accepts indented methods in #{keyword} body" do inspect_source(<<-RUBY.strip_indent) #{keyword} a something. something_else end RUBY expect(cop.highlights.empty?).to be(true) end end %w[unless if].each do |keyword| it "accepts special indentation of return #{keyword} condition" do inspect_source(<<-RUBY.strip_indent) return #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) RUBY expect(cop.messages.empty?).to be(true) end end it 'registers an offense for wrong indentation of for expression' do expect_offense(<<-RUBY.strip_indent) for n in a. b ^ Use 4 (not 2) spaces for indenting a collection in a `for` statement spanning multiple lines. end RUBY end it 'accepts special indentation of for expression' do expect_no_offenses(<<-RUBY.strip_indent) for n in a. b end RUBY end it 'accepts indentation of assignment' do expect_no_offenses(<<-RUBY.strip_indent) formatted_int = int_part .abs .to_s .reverse .gsub(/...(?=.)/, '&_') .reverse RUBY end it 'registers an offense for correct + unrecognized style' do inspect_source(<<-RUBY.strip_indent) a. b c. d RUBY expect(cop.messages).to eq(['Use 2 (not 4) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(%w[d]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for aligned operators in assignment' do msg = 'Use %d (not %d) spaces for indenting an expression ' \ 'in an assignment spanning multiple lines.' expect_offense(<<-RUBY.strip_indent) formatted_int = int_part .abs ^^^^ #{format(msg, 2, 16)} .reverse ^^^^^^^^ #{format(msg, 2, 16)} RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a. b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a. b something end RUBY end context 'when indentation width is overridden for this cop' do let(:cop_indent) { 7 } it 'accepts indented methods' do expect_no_offenses(<<-RUBY.strip_indent) User.a .c .b RUBY end it 'accepts correctly indented methods in operation' do inspect_source(<<-RUBY.strip_margin('|')) | 1 + a | .b | .c RUBY expect(cop.offenses.empty?).to be(true) expect(cop.highlights.empty?).to be(true) end it 'accepts indented methods in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a. b something end RUBY end it 'accepts indentation of assignment' do expect_no_offenses(<<-RUBY.strip_indent) formatted_int = int_part .abs .to_s .reverse RUBY end [ %w[an if], %w[an unless], %w[a while], %w[an until] ].each do |article, keyword| it "accepts indentation of #{keyword} condition which is offset " \ 'by a single normal indentation step' do # normal code indentation is 2 spaces, and we have configured # multiline method indentation to 7 spaces # so in this case, 9 spaces are required inspect_source(<<-RUBY.strip_indent) #{keyword} receiver. nil? && !args.empty? end RUBY expect(cop.messages.empty?).to be(true) end it "registers an offense for a 4 space indentation of #{keyword} " \ 'condition' do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver .nil? && !args.empty? end RUBY expect(cop.highlights).to eq(['.nil?']) expect(cop.messages).to eq(['Use 9 (not 4) spaces for indenting a ' \ "condition in #{article} `#{keyword}` " \ 'statement spanning multiple lines.']) end it "accepts indented methods in #{keyword} body" do inspect_source(<<-RUBY.strip_indent) #{keyword} a something. something_else end RUBY expect(cop.highlights.empty?).to be(true) end end end end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_method_definition_brace_layout_spec.rb000066400000000000000000000015211322072016200316050ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineMethodDefinitionBraceLayout, :config do # rubocop:disable Metrics/LineLength subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } it 'ignores implicit defs' do expect_no_offenses(<<-RUBY.strip_indent) def foo a: 1, b: 2 end RUBY end it 'ignores single-line defs' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a,b) end RUBY end it 'ignores defs without params' do expect_no_offenses(<<-RUBY.strip_indent) def foo end RUBY end include_examples 'multiline literal brace layout' do let(:prefix) { 'def foo' } let(:suffix) { 'end' } let(:open) { '(' } let(:close) { ')' } let(:multi_prefix) { 'b: ' } end end rubocop-0.52.1/spec/rubocop/cop/layout/multiline_operation_indentation_spec.rb000066400000000000000000000462231322072016200277700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::MultilineOperationIndentation do subject(:cop) { described_class.new(config) } let(:config) do merged = RuboCop::ConfigLoader .default_configuration['Layout/MultilineOperationIndentation'] .merge(cop_config) .merge('IndentationWidth' => cop_indent) RuboCop::Config .new('Layout/MultilineOperationIndentation' => merged, 'Layout/IndentationWidth' => { 'Width' => indentation_width }) end let(:indentation_width) { 2 } let(:cop_indent) { nil } # use indentation width from Layout/IndentationWidth shared_examples 'common' do it 'accepts indented operands in ordinary statement' do inspect_source(<<-RUBY.strip_indent) a + b RUBY expect(cop.messages.empty?).to be(true) end it 'accepts indented operands inside and outside a block' do inspect_source(<<-RUBY.strip_indent) a = b.map do |c| c + b + d do x + y end end RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense for no indentation of second line' do inspect_source(<<-RUBY.strip_indent) a + b RUBY expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['b']) end it 'registers an offense for one space indentation of second line' do inspect_source(<<-RUBY.strip_indent) a + b RUBY expect(cop.messages).to eq(['Use 2 (not 1) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['b']) end it 'does not check method calls' do expect_no_offenses(<<-RUBY.strip_indent) a .(args) Foo .a .b Foo .a .b(c) expect { Foo.new }. to change { Bar.count }. from(1).to(2) RUBY end it 'registers an offense for three spaces indentation of second line' do inspect_source(<<-RUBY.strip_indent) a || b c and d RUBY expect(cop.messages).to eq(['Use 2 (not 3) spaces for indenting an ' \ 'expression spanning multiple lines.'] * 2) expect(cop.highlights).to eq(%w[b d]) end it 'registers an offense for extra indentation of third line' do inspect_source(<<-RUBY.strip_margin('|')) | a || | b || | c RUBY expect(cop.messages).to eq(['Use 2 (not 4) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['c']) end it 'registers an offense for the emacs ruby-mode 1.1 indentation of an ' \ 'expression in an array' do inspect_source(<<-RUBY.strip_margin('|')) | [ | a + | b | ] RUBY expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['b']) end it 'accepts indented operands in an array' do inspect_source(<<-RUBY.strip_margin('|')) | dm[i][j] = [ | dm[i-1][j-1] + | (this[j-1] == that[i-1] ? 0 : sub), | dm[i][j-1] + ins, | dm[i-1][j] + del | ].min RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts two spaces indentation in assignment of local variable' do inspect_source(<<-RUBY.strip_indent) a = 'foo' + 'bar' RUBY expect(cop.messages.empty?).to be(true) end it 'accepts two spaces indentation in assignment of array element' do inspect_source(<<-RUBY.strip_indent) a['test'] = 'foo' + 'bar' RUBY expect(cop.messages.empty?).to be(true) end it 'accepts two spaces indentation of second line' do inspect_source(<<-RUBY.strip_margin('|')) | a || | b RUBY expect(cop.messages.empty?).to be(true) end it 'accepts no extra indentation of third line' do inspect_source(<<-RUBY.strip_margin('|')) | a && | b && | c RUBY expect(cop.messages.empty?).to be(true) end it 'accepts indented operands in for body' do inspect_source(<<-RUBY.strip_indent) for x in a something && something_else end RUBY expect(cop.highlights.empty?).to be(true) end it 'accepts alignment inside a grouped expression' do inspect_source(<<-RUBY.strip_indent) (a + b) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts an expression where the first operand spans multiple lines' do inspect_source(<<-RUBY.strip_indent) subject.each do |item| result = resolve(locale) and return result end and nil RUBY expect(cop.messages.empty?).to be(true) end it 'accepts any indentation of parameters to #[]' do inspect_source(<<-RUBY.strip_indent) payment = Models::IncomingPayments[ id: input['incoming-payment-id'], user_id: @user[:id]] RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense for an unindented multiline operation that is ' \ 'the left operand in another operation' do inspect_source(<<-RUBY.strip_indent) a + b < 3 RUBY expect(cop.messages).to eq(['Use 2 (not 0) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(['b']) end end context 'when EnforcedStyle is aligned' do let(:cop_config) { { 'EnforcedStyle' => 'aligned' } } include_examples 'common' it 'accepts aligned operands in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a + b something end RUBY end it 'registers an offense for indented operands in if condition' do inspect_source(<<-RUBY.strip_indent) if a + b something end RUBY expect(cop.messages).to eq(['Align the operands of a condition in an ' \ '`if` statement spanning multiple lines.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indented') end it 'accepts indented code on LHS of equality operator' do expect_no_offenses(<<-RUBY.strip_indent) def config_to_allow_offenses a + b == c end RUBY end it 'accepts indented operands inside block + assignment' do expect_no_offenses(<<-RUBY.strip_indent) a = b.map do |c| c + d end requires_interpolation = node.children.any? do |s| s.type == :dstr || s.loc.expression.source =~ REGEXP end RUBY end it 'accepts indented operands with ternary operators' do expect_no_offenses(<<-RUBY.strip_indent) one || two ? 3 : 5 RUBY end it 'registers an offense for indented second part of string' do inspect_source(<<-RUBY.strip_indent) it "should convert " + "a to " + "b" do end RUBY expect(cop.messages).to eq(['Align the operands of an expression ' \ 'spanning multiple lines.'] * 2) expect(cop.highlights).to eq(['"a to "', '"b"']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indented') end it 'registers an offense for indented operand in second argument' do inspect_source(<<-RUBY.strip_indent) puts a, 1 + 2 RUBY expect(cop.messages) .to eq(['Align the operands of an expression spanning multiple lines.']) expect(cop.highlights).to eq(['2']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'indented') end it 'registers an offense for misaligned string operand when the first ' \ 'operand has backslash continuation' do inspect_source(['def f', " flash[:error] = 'Here is a string ' \\", " 'That spans' <<", " 'multiple lines'", 'end']) expect(cop.messages).to eq(['Align the operands of an expression in an ' \ 'assignment spanning multiple lines.']) expect(cop.highlights).to eq(["'multiple lines'"]) end it 'registers an offense for misaligned string operand when plus is used' do expect_offense(<<-RUBY.strip_indent) Error = 'Here is a string ' + 'That spans' << 'multiple lines' ^^^^^^^^^^^^^^^^ Align the operands of an expression in an assignment spanning multiple lines. RUBY end it 'registers an offense for misaligned operands in unless condition' do inspect_source(<<-RUBY.strip_indent) unless a + b something end RUBY expect(cop.messages).to eq(['Align the operands of a condition in an ' \ '`unless` statement spanning multiple ' \ 'lines.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end [ %w[an if], %w[an unless], %w[a while], %w[an until] ].each do |article, keyword| it "registers an offense for misaligned operands in #{keyword} " \ 'condition' do inspect_source(<<-RUBY.strip_indent) #{keyword} a or b something end RUBY expect(cop.messages).to eq(['Align the operands of a condition in ' \ "#{article} `#{keyword}` statement " \ 'spanning multiple lines.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'indented') end end it 'accepts aligned operands in assignment' do expect_no_offenses(<<-RUBY.strip_indent) a = b + c + d RUBY end it 'accepts aligned or:ed operands in assignment' do expect_no_offenses(<<-RUBY.strip_indent) tmp_dir = ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] || Etc.systmpdir || '/tmp' RUBY end it 'registers an offense for unaligned operands in op-assignment' do expect_offense(<<-RUBY.strip_indent) bar *= Foo + a + ^ Align the operands of an expression in an assignment spanning multiple lines. b(c) RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a + b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a + b something end RUBY end end context 'when EnforcedStyle is indented' do let(:cop_config) { { 'EnforcedStyle' => 'indented' } } include_examples 'common' it 'accepts indented operands in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a + b something end RUBY end it 'registers an offense for aligned operands in if condition' do inspect_source(<<-RUBY.strip_indent) if a + b something end RUBY expect(cop.messages).to eq(['Use 4 (not 3) spaces for indenting a ' \ 'condition in an `if` statement spanning ' \ 'multiple lines.']) expect(cop.highlights).to eq(['b']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'aligned') end it 'accepts the indentation of a broken string' do expect_no_offenses(<<-RUBY.strip_indent) MSG = 'Use 2 (not %d) spaces for indenting a ' \ 'broken line.' RUBY end it 'accepts normal indentation of method parameters' do expect_no_offenses(<<-RUBY.strip_indent) Parser::Source::Range.new(expr.source_buffer, begin_pos, begin_pos + line.length) RUBY end it 'accepts any indentation of method parameters' do expect_no_offenses(<<-RUBY.strip_indent) a(b + c + d) RUBY end it 'accepts normal indentation inside grouped expression' do expect_no_offenses(<<-RUBY.strip_indent) arg_array.size == a.size && ( arg_array == a || arg_array.map(&:children) == a.map(&:children) ) RUBY end it 'registers an offense for aligned code on LHS of equality operator' do expect_offense(<<-RUBY.strip_indent) def config_to_allow_offenses a + b == c ^ Use 2 (not 0) spaces for indenting an expression spanning multiple lines. end RUBY end [ %w[an if], %w[an unless], %w[a while], %w[an until] ].each do |article, keyword| it "accepts double indentation of #{keyword} condition" do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) end #{keyword} receiver. nil? end RUBY expect(cop.messages.empty?).to be(true) end it "registers an offense for a 2 space indentation of #{keyword} " \ 'condition' do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) end RUBY expect(cop.highlights).to eq(['!args.empty?', 'BLACKLIST.include?(method_name)']) expect(cop.messages).to eq(['Use 4 (not 2) spaces for indenting a ' \ "condition in #{article} `#{keyword}` " \ 'statement spanning multiple lines.'] * 2) end it "accepts indented operands in #{keyword} body" do inspect_source(<<-RUBY.strip_indent) #{keyword} a something && something_else end RUBY expect(cop.highlights.empty?).to be(true) end end %w[unless if].each do |keyword| it "accepts special indentation of return #{keyword} condition" do inspect_source(<<-RUBY.strip_indent) return #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) RUBY expect(cop.messages.empty?).to be(true) end end it 'registers an offense for wrong indentation of for expression' do expect_offense(<<-RUBY.strip_indent) for n in a + b ^ Use 4 (not 2) spaces for indenting a collection in a `for` statement spanning multiple lines. end RUBY end it 'accepts special indentation of for expression' do expect_no_offenses(<<-RUBY.strip_indent) for n in a + b end RUBY end it 'accepts indentation of assignment' do expect_no_offenses(<<-RUBY.strip_indent) a = b + c + d RUBY end it 'registers an offense for correct + unrecognized style' do inspect_source(<<-RUBY.strip_indent) a || b c and d RUBY expect(cop.messages).to eq(['Use 2 (not 4) spaces for indenting an ' \ 'expression spanning multiple lines.']) expect(cop.highlights).to eq(%w[d]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for aligned operators in assignment' do msg = 'Use %d (not %d) spaces for indenting an expression in ' \ 'an assignment spanning multiple lines.' expect_offense(<<-RUBY.strip_indent) a = b + c + ^ #{format(msg, 2, 4)} d ^ #{format(msg, 2, 4)} RUBY end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a + b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a + b something end RUBY end context 'when indentation width is overridden for this cop' do let(:cop_indent) { 6 } it 'accepts indented operands in if condition' do expect_no_offenses(<<-RUBY.strip_indent) if a + b something end RUBY end [ %w[an if], %w[an unless], %w[a while], %w[an until] ].each do |article, keyword| it "accepts indentation of #{keyword} condition which is offset " \ 'by a single normal indentation step' do # normal code indentation is 2 spaces, and we have configured # multiline method indentation to 6 spaces # so in this case, 8 spaces are required inspect_source(<<-RUBY.strip_indent) #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) end #{keyword} receiver. nil? end RUBY expect(cop.messages.empty?).to be(true) end it "registers an offense for a 4 space indentation of #{keyword} " \ 'condition' do inspect_source(<<-RUBY.strip_indent) #{keyword} receiver.nil? && !args.empty? && BLACKLIST.include?(method_name) end RUBY expect(cop.highlights).to eq(['!args.empty?', 'BLACKLIST.include?(method_name)']) expect(cop.messages).to eq(['Use 8 (not 4) spaces for indenting a ' \ "condition in #{article} `#{keyword}` " \ 'statement spanning multiple lines.'] * 2) end it "accepts indented operands in #{keyword} body" do inspect_source(<<-RUBY.strip_indent) #{keyword} a something && something_else end RUBY expect(cop.highlights.empty?).to be(true) end end it 'auto-corrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) until a + b something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until a + b something end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/rescue_ensure_alignment_spec.rb000066400000000000000000000107431322072016200262150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::RescueEnsureAlignment, :config do subject(:cop) { described_class.new(config) } shared_examples 'common behavior' do |keyword| context 'bad alignment' do it 'registers an offense when used with begin' do inspect_source(<<-RUBY.strip_indent) begin something #{keyword} error end RUBY expect(cop.messages).to eq(["`#{keyword}` at 3, 4 is not aligned with" \ ' `end` at 5, 0.']) end it 'registers an offense when used with def' do inspect_source(<<-RUBY.strip_indent) def test something #{keyword} error end RUBY expect(cop.messages).to eq(["`#{keyword}` at 3, 4 is not aligned with" \ ' `end` at 5, 0.']) end it 'registers an offense when used with defs' do inspect_source(<<-RUBY.strip_indent) def Test.test something #{keyword} error end RUBY expect(cop.messages).to eq(["`#{keyword}` at 3, 4 is not aligned with" \ ' `end` at 5, 0.']) end it 'registers an offense when used with class' do inspect_source(<<-RUBY.strip_indent) class C something #{keyword} error end RUBY expect(cop.messages).to eq(["`#{keyword}` at 3, 4 is not aligned with" \ ' `end` at 5, 0.']) end it 'registers an offense when used with module' do inspect_source(<<-RUBY.strip_indent) module M something #{keyword} error end RUBY expect(cop.messages).to eq(["`#{keyword}` at 3, 4 is not aligned with" \ ' `end` at 5, 0.']) end it 'accepts rescue and ensure on the same line' do inspect_source('begin; puts 1; rescue; ensure; puts 2; end') expect(cop.messages.empty?).to be(true) end it 'auto-corrects' do corrected = autocorrect_source(<<-RUBY.strip_indent) begin something #{keyword} error end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) begin something #{keyword} error end RUBY end end it 'accepts correct alignment' do inspect_source(['begin', ' something', keyword, ' error', 'end']) expect(cop.messages.empty?).to be(true) end context '>= Ruby 2.5', :ruby25 do it "accepts aligned #{keyword} in do-end block" do expect_no_offenses(<<-RUBY.strip_indent) [1, 2, 3].each do |el| el.to_s rescue StandardError => _exception next end RUBY end it "accepts aligned #{keyword} in do-end block in a method" do expect_no_offenses(<<-RUBY.strip_indent) def foo [1, 2, 3].each do |el| el.to_s rescue StandardError => _exception next end end RUBY end it "registers an offense for not aligned #{keyword} in do-end block" do expect_offense(<<-RUBY.strip_indent) def foo [1, 2, 3].each do |el| el.to_s rescue StandardError => _exception ^^^^^^ `rescue` at 4, 0 is not aligned with `end` at 6, 2. next end end RUBY end end end context 'rescue' do it_behaves_like 'common behavior', 'rescue' it 'accepts the modifier form' do expect_no_offenses('test rescue nil') end end context 'ensure' do it_behaves_like 'common behavior', 'ensure' end describe 'excluded file' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/RescueEnsureAlignment' => { 'Enabled' => true, 'Exclude' => ['**/**'] }) end it 'processes excluded files with issue' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue bar end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_after_colon_spec.rb000066400000000000000000000030121322072016200247450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAfterColon do subject(:cop) { described_class.new } it 'registers an offense for colon without space after it' do expect_offense(<<-RUBY.strip_indent) {a:3} ^ Space missing after colon. RUBY end it 'accepts colons in symbols' do expect_no_offenses('x = :a') end it 'accepts colon in ternary followed by space' do expect_no_offenses('x = w ? a : b') end it 'accepts hashes with a space after colons' do expect_no_offenses('{a: 3}') end it 'accepts hash rockets' do expect_no_offenses('x = {"a"=>1}') end it 'accepts if' do expect_no_offenses(<<-RUBY.strip_indent) x = if w a end RUBY end it 'accepts colons in strings' do expect_no_offenses("str << ':'") end it 'accepts required keyword arguments' do expect_no_offenses(<<-RUBY.strip_indent) def f(x:, y:) end RUBY end it 'accepts colons denoting required keyword argument' do expect_no_offenses(<<-RUBY.strip_indent) def initialize(table:, nodes:) end RUBY end it 'registers an offence if an keyword optional argument has no space' do expect_offense(<<-RUBY.strip_indent) def m(var:1, other_var: 2) ^ Space missing after colon. end RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source('def f(a:, b:2); {a:3}; end') expect(new_source).to eq('def f(a:, b: 2); {a: 3}; end') end end rubocop-0.52.1/spec/rubocop/cop/layout/space_after_comma_spec.rb000066400000000000000000000046341322072016200247420ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAfterComma do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/SpaceInsideHashLiteralBraces' => brace_config) end let(:brace_config) { {} } shared_examples 'ends with an item' do |items, correct_items| it 'registers an offense' do inspect_source(source.call(items)) expect(cop.messages).to eq( ['Space missing after comma.'] ) end it 'does auto-correction' do new_source = autocorrect_source(source.call(items)) expect(new_source).to eq source.call(correct_items) end end shared_examples 'trailing comma' do |items| it 'accepts the last comma' do inspect_source(source.call(items)) expect(cop.messages.empty?).to be(true) end end context 'block argument commas without space' do let(:source) { ->(args) { "each { |#{args}| }" } } it_behaves_like 'ends with an item', 's,t', 's, t' it_behaves_like 'trailing comma', 's, t,' end context 'array index commas without space' do let(:source) { ->(items) { "formats[#{items}]" } } it_behaves_like 'ends with an item', '0,1', '0, 1' it_behaves_like 'trailing comma', '0,' end context 'method call arg commas without space' do let(:source) { ->(args) { "a(#{args})" } } it_behaves_like 'ends with an item', '1,2', '1, 2' end context 'inside hash braces' do shared_examples 'common behavior' do it 'accepts a space between a comma and a closing brace' do inspect_source('{ foo:bar, }') expect(cop.messages.empty?).to be(true) end end context 'when EnforcedStyle for SpaceInsideBlockBraces is space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'space' } end it_behaves_like 'common behavior' it 'registers an offense for no space between a comma and a ' \ 'closing brace' do inspect_source('{ foo:bar,}') expect(cop.messages).to eq(['Space missing after comma.']) end end context 'when EnforcedStyle for SpaceInsideBlockBraces is no_space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'no_space' } end it_behaves_like 'common behavior' it 'accepts no space between a comma and a closing brace' do expect_no_offenses('{foo:bar,}') end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_after_method_name_spec.rb000066400000000000000000000040771322072016200261270ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAfterMethodName do subject(:cop) { described_class.new } it 'registers an offense for def with space before the parenthesis' do expect_offense(<<-RUBY.strip_indent) def func (x) ^ Do not put a space between a method name and the opening parenthesis. a end RUBY end it 'registers offense for class def with space before parenthesis' do expect_offense(<<-RUBY.strip_indent) def self.func (x) ^ Do not put a space between a method name and the opening parenthesis. a end RUBY end it 'registers offense for assignment def with space before parenthesis' do expect_offense(<<-RUBY.strip_indent) def func= (x) ^ Do not put a space between a method name and the opening parenthesis. a end RUBY end it 'accepts a def without arguments' do expect_no_offenses(<<-RUBY.strip_indent) def func a end RUBY end it 'accepts a defs without arguments' do expect_no_offenses(<<-RUBY.strip_indent) def self.func a end RUBY end it 'accepts a def with arguments but no parentheses' do expect_no_offenses(<<-RUBY.strip_indent) def func x a end RUBY end it 'accepts class method def with arguments but no parentheses' do expect_no_offenses(<<-RUBY.strip_indent) def self.func x a end RUBY end it 'accepts an assignment def with arguments but no parentheses' do expect_no_offenses(<<-RUBY.strip_indent) def func= x a end RUBY end it 'auto-corrects unwanted space' do new_source = autocorrect_source(<<-RUBY.strip_indent) def func (x) a end def self.func (x) a end def func= (x) a end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def func(x) a end def self.func(x) a end def func=(x) a end RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/space_after_not_spec.rb000066400000000000000000000023731322072016200244440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAfterNot do subject(:cop) { described_class.new } it 'reports an offense for space after !' do expect_offense(<<-RUBY.strip_indent) ! something ^^^^^^^^^^^ Do not leave space between `!` and its argument. RUBY end it 'accepts no space after !' do expect_no_offenses('!something') end it 'accepts space after not keyword' do expect_no_offenses('not something') end it 'reports an offense for space after ! with the negated receiver ' \ 'wrapped in parentheses' do inspect_source('! (model)') expect(cop.messages) .to eq(['Do not leave space between `!` and its argument.']) expect(cop.highlights).to eq(['! (model)']) end context 'auto-correct' do it 'removes redundant space' do new_source = autocorrect_source('! something') expect(new_source).to eq('!something') end it 'keeps space after not keyword' do new_source = autocorrect_source('not something') expect(new_source).to eq('not something') end it 'removes redundant space when there is a parentheses' do new_source = autocorrect_source('! (model)') expect(new_source).to eq('!(model)') end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_after_semicolon_spec.rb000066400000000000000000000033251322072016200256320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAfterSemicolon do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/SpaceInsideBlockBraces' => brace_config) end let(:brace_config) { {} } it 'registers an offense for semicolon without space after it' do expect_offense(<<-RUBY.strip_indent) x = 1;y = 2 ^ Space missing after semicolon. RUBY end it 'does not crash if semicolon is the last character of the file' do expect_no_offenses('x = 1;') end it 'auto-corrects missing space' do new_source = autocorrect_source('x = 1;y = 2') expect(new_source).to eq('x = 1; y = 2') end context 'inside block braces' do shared_examples 'common behavior' do it 'accepts a space between a semicolon and a closing brace' do inspect_source('test { ; }') expect(cop.messages.empty?).to be(true) end end context 'when EnforcedStyle for SpaceInsideBlockBraces is space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'space' } end it_behaves_like 'common behavior' it 'registers an offense for no space between a semicolon and a ' \ 'closing brace' do inspect_source('test { ;}') expect(cop.messages).to eq(['Space missing after semicolon.']) end end context 'when EnforcedStyle for SpaceInsideBlockBraces is no_space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'no_space' } end it_behaves_like 'common behavior' it 'accepts no space between a semicolon and a closing brace' do expect_no_offenses('test { ;}') end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_around_block_parameters_spec.rb000066400000000000000000000165431322072016200273540ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAroundBlockParameters, :config do subject(:cop) { described_class.new(config) } shared_examples 'common behavior' do it 'accepts an empty block' do expect_no_offenses('{}.each {}') end it 'skips lambda without args' do expect_no_offenses('->() { puts "a" }') end it 'skips lambda without parens' do expect_no_offenses('->a { puts a }') end end context 'when EnforcedStyleInsidePipes is no_space' do let(:cop_config) { { 'EnforcedStyleInsidePipes' => 'no_space' } } include_examples 'common behavior' it 'accepts a block with spaces in the right places' do expect_no_offenses('{}.each { |x, y| puts x }') end it 'accepts a block with parameters but no body' do expect_no_offenses('{}.each { |x, y| }') end it 'accepts a block parameter without preceding space' do # This is checked by Layout/SpaceAfterComma. expect_no_offenses('{}.each { |x,y| puts x }') end it 'accepts a lambda with spaces in the right places' do expect_no_offenses('->(x, y) { puts x }') end it 'registers an offense for space before first parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { | x| puts x } ^ Space before first block parameter detected. RUBY end it 'registers an offense for space after last parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { |x, y | puts x } ^^ Space after last block parameter detected. RUBY end it 'registers an offense for no space after closing pipe' do expect_offense(<<-RUBY.strip_indent) {}.each { |x, y|puts x } ^ Space after closing `|` missing. RUBY end it 'registers an offense to a lambda for space before first parameter' do expect_offense(<<-RUBY.strip_indent) ->( x, y) { puts x } ^ Space before first block parameter detected. RUBY end it 'registers an offense to a lambda for space after last parameter' do expect_offense(<<-RUBY.strip_indent) ->(x, y ) { puts x } ^^ Space after last block parameter detected. RUBY end it 'accepts line break after closing pipe' do expect_no_offenses(<<-RUBY.strip_indent) {}.each do |x, y| puts x end RUBY end it 'registers an offense for multiple spaces before parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { |x, y| puts x } ^^ Extra space before block parameter detected. RUBY end context 'trailing comma' do it 'registers an offense for space after the last comma' do expect_offense(<<-RUBY.strip_indent) {}.each { |x, | puts x } ^ Space after last block parameter detected. RUBY end it 'accepts no space after the last comma' do expect_no_offenses('{}.each { |x,| puts x }') end end it 'auto-corrects offenses' do new_source = autocorrect_source('{}.each { | x=5, (y,*z) |puts x }') expect(new_source).to eq('{}.each { |x=5, (y,*z)| puts x }') end it 'auto-corrects offenses for a lambda' do new_source = autocorrect_source('->( a, b, c) { puts a }') expect(new_source).to eq('->(a, b, c) { puts a }') end end context 'when EnforcedStyleInsidePipes is space' do let(:cop_config) { { 'EnforcedStyleInsidePipes' => 'space' } } include_examples 'common behavior' it 'accepts a block with spaces in the right places' do expect_no_offenses('{}.each { | x, y | puts x }') end it 'accepts a block with parameters but no body' do expect_no_offenses('{}.each { | x, y | }') end it 'accepts a block parameter without preceding space' do # This is checked by Layout/SpaceAfterComma. expect_no_offenses('{}.each { | x,y | puts x }') end it 'accepts a lambda with spaces in the right places' do expect_no_offenses('->( x, y ) { puts x }') end it 'registers an offense for no space before first parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { |x | puts x } ^ Space before first block parameter missing. RUBY end it 'registers an offense for no space after last parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { | x, y| puts x } ^ Space after last block parameter missing. RUBY end it 'registers an offense for extra space before first parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { | x | puts x } ^ Extra space before first block parameter detected. RUBY end it 'registers an offense for multiple spaces after last parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { | x, y | puts x } ^^ Extra space after last block parameter detected. RUBY end it 'registers an offense for no space after closing pipe' do expect_offense(<<-RUBY.strip_indent) {}.each { | x, y |puts x } ^ Space after closing `|` missing. RUBY end it 'registers an offense to a lambda for no space before first parameter' do expect_offense(<<-RUBY.strip_indent) ->(x ) { puts x } ^ Space before first block parameter missing. RUBY end it 'registers an offense to a lambda for no space after last parameter' do expect_offense(<<-RUBY.strip_indent) ->( x, y) { puts x } ^ Space after last block parameter missing. RUBY end it 'registers an offense to a lambda for extra space' \ 'before first parameter' do expect_offense(<<-RUBY.strip_indent) ->( x ) { puts x } ^ Extra space before first block parameter detected. RUBY end it 'registers an offense to a lambda for multiple spaces' \ 'after last parameter' do expect_offense(<<-RUBY.strip_indent) ->( x, y ) { puts x } ^^ Extra space after last block parameter detected. RUBY end it 'accepts line break after closing pipe' do expect_no_offenses(<<-RUBY.strip_indent) {}.each do | x, y | puts x end RUBY end it 'registers an offense for multiple spaces before parameter' do expect_offense(<<-RUBY.strip_indent) {}.each { | x, y | puts x } ^^ Extra space before block parameter detected. RUBY end context 'trailing comma' do it 'accepts space after the last comma' do expect_no_offenses('{}.each { | x, | puts x }') end it 'registers an offense for no space after the last comma' do expect_offense(<<-RUBY.strip_indent) {}.each { | x,| puts x } ^ Space after last block parameter missing. RUBY end end it 'auto-corrects block arguments inside Hash#each' do new_source = autocorrect_source('{}.each { | x=5, (y,*z)|puts x }') expect(new_source).to eq('{}.each { | x=5, (y,*z) | puts x }') end it 'auto-corrects lambda args' do new_source = autocorrect_source('->( x, y) { puts x }') expect(new_source).to eq('->( x, y ) { puts x }') end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_around_equals_in_parameter_default_spec.rb000066400000000000000000000070751322072016200315630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAroundEqualsInParameterDefault, :config do # rubocop:disable Metrics/LineLength subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is space' do let(:cop_config) { { 'EnforcedStyle' => 'space' } } it 'registers an offense for default value assignment without space' do inspect_source(<<-RUBY.strip_indent) def f(x, y=0, z= 1) end RUBY expect(cop.messages) .to eq(['Surrounding space missing in default value assignment.'] * 2) expect(cop.highlights).to eq(['=', '= ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for assignment empty string without space' do inspect_source(<<-RUBY.strip_indent) def f(x, y="", z=1) end RUBY expect(cop.offenses.size).to eq(2) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space') end it 'registers an offense for assignment of empty list without space' do expect_offense(<<-RUBY.strip_indent) def f(x, y=[]) ^ Surrounding space missing in default value assignment. end RUBY end it 'accepts default value assignment with space' do expect_no_offenses(<<-RUBY.strip_indent) def f(x, y = 0, z = {}) end RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source(['def f(x, y=0, z=1)', 'end']) expect(new_source).to eq(['def f(x, y = 0, z = 1)', 'end'].join("\n")) end it 'accepts default value assignment with spaces and unary + operator' do expect_no_offenses(<<-RUBY.strip_indent) def f(x, y = +1, z = {}) end RUBY end it 'auto-corrects missing space for arguments with unary operators' do new_source = autocorrect_source(<<-RUBY.strip_indent) def f(x=-1, y= 0, z =+1) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def f(x = -1, y = 0, z = +1) end RUBY end end context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } it 'registers an offense for default value assignment with space' do inspect_source(<<-RUBY.strip_indent) def f(x, y = 0, z =1, w= 2) end RUBY expect(cop.messages) .to eq(['Surrounding space detected in default value assignment.'] * 3) expect(cop.highlights).to eq([' = ', ' =', '= ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for assignment empty string with space' do inspect_source(<<-RUBY.strip_indent) def f(x, y = "", z = 1) end RUBY expect(cop.offenses.size).to eq(2) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space') end it 'registers an offense for assignment of empty list with space' do expect_offense(<<-RUBY.strip_indent) def f(x, y = []) ^^^ Surrounding space detected in default value assignment. end RUBY end it 'accepts default value assignment without space' do expect_no_offenses(<<-RUBY.strip_indent) def f(x, y=0, z={}) end RUBY end it 'auto-corrects unwanted space' do new_source = autocorrect_source(<<-RUBY.strip_indent) def f(x, y = 0, z= 1, w= 2) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def f(x, y=0, z=1, w=2) end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_around_keyword_spec.rb000066400000000000000000000220641322072016200255160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAroundKeyword do subject(:cop) { described_class.new } shared_examples 'missing before' do |highlight, expr, correct| it 'registers an offense for missing space before keyword in ' \ "`#{expr}`" do inspect_source(expr) expect(cop.messages) .to eq(["Space before keyword `#{highlight}` is missing."]) expect(cop.highlights).to eq([highlight]) end it 'auto-corrects' do expect(autocorrect_source(expr)).to eq correct end end shared_examples 'missing after' do |highlight, expr, correct| it 'registers an offense for missing space after keyword in ' \ "`#{expr}`" do inspect_source(expr) expect(cop.messages) .to eq(["Space after keyword `#{highlight}` is missing."]) expect(cop.highlights).to eq([highlight]) end it 'auto-corrects' do expect(autocorrect_source(expr)).to eq correct end end shared_examples 'accept before' do |after, expr| it "accepts `#{after}` before keyword in `#{expr}`" do inspect_source(expr) expect(cop.offenses.empty?).to be(true) end end shared_examples 'accept after' do |after, expr| it "accepts `#{after}` after keyword in `#{expr}`" do inspect_source(expr) expect(cop.offenses.empty?).to be(true) end end shared_examples 'accept around' do |after, expr| it "accepts `#{after}` around keyword in `#{expr}`" do inspect_source(expr) expect(cop.offenses.empty?).to be(true) end end it_behaves_like 'missing after', 'BEGIN', 'BEGIN{}', 'BEGIN {}' it_behaves_like 'missing after', 'END', 'END{}', 'END {}' it_behaves_like 'missing before', 'and', '1and 2', '1 and 2' it_behaves_like 'missing after', 'and', '1 and(2)', '1 and (2)' it_behaves_like 'missing after', 'begin', 'begin"" end', 'begin "" end' it_behaves_like 'missing after', 'break', 'break""', 'break ""' it_behaves_like 'accept after', '(', 'break(1)' it_behaves_like 'missing after', 'case', 'case"" when 1; end', 'case "" when 1; end' it_behaves_like 'missing before', 'do', 'a "b"do end', 'a "b" do end' it_behaves_like 'missing after', 'do', 'a do|x| end', 'a do |x| end' it_behaves_like 'missing before', 'do', 'while 1do end', 'while 1 do end' it_behaves_like 'missing after', 'do', 'while 1 do"x" end', 'while 1 do "x" end' it_behaves_like 'missing before', 'do', 'until 1do end', 'until 1 do end' it_behaves_like 'missing after', 'do', 'until 1 do"x" end', 'until 1 do "x" end' it_behaves_like 'missing before', 'do', 'for x in []do end', 'for x in [] do end' it_behaves_like 'missing after', 'do', 'for x in [] do"x" end', 'for x in [] do "x" end' it_behaves_like 'missing before', 'end', 'begin "a"end', 'begin "a" end' it_behaves_like 'missing before', 'end', 'if a; "b"end', 'if a; "b" end' it_behaves_like 'missing before', 'end', 'a do "a"end', 'a do "a" end' it_behaves_like 'missing before', 'end', 'while 1 do "x"end', 'while 1 do "x" end' it_behaves_like 'missing before', 'end', 'until 1 do "x"end', 'until 1 do "x" end' it_behaves_like 'missing before', 'end', 'for x in [] do "x"end', 'for x in [] do "x" end' it_behaves_like 'accept after', '.', 'begin end.inspect' it_behaves_like 'missing before', 'else', 'if a; ""else end', 'if a; "" else end' it_behaves_like 'missing after', 'else', 'if a; else"" end', 'if a; else "" end' it_behaves_like 'missing before', 'else', 'begin rescue; ""else end', 'begin rescue; "" else end' it_behaves_like 'missing after', 'else', 'begin rescue; else"" end', 'begin rescue; else "" end' it_behaves_like 'missing before', 'else', 'case a; when b; ""else end', 'case a; when b; "" else end' it_behaves_like 'missing after', 'else', 'case a; when b; else"" end', 'case a; when b; else "" end' it_behaves_like 'missing before', 'elsif', 'if a; ""elsif b; end', 'if a; "" elsif b; end' it_behaves_like 'missing after', 'elsif', 'if a; elsif""; end', 'if a; elsif ""; end' it_behaves_like 'missing before', 'elsif', 'if a; ""elsif b; end', 'if a; "" elsif b; end' it_behaves_like 'missing after', 'elsif', 'if a; elsif""; end', 'if a; elsif ""; end' it_behaves_like 'missing before', 'ensure', 'begin ""ensure end', 'begin "" ensure end' it_behaves_like 'missing after', 'ensure', 'begin ensure"" end', 'begin ensure "" end' it_behaves_like 'missing after', 'if', 'if""; end', 'if ""; end' it_behaves_like 'missing after', 'next', 'next""', 'next ""' it_behaves_like 'accept after', '(', 'next(1)' it_behaves_like 'missing after', 'not', 'not""', 'not ""' it_behaves_like 'accept after', '(', 'not(1)' it_behaves_like 'missing before', 'or', '1or 2', '1 or 2' it_behaves_like 'missing after', 'or', '1 or(2)', '1 or (2)' it_behaves_like 'missing before', 'rescue', '""rescue a', '"" rescue a' it_behaves_like 'missing after', 'rescue', 'a rescue""', 'a rescue ""' it_behaves_like 'accept after', 'rescue', 'begin; rescue(Error); end', 'begin; rescue(Error); end' it_behaves_like 'missing after', 'return', 'return""', 'return ""' it_behaves_like 'accept after', '(', 'return(1)' it_behaves_like 'missing after', 'super', 'super""', 'super ""' it_behaves_like 'accept after', '(', 'super(1)' it_behaves_like 'missing after', 'super', 'super{}', 'super {}' it_behaves_like 'accept after', '(', 'defined?(1)' it_behaves_like 'missing after', 'defined?', 'defined?1', 'defined? 1' it_behaves_like 'missing before', 'then', 'if ""then a end', 'if "" then a end' it_behaves_like 'missing after', 'then', 'if a then"" end', 'if a then "" end' it_behaves_like 'missing after', 'unless', 'unless""; end', 'unless ""; end' it_behaves_like 'missing before', 'until', '1until ""', '1 until ""' it_behaves_like 'missing after', 'until', '1 until""', '1 until ""' it_behaves_like 'missing before', 'when', 'case ""when a; end', 'case "" when a; end' it_behaves_like 'missing after', 'when', 'case a when""; end', 'case a when ""; end' it_behaves_like 'missing before', 'while', '1while ""', '1 while ""' it_behaves_like 'missing after', 'while', '1 while""', '1 while ""' it_behaves_like 'missing after', 'yield', 'yield""', 'yield ""' it_behaves_like 'accept after', '(', 'yield(1)' it_behaves_like 'accept after', '+', '+begin end' it_behaves_like 'missing after', 'begin', 'begin+1 end', 'begin +1 end' # Common exceptions it_behaves_like 'accept after', '\\', "test do\\\nend" it_behaves_like 'accept after', '\n', "test do\nend" it_behaves_like 'accept around', '()', '(next)' it_behaves_like 'accept before', '!', '!yield' it_behaves_like 'accept after', '.', 'yield.method' it_behaves_like 'accept before', '!', '!yield.method' it_behaves_like 'accept before', '!', '!super.method' context '&.', :ruby23 do it_behaves_like 'accept after', '&.', 'super&.foo' it_behaves_like 'accept after', '&.', 'yield&.foo' end it_behaves_like 'accept after', '[', 'super[1]' it_behaves_like 'accept after', '[', 'yield[1]' # Layout/SpaceAroundBlockParameters it_behaves_like 'accept before', '|', 'loop { |x|break }' # Layout/SpaceAroundOperators it_behaves_like 'accept before', '=', 'a=begin end' it_behaves_like 'accept before', '==', 'a==begin end' it_behaves_like 'accept before', '+', 'a+begin end' it_behaves_like 'accept before', '+', 'a+begin; end.method' it_behaves_like 'accept before', '-', 'a-begin end' it_behaves_like 'accept before', '*', 'a*begin end' it_behaves_like 'accept before', '**', 'a**begin end' it_behaves_like 'accept before', '/', 'a/begin end' it_behaves_like 'accept before', '<', 'a', 'a>begin end' it_behaves_like 'accept before', '&&', 'a&&begin end' it_behaves_like 'accept before', '||', 'a||begin end' it_behaves_like 'accept before', '=*', 'a=*begin end' # Layout/SpaceBeforeBlockBraces it_behaves_like 'accept after', '{', 'loop{}' # Layout/SpaceBeforeComma, Layout/SpaceAfterComma it_behaves_like 'accept around', ',', 'a 1,next,1' # Layout/SpaceBeforeComment it_behaves_like 'accept after', '#', 'next#comment' # Layout/SpaceBeforeSemicolon, Layout/SpaceAfterSemicolon it_behaves_like 'accept around', ';', 'test do;end' # Layout/SpaceInsideArrayLiteralBrackets it_behaves_like 'accept around', '[]', '[begin end]' # Layout/SpaceInsideBlockBraces it_behaves_like 'accept around', '{}', 'loop {next}' # Layout/SpaceInsideHashLiteralBraces it_behaves_like 'accept around', '{}', '{a: begin end}' # Layout/SpaceInsideReferenceBrackets it_behaves_like 'accept around', '[]', 'a[begin end]' # Layout/SpaceInsideStringInterpolation it_behaves_like 'accept around', '{}', '"#{begin end}"' end rubocop-0.52.1/spec/rubocop/cop/layout/space_around_operators_spec.rb000066400000000000000000000537041322072016200260550ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceAroundOperators do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config .new( 'Layout/AlignHash' => { 'EnforcedHashRocketStyle' => hash_style }, 'Layout/SpaceAroundOperators' => { 'AllowForAlignment' => allow_for_alignment } ) end let(:hash_style) { 'key' } let(:allow_for_alignment) { true } it 'accepts operator surrounded by tabs' do expect_no_offenses("a\t+\tb") end it 'accepts operator symbols' do expect_no_offenses('func(:-)') end it 'accepts ranges' do expect_no_offenses('a, b = (1..2), (1...3)') end it 'accepts scope operator' do expect_no_offenses('@io.class == Zlib::GzipWriter') end it 'accepts ::Kernel::raise' do expect_no_offenses('::Kernel::raise IllegalBlockError.new') end it 'accepts exclamation point negation' do expect_offense(<<-RUBY.strip_indent) x = !a&&!b ^^ Surrounding space missing for operator `&&`. RUBY end it 'accepts exclamation point definition' do expect_no_offenses(<<-RUBY.strip_indent) def ! !__getobj__ end RUBY end it 'accepts a unary' do expect_no_offenses(<<-RUBY.strip_indent) def bm(label_width = 0, *labels, &blk) benchmark(CAPTION, label_width, FORMAT, *labels, &blk) end def each &block +11 end def self.search *args end def each *args end RUBY end it 'accepts splat operator' do expect_no_offenses('return *list if options') end it 'accepts def of operator' do expect_no_offenses(<<-RUBY.strip_indent) def +(other); end def self.===(other); end RUBY end it 'accepts an operator at the end of a line' do expect_no_offenses(<<-RUBY.strip_indent) ['Favor unless over if for negative ' + 'conditions.'] * 2 RUBY end it 'accepts an assignment with spaces' do expect_no_offenses('x = 0') end it 'accepts an assignment by `for` statement' do expect_no_offenses(<<-RUBY.strip_indent) for a in [] do; end for A in [] do; end for @a in [] do; end for @@a in [] do; end RUBY end it 'accepts an operator called with method syntax' do expect_no_offenses('Date.today.+(1).to_s') end it 'accepts operators with spaces' do expect_no_offenses(<<-RUBY.strip_indent) x += a + b - c * d / e % f ^ g | h & i || j y -= k && l RUBY end it "accepts some operators that are exceptions & don't need spaces" do expect_no_offenses(<<-RUBY.strip_indent) (1..3) ActionController::Base each { |s, t| } RUBY end it 'accepts an assignment followed by newline' do expect_no_offenses(<<-RUBY.strip_indent) x = 0 RUBY end it 'accepts an operator at the beginning of a line' do expect_no_offenses(<<-'RUBY'.strip_indent) a = b \ && c RUBY end it 'registers an offenses for exponent operator with spaces' do expect_offense(<<-RUBY.strip_indent) x = a * b ** 2 ^^ Space around operator `**` detected. RUBY end it 'auto-corrects unwanted space around **' do new_source = autocorrect_source(<<-RUBY.strip_indent) x = a * b ** 2 y = a * b** 2 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) x = a * b**2 y = a * b**2 RUBY end it 'accepts exponent operator without spaces' do expect_no_offenses('x = a * b**2') end it 'accepts unary operators without space' do expect_no_offenses(<<-RUBY.strip_indent) [].map(&:size) a.(b) -3 arr.collect { |e| -e } x = +2 RUBY end it 'accepts [arg] without space' do expect_no_offenses('files[2]') end it 'accepts [] without space' do expect_no_offenses('files[]') end it 'accepts []= without space' do expect_no_offenses('files[:key], files[:another] = method') end it 'accepts argument default values without space' do # These are handled by SpaceAroundEqualsInParameterDefault, # so SpaceAroundOperators leaves them alone. expect_no_offenses(<<-RUBY.strip_indent) def init(name=nil) end RUBY end it 'accepts the construct class <2, a: b }') } context 'and Layout/AlignHash:EnforcedHashRocketStyle is key' do let(:hash_style) { 'key' } it 'registers an offense for a hash rocket without spaces' do expect(cop.messages) .to eq(['Surrounding space missing for operator `=>`.']) end end context 'and Layout/AlignHash:EnforcedHashRocketStyle is table' do let(:hash_style) { 'table' } it 'registers an offense for a hash rocket without spaces' do expect(cop.messages) .to eq(['Surrounding space missing for operator `=>`.']) end end end context 'when a hash literal is on multiple lines' do before do inspect_source(<<-RUBY.strip_indent) { 1=>2, a: b } RUBY end context 'and Layout/AlignHash:EnforcedHashRocketStyle is key' do let(:hash_style) { 'key' } it 'registers an offense for a hash rocket without spaces' do expect(cop.messages) .to eq(['Surrounding space missing for operator `=>`.']) end end context 'and Layout/AlignHash:EnforcedHashRocketStyle is table' do let(:hash_style) { 'table' } it "doesn't register an offense for a hash rocket without spaces" do expect_no_offenses(<<-RUBY.strip_indent) { 1=>2, a: b } RUBY end end end it 'registers an offense for match operators without space' do expect_offense(<<-RUBY.strip_indent) x=~/abc/ ^^ Surrounding space missing for operator `=~`. y !~/abc/ ^^ Surrounding space missing for operator `!~`. RUBY end it 'registers an offense for various assignments without space' do expect_offense(<<-RUBY.strip_indent) x||=0 ^^^ Surrounding space missing for operator `||=`. y&&=0 ^^^ Surrounding space missing for operator `&&=`. z*=2 ^^ Surrounding space missing for operator `*=`. @a=0 ^ Surrounding space missing for operator `=`. @@a=0 ^ Surrounding space missing for operator `=`. a,b=0 ^ Surrounding space missing for operator `=`. A=0 ^ Surrounding space missing for operator `=`. x[3]=0 ^ Surrounding space missing for operator `=`. $A=0 ^ Surrounding space missing for operator `=`. A||=0 ^^^ Surrounding space missing for operator `||=`. RUBY end it 'registers an offense for equality operators without space' do expect_offense(<<-RUBY.strip_indent) x==0 ^^ Surrounding space missing for operator `==`. y!=0 ^^ Surrounding space missing for operator `!=`. Hash===z ^^^ Surrounding space missing for operator `===`. RUBY end it 'registers an offense for - without space with negative lhs operand' do expect_offense(<<-RUBY.strip_indent) -1-arg ^ Surrounding space missing for operator `-`. RUBY end it 'registers an offense for inheritance < without space' do expect_offense(<<-RUBY.strip_indent) class ShowSourceTestClasse ^^ Surrounding space missing for operator `=>`. end RUBY end it "doesn't eat a newline when auto-correcting" do new_source = autocorrect_source(<<-RUBY.strip_indent) 'Here is a'+ 'joined string'+ 'across three lines' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) 'Here is a' + 'joined string' + 'across three lines' RUBY end it "doesn't register an offense for operators with newline on right" do expect_no_offenses(<<-RUBY.strip_indent) 'Here is a' + 'joined string' + 'across three lines' RUBY end end describe 'extra space around operators' do shared_examples 'modifier with extra space' do |keyword| it "registers an offense in presence of modifier #{keyword} statement" do src = <<-RUBY.strip_indent a = 1 #{keyword} condition c = 2 RUBY inspect_source(src) expect(cop.offenses.map(&:line)).to eq([1, 2]) expect(cop.messages).to eq( ['Operator `=` should be surrounded by a single space.'] * 2 ) new_source = autocorrect_source(src) expect(new_source).to eq(<<-RUBY.strip_indent) a = 1 #{keyword} condition c = 2 RUBY end end it 'registers an offense for assignment with many spaces on either side' do expect_offense(<<-RUBY.strip_indent) x = 0 ^ Operator `=` should be surrounded by a single space. y += 0 ^^ Operator `+=` should be surrounded by a single space. z[0] = 0 ^ Operator `=` should be surrounded by a single space. RUBY end it 'auto-corrects assignment with too many spaces on either side' do new_source = autocorrect_source(<<-RUBY.strip_indent) x = 0 y = 0 z = 0 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) x = 0 y = 0 z = 0 RUBY end it 'registers an offense for ternary operator with too many spaces' do expect_offense(<<-RUBY.strip_indent) x == 0 ? 1 : 2 ^ Operator `:` should be surrounded by a single space. ^ Operator `?` should be surrounded by a single space. RUBY end it 'auto-corrects a ternary operator too many spaces' do new_source = autocorrect_source('x == 0 ? 1 : 2') expect(new_source).to eq('x == 0 ? 1 : 2') end it_behaves_like 'modifier with extra space', 'if' it_behaves_like 'modifier with extra space', 'unless' it_behaves_like 'modifier with extra space', 'while' it_behaves_like 'modifier with extra space', 'until' it 'registers an offense for binary operators that could be unary' do expect_offense(<<-RUBY.strip_indent) a - 3 ^ Operator `-` should be surrounded by a single space. x & 0xff ^ Operator `&` should be surrounded by a single space. z + 0 ^ Operator `+` should be surrounded by a single space. RUBY end it 'auto-corrects missing space in binary operators that could be unary' do new_source = autocorrect_source(<<-RUBY.strip_indent) a - 3 x & 0xff z + 0 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a - 3 x & 0xff z + 0 RUBY end it 'registers an offense for arguments to a method' do expect_offense(<<-RUBY.strip_indent) puts 1 + 2 ^ Operator `+` should be surrounded by a single space. RUBY end it 'auto-corrects missing space in arguments to a method' do new_source = autocorrect_source('puts 1 + 2') expect(new_source).to eq('puts 1 + 2') end it 'registers an offense for operators with too many spaces' do expect_offense(<<-RUBY.strip_indent) x += a ^^ Operator `+=` should be surrounded by a single space. a + b ^ Operator `+` should be surrounded by a single space. b - c ^ Operator `-` should be surrounded by a single space. c * d ^ Operator `*` should be surrounded by a single space. d / e ^ Operator `/` should be surrounded by a single space. e % f ^ Operator `%` should be surrounded by a single space. f ^ g ^ Operator `^` should be surrounded by a single space. g | h ^ Operator `|` should be surrounded by a single space. h & i ^ Operator `&` should be surrounded by a single space. i || j ^^ Operator `||` should be surrounded by a single space. y -= k && l ^^ Operator `-=` should be surrounded by a single space. ^^ Operator `&&` should be surrounded by a single space. RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source( <<-RUBY.strip_indent x += a + b - c * d / e % f ^ g | h & i || j y -= k && l RUBY ) expect(new_source).to eq(<<-RUBY.strip_indent) x += a + b - c * d / e % f ^ g | h & i || j y -= k && l RUBY end it 'registers an offense for a setter call with too many spaces' do expect_offense(<<-RUBY.strip_indent) x.y = 2 ^ Operator `=` should be surrounded by a single space. RUBY end it 'registers an offense for a hash rocket with too many spaces' do expect_offense(<<-RUBY.strip_indent) { 1 => 2, a: b } ^^ Operator `=>` should be surrounded by a single space. RUBY end it 'registers an offense for a hash rocket with an extra space' \ 'on multiple line' do inspect_source(<<-RUBY.strip_indent) { 1 => 2 } RUBY expect(cop.messages).to eq( ['Operator `=>` should be surrounded by a single space.'] ) end it 'accepts for a hash rocket with an extra space for alignment' \ 'on multiple line' do inspect_source(<<-RUBY.strip_indent) { 1 => 2, 11 => 3 } RUBY expect(cop.offenses.empty?).to be(true) end context 'when does not allowed for alignment' do let(:allow_for_alignment) { false } it 'accepts an extra space' do expect_offense(<<-RUBY.strip_indent) { 1 => 2, ^^ Operator `=>` should be surrounded by a single space. 11 => 3 } RUBY end end it 'registers an offense for match operators with too many spaces' do expect_offense(<<-RUBY.strip_indent) x =~ /abc/ ^^ Operator `=~` should be surrounded by a single space. y !~ /abc/ ^^ Operator `!~` should be surrounded by a single space. RUBY end it 'registers an offense for various assignments with too many spaces' do expect_offense(<<-RUBY.strip_indent) x ||= 0 ^^^ Operator `||=` should be surrounded by a single space. y &&= 0 ^^^ Operator `&&=` should be surrounded by a single space. z *= 2 ^^ Operator `*=` should be surrounded by a single space. @a = 0 ^ Operator `=` should be surrounded by a single space. @@a = 0 ^ Operator `=` should be surrounded by a single space. a,b = 0 ^ Operator `=` should be surrounded by a single space. A = 0 ^ Operator `=` should be surrounded by a single space. x[3] = 0 ^ Operator `=` should be surrounded by a single space. $A = 0 ^ Operator `=` should be surrounded by a single space. A ||= 0 ^^^ Operator `||=` should be surrounded by a single space. A += 0 ^^ Operator `+=` should be surrounded by a single space. RUBY end it 'registers an offense for equality operators with too many spaces' do expect_offense(<<-RUBY.strip_indent) x == 0 ^^ Operator `==` should be surrounded by a single space. y != 0 ^^ Operator `!=` should be surrounded by a single space. Hash === z ^^^ Operator `===` should be surrounded by a single space. RUBY end it 'registers an offense for - with too many spaces with ' \ 'negative lhs operand' do inspect_source('-1 - arg') expect(cop.messages) .to eq(['Operator `-` should be surrounded by a single space.']) end it 'registers an offense for inheritance < with too many spaces' do expect_offense(<<-RUBY.strip_indent) class Foo < Bar ^ Operator `<` should be surrounded by a single space. end RUBY end it 'registers an offense for hash rocket with too many spaces at rescue' do expect_offense(<<-RUBY.strip_indent) begin rescue Exception => e ^^ Operator `=>` should be surrounded by a single space. end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_before_block_braces_spec.rb000066400000000000000000000100251322072016200264070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceBeforeBlockBraces, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'space' } } context 'when EnforcedStyle is space' do it 'accepts braces surrounded by spaces' do expect_no_offenses('each { puts }') end it 'registers an offense for left brace without outer space' do inspect_source('each{ puts }') expect(cop.messages).to eq(['Space missing to the left of {.']) expect(cop.highlights).to eq(['{']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space') end it 'registers an offense for opposite + correct style' do inspect_source(<<-RUBY.strip_indent) each{ puts } each { puts } RUBY expect(cop.messages).to eq(['Space missing to the left of {.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for multiline block where left brace has no ' \ 'outer space' do inspect_source(<<-RUBY.strip_indent) foo.map{ |a| a.bar.to_s } RUBY expect(cop.messages).to eq(['Space missing to the left of {.']) expect(cop.highlights).to eq(['{']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space') end it 'auto-corrects missing space' do new_source = autocorrect_source('each{ puts }') expect(new_source).to eq('each { puts }') end end context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } it 'registers an offense for braces surrounded by spaces' do inspect_source('each { puts }') expect(cop.messages).to eq(['Space detected to the left of {.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space') end it 'registers an offense for correct + opposite style' do inspect_source(<<-RUBY.strip_indent) each{ puts } each { puts } RUBY expect(cop.messages).to eq(['Space detected to the left of {.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts left brace without outer space' do expect_no_offenses('each{ puts }') end end context 'with space before empty braces not allowed' do let(:cop_config) do { 'EnforcedStyle' => 'space', 'EnforcedStyleForEmptyBraces' => 'no_space' } end it 'accepts empty braces without outer space' do expect_no_offenses('->{}') end it 'registers an offense for empty braces' do inspect_source('-> {}') expect(cop.messages).to eq(['Space detected to the left of {.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyleForEmptyBraces' => 'space') end it 'auto-corrects unwanted space' do new_source = autocorrect_source('-> {}') expect(new_source).to eq('->{}') end end context 'with space before empty braces allowed' do let(:cop_config) do { 'EnforcedStyle' => 'no_space', 'EnforcedStyleForEmptyBraces' => 'space' } end it 'accepts empty braces with outer space' do expect_no_offenses('-> {}') end it 'registers an offense for empty braces' do inspect_source('->{}') expect(cop.messages).to eq(['Space missing to the left of {.']) expect(cop.highlights).to eq(['{']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyleForEmptyBraces' => 'no_space') end it 'auto-corrects missing space' do new_source = autocorrect_source('->{}') expect(new_source).to eq('-> {}') end end context 'with invalid value for EnforcedStyleForEmptyBraces' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'unknown' } } it 'fails with an error' do expect { inspect_source('each {}') } .to raise_error('Unknown EnforcedStyleForEmptyBraces selected!') end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_before_comma_spec.rb000066400000000000000000000022751322072016200251020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceBeforeComma do subject(:cop) { described_class.new } it 'registers an offense for block argument with space before comma' do expect_offense(<<-RUBY.strip_indent) each { |s , t| } ^ Space found before comma. RUBY end it 'registers an offense for array index with space before comma' do expect_offense(<<-RUBY.strip_indent) formats[0 , 1] ^ Space found before comma. RUBY end it 'registers an offense for method call arg with space before comma' do expect_offense(<<-RUBY.strip_indent) a(1 , 2) ^ Space found before comma. RUBY end it 'does not register an offense for no spaces before comma' do expect_no_offenses('a(1, 2)') end it 'auto-corrects space before comma' do new_source = autocorrect_source('each { |s , t| a(1 , formats[0 , 1])}') expect(new_source).to eq('each { |s, t| a(1, formats[0, 1])}') end it 'handles more than one space before a comma' do new_source = autocorrect_source('each { |s , t| a(1 , formats[0 , 1])}') expect(new_source).to eq('each { |s, t| a(1, formats[0, 1])}') end end rubocop-0.52.1/spec/rubocop/cop/layout/space_before_comment_spec.rb000066400000000000000000000015071322072016200254450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceBeforeComment do subject(:cop) { described_class.new } it 'registers an offense for missing space before an EOL comment' do expect_offense(<<-RUBY.strip_indent) a += 1# increment ^^^^^^^^^^^ Put a space before an end-of-line comment. RUBY end it 'accepts an EOL comment with a preceding space' do expect_no_offenses('a += 1 # increment') end it 'accepts a comment that begins a line' do expect_no_offenses('# comment') end it 'accepts a doc comment' do expect_no_offenses(<<-RUBY.strip_indent) =begin Doc comment =end RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source('a += 1# increment') expect(new_source).to eq('a += 1 # increment') end end rubocop-0.52.1/spec/rubocop/cop/layout/space_before_first_arg_spec.rb000066400000000000000000000075261322072016200257720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceBeforeFirstArg, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowForAlignment' => true } } context 'for method calls without parentheses' do it 'registers an offense for method call with two spaces before the ' \ 'first arg' do inspect_source(<<-RUBY.strip_indent) something x a.something y, z RUBY expect(cop.messages) .to eq(['Put one space between the method name and the first ' \ 'argument.'] * 2) expect(cop.highlights).to eq([' ', ' ']) end it 'auto-corrects extra space' do new_source = autocorrect_source(<<-RUBY.strip_indent) something x a.something y, z RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something x a.something y, z RUBY end it 'registers an offense for method call with no spaces before the '\ 'first arg' do inspect_source(<<-RUBY.strip_indent) something'hello' a.something'hello world' RUBY expect(cop.messages) .to eq(['Put one space between the method name and the first ' \ 'argument.'] * 2) end it 'auto-corrects missing space' do new_source = autocorrect_source(<<-RUBY.strip_indent) something'hello' a.something'hello world' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) something 'hello' a.something 'hello world' RUBY end it 'accepts a method call with one space before the first arg' do expect_no_offenses(<<-RUBY.strip_indent) something x a.something y, z RUBY end it 'accepts + operator' do expect_no_offenses(<<-RUBY.strip_indent) something + x RUBY end it 'accepts setter call' do expect_no_offenses(<<-RUBY.strip_indent) something.x = y RUBY end it 'accepts multiple space containing line break' do expect_no_offenses(<<-RUBY.strip_indent) something \\ x RUBY end context 'when AllowForAlignment is true' do it 'accepts method calls with aligned first arguments' do expect_no_offenses(<<-RUBY.strip_indent) form.inline_input :full_name, as: :string form.disabled_input :password, as: :passwd form.masked_input :zip_code, as: :string form.masked_input :email_address, as: :email form.masked_input :phone_number, as: :tel RUBY end end context 'when AllowForAlignment is false' do let(:cop_config) { { 'AllowForAlignment' => false } } it 'does not accept method calls with aligned first arguments' do expect_offense(<<-RUBY.strip_indent) form.inline_input :full_name, as: :string ^^^ Put one space between the method name and the first argument. form.disabled_input :password, as: :passwd form.masked_input :zip_code, as: :string ^^^ Put one space between the method name and the first argument. form.masked_input :email_address, as: :email ^^^ Put one space between the method name and the first argument. form.masked_input :phone_number, as: :tel ^^^ Put one space between the method name and the first argument. RUBY end end end context 'for method calls with parentheses' do it 'accepts a method call without space' do expect_no_offenses(<<-RUBY.strip_indent) something(x) a.something(y, z) RUBY end it 'accepts a method call with space after the left parenthesis' do expect_no_offenses('something( x )') end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_before_semicolon_spec.rb000066400000000000000000000036011322072016200257700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceBeforeSemicolon do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/SpaceInsideBlockBraces' => brace_config) end let(:brace_config) { {} } it 'registers an offense for space before semicolon' do expect_offense(<<-RUBY.strip_indent) x = 1 ; y = 2 ^ Space found before semicolon. RUBY end it 'does not register an offense for no space before semicolons' do expect_no_offenses('x = 1; y = 2') end it 'auto-corrects space before semicolon' do new_source = autocorrect_source('x = 1 ; y = 2') expect(new_source).to eq('x = 1; y = 2') end it 'handles more than one space before a semicolon' do new_source = autocorrect_source('x = 1 ; y = 2') expect(new_source).to eq('x = 1; y = 2') end context 'inside block braces' do shared_examples 'common behavior' do it 'accepts no space between an opening brace and a semicolon' do inspect_source('test {; }') expect(cop.messages.empty?).to be(true) end end context 'when EnforcedStyle for SpaceInsideBlockBraces is space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'space' } end it_behaves_like 'common behavior' it 'accepts a space between an opening brace and a semicolon' do expect_no_offenses('test { ; }') end end context 'when EnforcedStyle for SpaceInsideBlockBraces is no_space' do let(:brace_config) do { 'Enabled' => true, 'EnforcedStyle' => 'no_space' } end it_behaves_like 'common behavior' it 'registers an offense for a space between an opening brace and a ' \ 'semicolon' do inspect_source('test { ; }') expect(cop.messages).to eq(['Space found before semicolon.']) end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_in_lambda_literal_spec.rb000066400000000000000000000137111322072016200261030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInLambdaLiteral, :config do subject(:cop) { described_class.new(config) } context 'when configured to enforce spaces' do let(:cop_config) { { 'EnforcedStyle' => 'require_space' } } it 'registers an offense for no space between -> and (' do expect_offense(<<-RUBY.strip_indent) a = ->(b, c) { b + c } ^^^^^^^^^^^^^^^^^^ Use a space between `->` and opening brace in lambda literals RUBY end it 'does not register an offense for a space between -> and (' do expect_no_offenses('a = -> (b, c) { b + c }') end it 'does not register an offense for multi-line lambdas' do expect_no_offenses(<<-RUBY.strip_indent) l = lambda do |a, b| tmp = a * 7 tmp * b / 50 end RUBY end it 'does not register an offense for no space between -> and {' do expect_no_offenses('a = ->{ b + c }') end it 'registers an offense for no space in the inner nested lambda' do expect_offense(<<-RUBY.strip_indent) a = -> (b = ->(c) {}, d) { b + d } ^^^^^^^^ Use a space between `->` and opening brace in lambda literals RUBY end it 'registers an offense for no space in the outer nested lambda' do expect_offense(<<-RUBY.strip_indent) a = ->(b = -> (c) {}, d) { b + d } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a space between `->` and opening brace in lambda literals RUBY end it 'registers an offense for no space in both lambdas when nested' do expect_offense(<<-RUBY.strip_indent) a = ->(b = ->(c) {}, d) { b + d } ^^^^^^^^ Use a space between `->` and opening brace in lambda literals ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use a space between `->` and opening brace in lambda literals RUBY end it 'autocorrects an offense for no space between -> and (' do code = 'a = ->(b, c) { b + c }' expected = 'a = -> (b, c) { b + c }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for no space in the inner nested lambda' do code = 'a = -> (b = ->(c) {}, d) { b + d }' expected = 'a = -> (b = -> (c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for no space in the outer nested lambda' do code = 'a = ->(b = -> (c) {}, d) { b + d }' expected = 'a = -> (b = -> (c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for no space in both lambdas when nested' do code = 'a = ->(b = ->(c) {}, d) { b + d }' expected = 'a = -> (b = -> (c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end end context 'when configured to enforce no space' do let(:cop_config) { { 'EnforcedStyle' => 'require_no_space' } } it 'registers an offense for a space between -> and (' do expect_offense(<<-RUBY.strip_indent) a = -> (b, c) { b + c } ^^^^^^^^^^^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals RUBY end it 'does not register an offense for no space between -> and (' do expect_no_offenses('a = ->(b, c) { b + c }') end it 'does not register an offense for multi-line lambdas' do expect_no_offenses(<<-RUBY.strip_indent) l = lambda do |a, b| tmp = a * 7 tmp * b / 50 end RUBY end it 'does not register an offense for a space between -> and {' do expect_no_offenses('a = -> { b + c }') end it 'registers an offense for spaces between -> and (' do expect_offense(<<-RUBY.strip_indent) a = -> (b, c) { b + c } ^^^^^^^^^^^^^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals RUBY end it 'registers an offense for a space in the inner nested lambda' do expect_offense(<<-RUBY.strip_indent) a = ->(b = -> (c) {}, d) { b + d } ^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals RUBY end it 'registers an offense for a space in the outer nested lambda' do expect_offense(<<-RUBY.strip_indent) a = -> (b = ->(c) {}, d) { b + d } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals RUBY end it 'registers two offenses for a space in both lambdas when nested' do expect_offense(<<-RUBY.strip_indent) a = -> (b = -> (c) {}, d) { b + d } ^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use spaces between `->` and opening brace in lambda literals RUBY end it 'autocorrects an offense for a space between -> and (' do code = 'a = -> (b, c) { b + c }' expected = 'a = ->(b, c) { b + c }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for spaces between -> and (' do code = 'a = -> (b, c) { b + c }' expected = 'a = ->(b, c) { b + c }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for a space in the inner nested lambda' do code = 'a = ->(b = -> (c) {}, d) { b + d }' expected = 'a = ->(b = ->(c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects an offense for a space in the outer nested lambda' do code = 'a = -> (b = ->(c) {}, d) { b + d }' expected = 'a = ->(b = ->(c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end it 'autocorrects two offenses for a space in both lambdas when nested' do code = 'a = -> (b = -> (c) {}, d) { b + d }' expected = 'a = ->(b = ->(c) {}, d) { b + d }' expect(autocorrect_source(code)).to eq(expected) end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_array_literal_brackets_spec.rb000066400000000000000000000351771322072016200305360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideArrayLiteralBrackets, :config do subject(:cop) { described_class.new(config) } it 'does not register offense for any kind of reference brackets' do expect_no_offenses(<<-RUBY.strip_indent) a[1] b[ 3] c[ foo ] d[index, 2] RUBY end context 'with space inside empty brackets not allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBrackets' => 'no_space' } } it 'accepts empty brackets with no space inside' do expect_no_offenses('a = []') end it 'registers an offense for empty brackets with one space inside' do expect_offense(<<-RUBY.strip_indent) a = [ ] ^^^ Do not use space inside empty array brackets. RUBY end it 'registers an offense for empty brackets with lots of space inside' do expect_offense(<<-RUBY.strip_indent) a = [ ] ^^^^^^^ Do not use space inside empty array brackets. RUBY end it 'auto-corrects an unwanted single space' do new_source = autocorrect_source('a = [ ]') expect(new_source).to eq('a = []') end it 'auto-corrects multiple unwanted spaces' do new_source = autocorrect_source('a = [ ]') expect(new_source).to eq('a = []') end end context 'with space inside empty braces allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBrackets' => 'space' } } it 'accepts empty brackets with space inside' do expect_no_offenses('a = [ ]') end it 'registers offense for empty brackets with no space inside' do expect_offense(<<-RUBY.strip_indent) a = [] ^^ Use one space inside empty array brackets. RUBY end it 'registers offense for empty brackets with more than one space inside' do expect_offense(<<-RUBY.strip_indent) a = [ ] ^^^^^^^^ Use one space inside empty array brackets. RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source('a = []') expect(new_source).to eq('a = [ ]') end it 'auto-corrects too many spaces' do new_source = autocorrect_source('a = [ ]') expect(new_source).to eq('a = [ ]') end end context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } it 'does not register offense for arrays with no spaces' do expect_no_offenses(<<-RUBY.strip_indent) [1, 2, 3] [foo, bar] ["qux", "baz"] [[1, 2], [3, 4]] [{ foo: 1 }, { bar: 2}] RUBY end it 'does not register offense for arrays using ref brackets' do expect_no_offenses(<<-RUBY.strip_indent) [1, 2, 3][0] [foo, bar][ 1] ["qux", "baz"][ -1 ] [[1, 2], [3, 4]][1 ] [{ foo: 1 }, { bar: 2}][0] RUBY end it 'does not register offense when 2 arrays on one line' do expect_no_offenses(<<-RUBY.strip_indent) [2,3,4] + [5,6,7] RUBY end it 'does not register offense for array when brackets get own line' do expect_no_offenses(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY end it 'does not register offense for indented array ' \ 'when bottom bracket gets its own line & is misaligned' do expect_no_offenses(<<-RUBY.strip_indent) def do_stuff a = [ 1, 2 ] end RUBY end it 'does not register offense when bottom bracket gets its ' \ 'own line & has trailing method' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1, 2, nil ].compact RUBY end it 'does not register offense for valid multiline array' do expect_no_offenses(<<-RUBY.strip_indent) ['Encoding:', ' Enabled: false'] RUBY end it 'does not register offense for valid 2-dimensional array' do expect_no_offenses(<<-RUBY.strip_indent) [1, [2,3,4], [5,6,7]] RUBY end it 'accepts space inside array brackets if with comment' do expect_no_offenses(<<-RUBY.strip_indent) a = [ # Comment 1, 2 ] RUBY end it 'accepts square brackets as method name' do expect_no_offenses(<<-RUBY.strip_indent) def Vector.[](*array) end RUBY end it 'accepts square brackets called with method call syntax' do expect_no_offenses('subject.[](0)') end it 'registers offense in array brackets with leading whitespace' do expect_offense(<<-RUBY.strip_indent) [ 2, 3, 4] ^ Do not use space inside array brackets. RUBY end it 'registers offense in array brackets with trailing whitespace' do expect_offense(<<-RUBY.strip_indent) [b, c, d ] ^^^ Do not use space inside array brackets. RUBY end it 'registers offense in correct array when two on one line' do expect_offense(<<-RUBY.strip_indent) ['qux', 'baz' ] - ['baz'] ^^ Do not use space inside array brackets. RUBY end it 'registers offense in multiline array on end bracket' do expect_offense(<<-RUBY.strip_indent) ['ok', 'still good', 'not good' ] ^ Do not use space inside array brackets. RUBY end it 'registers offense in multiline array on end bracket' \ 'with trailing method' do expect_offense(<<-RUBY.strip_indent) [:good, :bad ].compact ^^ Do not use space inside array brackets. RUBY end it 'register offense when 2 arrays on one line' do expect_offense(<<-RUBY.strip_indent) [2,3,4] - [ 3,4] ^ Do not use space inside array brackets. RUBY end context 'auto-corrects' do it 'fixes multiple offenses in one set of array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ 89, 90, 91 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [89, 90, 91] RUBY end it 'fixes multiple offenses in two sets of array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ 89, 90, 91] + [ 1, 7, 9] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [89, 90, 91] + [1, 7, 9] RUBY end it 'fixes multiline offenses but does not fuss with alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ :foo, :bar, nil ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [:foo, :bar, nil] RUBY end it 'fixes multiline offenses with trailing method' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ a, b, c ].compact RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [a, b, c].compact RUBY end it 'ignores multiline array with whitespace before end bracket' do new_source = autocorrect_source(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY end end end shared_examples 'space inside arrays' do it 'does not register offense for arrays with spaces' do expect_no_offenses(<<-RUBY.strip_indent) [ 1, 2, 3 ] [ foo, bar ] [ "qux", "baz" ] [ { foo: 1 }, { bar: 2} ] RUBY end it 'does not register offense for arrays using ref brackets' do expect_no_offenses(<<-RUBY.strip_indent) [ 1, 2, 3 ][0] [ foo, bar ][ 1] [ "qux", "baz" ][ -1 ] [ { foo: 1 }, { bar: 2} ][0] RUBY end it 'does not register offense when 2 arrays on one line' do expect_no_offenses(<<-RUBY.strip_indent) [ 2,3,4 ] + [ 5,6,7 ] RUBY end it 'does not register offense for array when brackets get their own line' do expect_no_offenses(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY end it 'does not register offense for indented array ' \ 'when bottom bracket gets its own line & is misaligned' do expect_no_offenses(<<-RUBY.strip_indent) def do_stuff a = [ 1, 2 ] end RUBY end it 'does not register offense when bottom bracket gets its ' \ 'own line & has trailing method' do expect_no_offenses(<<-RUBY.strip_indent) a = [ 1, 2, nil ].compact RUBY end it 'does not register offense for valid multiline array' do expect_no_offenses(<<-RUBY.strip_indent) [ 'Encoding:', 'Enabled: false' ] RUBY end it 'accepts space inside array brackets with comment' do expect_no_offenses(<<-RUBY.strip_indent) a = [ # Comment 1, 2 ] RUBY end it 'accepts square brackets as method name' do expect_no_offenses(<<-RUBY.strip_indent) def Vector.[](*array) end RUBY end it 'accepts square brackets called with method call syntax' do expect_no_offenses('subject.[](0)') end it 'registers offense in array brackets with no leading whitespace' do expect_offense(<<-RUBY.strip_indent) [2, 3, 4 ] ^ Use space inside array brackets. RUBY end it 'registers offense in array brackets with no trailing whitespace' do expect_offense(<<-RUBY.strip_indent) [ b, c, d] ^ Use space inside array brackets. RUBY end it 'registers offense in correct array when two on one line' do expect_offense(<<-RUBY.strip_indent) [ 'qux', 'baz'] - [ 'baz' ] ^ Use space inside array brackets. RUBY end it 'registers offense in multiline array on end bracket' do expect_offense(<<-RUBY.strip_indent) [ 'ok', 'still good', 'not good'] ^ Use space inside array brackets. RUBY end it 'registers offense in multiline array on end bracket' \ 'with trailing method' do expect_offense(<<-RUBY.strip_indent) [ :good, :bad].compact ^ Use space inside array brackets. RUBY end it 'register offense when 2 arrays on one line' do expect_offense(<<-RUBY.strip_indent) [ 2, 3, 4 ] - [3, 4 ] ^ Use space inside array brackets. RUBY end context 'auto-corrects' do it 'fixes multiple offenses in one set of array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) [89, 90, 91] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [ 89, 90, 91 ] RUBY end it 'fixes multiple offenses in two sets of array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ 89, 90, 91] + [ 1, 7, 9] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [ 89, 90, 91 ] + [ 1, 7, 9 ] RUBY end it 'fixes multiline offenses but does not fuss with alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) [:foo, :bar, nil] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [ :foo, :bar, nil ] RUBY end it 'fixes multiline offenses with trailing method' do new_source = autocorrect_source(<<-RUBY.strip_indent) [a, b, c].compact RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [ a, b, c ].compact RUBY end it 'ignores multiline array with no whitespace before end bracket' do new_source = autocorrect_source(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) stuff = [ a, b ] RUBY end end end context 'when EnforcedStyle is space' do let(:cop_config) { { 'EnforcedStyle' => 'space' } } it_behaves_like 'space inside arrays' it 'does not register offense for valid 2-dimensional array' do expect_no_offenses(<<-RUBY.strip_indent) [ 1, [ 2,3,4 ], [ 5,6,7 ] ] RUBY end end context 'when EnforcedStyle is compact' do let(:cop_config) { { 'EnforcedStyle' => 'compact' } } it_behaves_like 'space inside arrays' it 'does not register offense for valid 2-dimensional array' do expect_no_offenses(<<-RUBY.strip_indent) [ 1, [ 2,3,4 ], [ 5,6,7 ]] RUBY end it 'does not register offense for valid 3-dimensional array' do expect_no_offenses(<<-RUBY.strip_indent) [[ 2, 3, [ 4 ]]] RUBY end it 'does not register offense for valid 4-dimensional array' do expect_no_offenses(<<-RUBY.strip_indent) [[[[ boom ]]]] RUBY end it 'registers offense if space between 2 closing brackets' do expect_offense(<<-RUBY.strip_indent) [ 1, [ 2,3,4 ], [ 5,6,7 ] ] ^ Do not use space inside array brackets. RUBY end it 'registers offense if space between 2 opening brackets' do expect_offense(<<-RUBY.strip_indent) [ [ 2,3,4 ], [ 5,6,7 ], 8 ] ^ Do not use space inside array brackets. RUBY end context 'auto-corrects' do it 'fixes 2-dimensional array with extra spaces' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ [ a, b ], [ 1, 7 ] ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [[ a, b ], [ 1, 7 ]] RUBY end it 'fixes offensive 3-dimensional array' do new_source = autocorrect_source(<<-RUBY.strip_indent) [ [a, b ], [foo, [bar, baz] ] ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [[ a, b ], [ foo, [ bar, baz ]]] RUBY end it 'ignores multi-dimensional multiline array with no ' \ 'whitespace before end bracket' do new_source = autocorrect_source(<<-RUBY.strip_indent) stuff = [ a, [ b, c ] ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) stuff = [ a, [ b, c ] ] RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_array_percent_literal_spec.rb000066400000000000000000000053311322072016200303650ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideArrayPercentLiteral do subject(:cop) { described_class.new } let(:message) do 'Use only a single space inside array percent literal.' end %w[i I w W].each do |type| [%w[{ }], %w[( )], %w([ ]), %w[! !]].each do |(ldelim, rdelim)| context "for #{type} type and #{[ldelim, rdelim]} delimiters" do define_method(:code_example) do |content| ['%', type, ldelim, content, rdelim].join end def expect_corrected(source, expected) expect(autocorrect_source(source)).to eq expected end it 'registers an offense for unnecessary spaces' do source = code_example('1 2') inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq([' ']) expect(cop.messages).to eq([message]) expect_corrected(source, code_example('1 2')) end it 'registers an offense for multiple spaces between items' do source = code_example('1 2 3') inspect_source(source) expect(cop.offenses.size).to eq(2) expect_corrected(source, code_example('1 2 3')) end it 'accepts literals with escaped and additional spaces' do source = code_example('a\ b \ c') inspect_source(source) expect(cop.offenses.size).to eq(1) expect_corrected(source, code_example('a\ b \ c')) end it 'accepts literals without additional spaces' do inspect_source(code_example('a b c')) expect(cop.messages.empty?).to be(true) end it 'accepts literals with escaped spaces' do inspect_source(code_example('a\ b\ \ c')) expect(cop.messages.empty?).to be(true) end it 'accepts multi-line literals' do inspect_source(<<-RUBY.strip_indent) %#{type}( a b c ) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts multi-line literals within a method' do inspect_source(<<-RUBY.strip_indent) def foo %#{type}( a b c ) end RUBY expect(cop.messages.empty?).to be(true) end it 'accepts newlines and additional following alignment spaces' do inspect_source(<<-RUBY.strip_indent) %#{type}(a b c) RUBY expect(cop.messages.empty?).to be(true) end end end end it 'accepts non array percent literals' do expect_no_offenses('%q( a b c )') end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_block_braces_spec.rb000066400000000000000000000254561322072016200264360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideBlockBraces, :config do SUPPORTED_STYLES = %w[space no_space].freeze subject(:cop) { described_class.new(config) } let(:cop_config) do { 'EnforcedStyle' => 'space', 'SupportedStyles' => SUPPORTED_STYLES, 'SpaceBeforeBlockParameters' => true } end context 'with space inside empty braces not allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'no_space' } } it 'accepts empty braces with no space inside' do expect_no_offenses('each {}') end it 'accepts braces with something inside' do expect_no_offenses('each { "f" }') end it 'accepts multiline braces with content' do expect_no_offenses(<<-RUBY.strip_indent) each { %( ) } RUBY end it 'accepts empty braces with comment and line break inside' do expect_no_offenses(<<-RUBY.strip_indent) each { # Comment } RUBY end it 'registers an offense for empty braces with line break inside' do inspect_source(<<-RUBY.strip_margin('|')) | each { | } RUBY expect(cop.messages).to eq(['Space inside empty braces detected.']) expect(cop.highlights).to eq(["\n "]) end it 'registers an offense for empty braces with space inside' do expect_offense(<<-RUBY.strip_indent) each { } ^ Space inside empty braces detected. RUBY end it 'auto-corrects unwanted space' do new_source = autocorrect_source('each { }') expect(new_source).to eq('each {}') end it 'does not auto-correct when braces are not empty' do old_source = <<-RUBY a { b } RUBY new_source = autocorrect_source(old_source) expect(new_source).to eq(old_source) end end context 'with space inside empty braces allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'space' } } it 'accepts empty braces with space inside' do expect_no_offenses('each { }') end it 'registers an offense for empty braces with no space inside' do expect_offense(<<-RUBY.strip_indent) each {} ^^ Space missing inside empty braces. RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source('each {}') expect(new_source).to eq('each { }') end end context 'with invalid value for EnforcedStyleForEmptyBraces' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'unknown' } } it 'fails with an error' do expect { inspect_source('each { }') } .to raise_error('Unknown EnforcedStyleForEmptyBraces selected!') end end it 'accepts braces surrounded by spaces' do expect_no_offenses('each { puts }') end it 'accepts left brace without outer space' do expect_no_offenses('each{ puts }') end it 'registers an offense for left brace without inner space' do inspect_source('each {puts }') expect(cop.messages).to eq(['Space missing inside {.']) expect(cop.highlights).to eq(['p']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for right brace without inner space' do inspect_source('each { puts}') expect(cop.messages).to eq(['Space missing inside }.']) expect(cop.highlights).to eq(['}']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers offenses for both braces without inner space' do inspect_source(<<-RUBY.strip_indent) a {} b { } each {puts} RUBY expect(cop.messages).to eq(['Space inside empty braces detected.', 'Space missing inside {.', 'Space missing inside }.']) expect(cop.highlights).to eq([' ', 'p', '}']) # Both correct and incorrect code has been found in relation to # EnforcedStyleForEmptyBraces, but that doesn't matter. EnforcedStyle can # be changed to get rid of the EnforcedStyle offenses. expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space') end it 'auto-corrects missing space' do new_source = autocorrect_source('each {puts}') expect(new_source).to eq('each { puts }') end context 'with passed in parameters' do context 'for single-line blocks' do it 'accepts left brace with inner space' do expect_no_offenses('each { |x| puts }') end it 'registers an offense for left brace without inner space' do inspect_source('each {|x| puts }') expect(cop.messages).to eq(['Space between { and | missing.']) expect(cop.highlights).to eq(['{|']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'for multi-line blocks' do it 'accepts left brace with inner space' do expect_no_offenses(<<-RUBY.strip_indent) each { |x| puts } RUBY end it 'registers an offense for left brace without inner space' do inspect_source(<<-RUBY.strip_indent) each {|x| puts } RUBY expect(cop.messages).to eq(['Space between { and | missing.']) expect(cop.highlights).to eq(['{|']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects missing space' do new_source = autocorrect_source(<<-SOURCE) each {|x| puts } SOURCE expect(new_source).to eq(<<-NEW_SOURCE) each { |x| puts } NEW_SOURCE end end it 'accepts new lambda syntax' do expect_no_offenses('->(x) { x }') end it 'auto-corrects missing space' do new_source = autocorrect_source('each {|x| puts }') expect(new_source).to eq('each { |x| puts }') end context 'and BlockDelimiters cop enabled' do let(:config) do RuboCop::Config.new('Style/BlockDelimiters' => { 'Enabled' => true }, 'Layout/SpaceInsideBlockBraces' => cop_config) end it 'does auto-correction for single-line blocks' do new_source = autocorrect_source('each {|x| puts}') expect(new_source).to eq('each { |x| puts }') end it 'does auto-correction for multi-line blocks' do old_source = <<-RUBY.strip_indent each {|x| puts } RUBY new_source = autocorrect_source(old_source) expect(new_source).to eq(<<-RUBY.strip_indent) each { |x| puts } RUBY end end context 'and space before block parameters not allowed' do let(:cop_config) do { 'EnforcedStyle' => 'space', 'SupportedStyles' => SUPPORTED_STYLES, 'SpaceBeforeBlockParameters' => false } end it 'registers an offense for left brace with inner space' do inspect_source('each { |x| puts }') expect(cop.messages).to eq(['Space between { and | detected.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new lambda syntax' do expect_no_offenses('->(x) { x }') end it 'auto-corrects unwanted space' do new_source = autocorrect_source('each { |x| puts }') expect(new_source).to eq('each {|x| puts }') end it 'accepts left brace without inner space' do expect_no_offenses('each {|x| puts }') end end end context 'configured with no_space' do let(:cop_config) do { 'EnforcedStyle' => 'no_space', 'SupportedStyles' => SUPPORTED_STYLES, 'SpaceBeforeBlockParameters' => true } end it 'accepts braces without spaces inside' do expect_no_offenses('each {puts}') end it 'registers an offense for left brace with inner space' do inspect_source('each { puts}') expect(cop.messages).to eq(['Space inside { detected.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for right brace with inner space' do inspect_source('each {puts }') expect(cop.messages).to eq(['Space inside } detected.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers offenses for both braces with inner space' do inspect_source('each { puts }') expect(cop.messages).to eq(['Space inside { detected.', 'Space inside } detected.']) expect(cop.highlights).to eq([' ', ' ']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space') end it 'accepts left brace without outer space' do expect_no_offenses('each{puts}') end it 'auto-corrects unwanted space' do new_source = autocorrect_source('each{ puts }') expect(new_source).to eq('each{puts}') end context 'with passed in parameters' do context 'and space before block parameters allowed' do it 'accepts left brace with inner space' do expect_no_offenses('each { |x| puts}') end it 'registers an offense for left brace without inner space' do inspect_source('each {|x| puts}') expect(cop.messages).to eq(['Space between { and | missing.']) expect(cop.highlights).to eq(['{|']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new lambda syntax' do expect_no_offenses('->(x) {x}') end it 'auto-corrects missing space' do new_source = autocorrect_source('each {|x| puts}') expect(new_source).to eq('each { |x| puts}') end end context 'and space before block parameters not allowed' do let(:cop_config) do { 'EnforcedStyle' => 'no_space', 'SupportedStyles' => SUPPORTED_STYLES, 'SpaceBeforeBlockParameters' => false } end it 'registers an offense for left brace with inner space' do inspect_source('each { |x| puts}') expect(cop.messages).to eq(['Space between { and | detected.']) expect(cop.highlights).to eq([' ']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new lambda syntax' do expect_no_offenses('->(x) {x}') end it 'auto-corrects unwanted space' do new_source = autocorrect_source('each { |x| puts}') expect(new_source).to eq('each {|x| puts}') end end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_hash_literal_braces_spec.rb000066400000000000000000000153111322072016200277700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideHashLiteralBraces, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'space' } } context 'with space inside empty braces not allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'no_space' } } it 'accepts empty braces with no space inside' do expect_no_offenses('h = {}') end it 'registers an offense for empty braces with space inside' do expect_offense(<<-RUBY.strip_indent) h = { } ^ Space inside empty hash literal braces detected. RUBY end it 'auto-corrects unwanted space' do new_source = autocorrect_source('h = { }') expect(new_source).to eq('h = {}') end end context 'with space inside empty braces allowed' do let(:cop_config) { { 'EnforcedStyleForEmptyBraces' => 'space' } } it 'accepts empty braces with space inside' do expect_no_offenses('h = { }') end it 'registers an offense for empty braces with no space inside' do expect_offense(<<-RUBY.strip_indent) h = {} ^ Space inside empty hash literal braces missing. RUBY end it 'auto-corrects missing space' do new_source = autocorrect_source('h = {}') expect(new_source).to eq('h = { }') end end it 'registers an offense for hashes with no spaces if so configured' do inspect_source(<<-RUBY.strip_indent) h = {a: 1, b: 2} h = {a => 1} RUBY expect(cop.messages).to eq(['Space inside { missing.', 'Space inside } missing.', 'Space inside { missing.', 'Space inside } missing.']) expect(cop.highlights).to eq(['{', '}', '{', '}']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'no_space') end it 'registers an offense for correct + opposite' do inspect_source('h = { a: 1}') expect(cop.messages).to eq(['Space inside } missing.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects missing space' do new_source = autocorrect_source(<<-RUBY.strip_indent) h = {a: 1, b: 2} h = {a => 1 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) h = { a: 1, b: 2 } h = { a => 1 } RUBY end context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } it 'registers an offense for hashes with spaces' do inspect_source('h = { a: 1, b: 2 }') expect(cop.messages).to eq(['Space inside { detected.', 'Space inside } detected.']) expect(cop.highlights).to eq([' ', ' ']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'space') end it 'registers an offense for opposite + correct' do inspect_source('h = {a: 1 }') expect(cop.messages).to eq(['Space inside } detected.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects unwanted space' do new_source = autocorrect_source(<<-RUBY.strip_indent) h = { a: 1, b: 2 } h = {a => 1 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) h = {a: 1, b: 2} h = {a => 1} RUBY end it 'accepts hashes with no spaces' do expect_no_offenses(<<-RUBY.strip_indent) h = {a: 1, b: 2} h = {a => 1} RUBY end it 'accepts multiline hash' do expect_no_offenses(<<-RUBY.strip_indent) h = { a: 1, b: 2, } RUBY end it 'accepts multiline hash with comment' do expect_no_offenses(<<-RUBY.strip_indent) h = { # Comment a: 1, b: 2, } RUBY end end context 'when EnforcedStyle is compact' do let(:cop_config) { { 'EnforcedStyle' => 'compact' } } it "doesn't register an offense for non-nested hashes with spaces" do inspect_source('h = { a: 1, b: 2 }') expect(cop.offenses.empty?).to be(true) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'compact') end it 'registers an offense for nested hashes with spaces' do expect_offense(<<-RUBY.strip_indent) h = { a: { a: 1, b: 2 } } ^ Space inside } detected. RUBY end it 'registers an offense for opposite + correct' do inspect_source('h = {a: 1 }') expect(cop.messages).to eq(['Space inside { missing.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects hashes with no space' do new_source = autocorrect_source(<<-RUBY.strip_indent) h = {a: 1, b: 2} h = {a => 1 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) h = { a: 1, b: 2 } h = { a => 1 } RUBY end it 'auto-corrects nested hashes with spaces' do new_source = autocorrect_source(<<-RUBY.strip_indent) h = { a: { a: 1, b: 2 } } h = {a => method { 1 } } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) h = { a: { a: 1, b: 2 }} h = { a => method { 1 }} RUBY end it 'registers offenses for hashes with no spaces' do expect_offense(<<-RUBY.strip_indent) h = {a: 1, b: 2} ^ Space inside } missing. ^ Space inside { missing. h = {a => 1} ^ Space inside } missing. ^ Space inside { missing. RUBY end it 'accepts multiline hash' do expect_no_offenses(<<-RUBY.strip_indent) h = { a: 1, b: 2, } RUBY end it 'accepts multiline hash with comment' do expect_no_offenses(<<-RUBY.strip_indent) h = { # Comment a: 1, b: 2, } RUBY end end it 'accepts hashes with spaces by default' do expect_no_offenses(<<-RUBY.strip_indent) h = { a: 1, b: 2 } h = { a => 1 } RUBY end it 'accepts hash literals with no braces' do expect_no_offenses('x(a: b.c)') end it 'can handle interpolation in a braceless hash literal' do # A tricky special case where the closing brace of the # interpolation risks getting confused for a hash literal brace. expect_no_offenses('f(get: "#{x}")') end context 'on Hash[{ x: 1 } => [1]]' do # regression test; see GH issue 2436 it 'does not register an offense' do expect_no_offenses('Hash[{ x: 1 } => [1]]') end end context 'on { key: "{" }' do # regression test; see GH issue 3958 it 'does not register an offense' do expect_no_offenses('{ key: "{" }') end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_parens_spec.rb000066400000000000000000000021751322072016200253060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideParens do subject(:cop) { described_class.new } it 'registers an offense for spaces inside parens' do expect_offense(<<-RUBY.strip_indent) f( 3) ^ Space inside parentheses detected. g = (a + 3 ) ^ Space inside parentheses detected. RUBY end it 'accepts parentheses in block parameter list' do expect_no_offenses(<<-RUBY.strip_indent) list.inject(Tms.new) { |sum, (label, item)| } RUBY end it 'accepts parentheses with no spaces' do expect_no_offenses('split("\\n")') end it 'accepts parentheses with line break' do expect_no_offenses(<<-RUBY.strip_indent) f( 1) RUBY end it 'accepts parentheses with comment and line break' do expect_no_offenses(<<-RUBY.strip_indent) f( # Comment 1) RUBY end it 'auto-corrects unwanted space' do new_source = autocorrect_source(<<-RUBY.strip_indent) f( 3) g = ( a + 3 ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) f(3) g = (a + 3) RUBY end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_percent_literal_delimiters_spec.rb000066400000000000000000000064311322072016200314120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsidePercentLiteralDelimiters do subject(:cop) { described_class.new } let(:message) do 'Do not use spaces inside percent literal delimiters.' end %w[i I w W x].each do |type| [%w[{ }], %w[( )], %w([ ]), %w[! !]].each do |(ldelim, rdelim)| context "for #{type} type and #{[ldelim, rdelim]} delimiters" do define_method(:code_example) do |content| ['%', type, ldelim, content, rdelim].join end def expect_corrected(source, expected) expect(autocorrect_source(source)).to eq expected end it 'registers an offense for unnecessary spaces' do source = code_example(' 1 2 ') inspect_source(source) expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq).to eq([message]) expect(cop.highlights).to eq([' ', ' ']) expect_corrected(source, code_example('1 2')) end it 'registers an offense for spaces after first delimiter' do source = code_example(' 1 2') inspect_source(source) expect(cop.offenses.size).to eq(1) expect_corrected(source, code_example('1 2')) end it 'registers an offense for spaces before final delimiter' do source = code_example('1 2 ') inspect_source(source) expect(cop.offenses.size).to eq(1) expect_corrected(source, code_example('1 2')) end it 'registers an offense for literals with escaped and other spaces' do source = code_example(' \ a b c\ ') inspect_source(source) expect(cop.offenses.size).to eq(2) expect_corrected(source, code_example('\ a b c\ ')) end it 'accepts literals without additional spaces' do inspect_source(code_example('a b c')) expect(cop.messages.empty?).to be(true) end it 'accepts literals with escaped spaces' do inspect_source(code_example('\ a b c\ ')) expect(cop.messages.empty?).to be(true) end it 'accepts multi-line literals' do inspect_source(<<-RUBY.strip_indent) %#{type}( a b c ) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts multi-line literals within a method' do inspect_source(<<-RUBY.strip_indent) def foo %#{type}( a b c ) end RUBY expect(cop.messages.empty?).to be(true) end it 'accepts newlines and additional following alignment spaces' do inspect_source(<<-RUBY.strip_indent) %#{type}(a b c) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts spaces between entries' do inspect_source(code_example('a b c')) expect(cop.messages.empty?).to be(true) end end end end it 'accepts other percent literals' do expect_no_offenses(<<-RUBY) %q( a b c ) %r( a b c ) %s( a b c ) RUBY end it 'accepts execute-string literals' do expect_no_offenses('` curl `') end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_range_literal_spec.rb000066400000000000000000000030501322072016200266170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideRangeLiteral do subject(:cop) { described_class.new } it 'registers an offense for space inside .. literal' do inspect_source(<<-RUBY.strip_indent) 1 .. 2 1.. 2 1 ..2 RUBY expect(cop.offenses.size).to eq(3) expect(cop.messages) .to eq(['Space inside range literal.'] * 3) end it 'accepts no space inside .. literal' do expect_no_offenses('1..2') end it 'registers an offense for space inside ... literal' do inspect_source(<<-RUBY.strip_indent) 1 ... 2 1... 2 1 ...2 RUBY expect(cop.offenses.size).to eq(3) expect(cop.messages) .to eq(['Space inside range literal.'] * 3) end it 'accepts no space inside ... literal' do expect_no_offenses('1...2') end it 'accepts complex range literal with space in it' do expect_no_offenses('0...(line - 1)') end it 'accepts multiline range literal with no space in it' do expect_no_offenses(<<-RUBY.strip_indent) x = 0.. 10 RUBY end it 'registers an offense in multiline range literal with space in it' do inspect_source(<<-RUBY.strip_indent) x = 0 .. 10 RUBY expect(cop.offenses.size).to eq(1) end it 'autocorrects space around .. literal' do corrected = autocorrect_source(['1 .. 2']) expect(corrected).to eq '1..2' end it 'autocorrects space around ... literal' do corrected = autocorrect_source(['1 ... 2']) expect(corrected).to eq '1...2' end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_reference_brackets_spec.rb000066400000000000000000000175561322072016200276430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideReferenceBrackets, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } it 'does not register offense for array literals' do expect_no_offenses(<<-RUBY.strip_indent) a = [1, 2 ] b = [ 3, 4] c = [5, 6] d = [ 7, 8 ] RUBY end it 'does not register offense for reference brackets with no spaces' do expect_no_offenses(<<-RUBY.strip_indent) a[1] b[index, 2] c["foo"] d[:bar] RUBY end it 'does not register offense for ref bcts with no spaces that assign' do expect_no_offenses(<<-RUBY.strip_indent) a[1] = 2 b[345] = [ 678, var, "", nil] c["foo"] = "qux" d[:bar] = var RUBY end it 'accepts square brackets as method name' do expect_no_offenses(<<-RUBY.strip_indent) def Vector.[](*array) end RUBY end it 'accepts square brackets called with method call syntax' do expect_no_offenses('subject.[](0)') end it 'accepts an array as a reference object' do expect_no_offenses('a[[ 1, 2 ]]') end it 'registers offense in ref brackets with leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[ :key] ^^ Do not use space inside reference brackets. RUBY end it 'registers offense in ref brackets with trailing whitespace' do expect_offense(<<-RUBY.strip_indent) b[:key ] ^ Do not use space inside reference brackets. RUBY end it 'registers offense in second ref brackets with leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[:key][ "key"] ^ Do not use space inside reference brackets. RUBY end it 'registers offense in second ref brackets with trailing whitespace' do expect_offense(<<-RUBY.strip_indent) a[1][:key ] ^^^ Do not use space inside reference brackets. RUBY end it 'registers offense in third ref brackets with leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[:key][3][ :key] ^ Do not use space inside reference brackets. RUBY end it 'registers offense in third ref brackets with trailing whitespace' do expect_offense(<<-RUBY.strip_indent) a[var]["key", 3][:key ] ^ Do not use space inside reference brackets. RUBY end it 'registers multiple offenses in one set of ref brackets' do inspect_source(<<-RUBY.strip_indent) b[ 89 ] RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq) .to eq(['Do not use space inside reference brackets.']) end it 'registers multiple offenses for multiple sets of ref brackets' do inspect_source(<<-RUBY.strip_indent) a[ :key]["foo" ][ 0 ] RUBY expect(cop.offenses.size).to eq(4) expect(cop.messages.uniq) .to eq(['Do not use space inside reference brackets.']) end context 'auto-correct' do it 'fixes multiple offenses in one set of ref brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) bar[ 89 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) bar[89] RUBY end it 'fixes multiple offenses for multiple sets of ref brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) b[ :key]["foo" ][ 0 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) b[:key]["foo"][0] RUBY end it 'avoids altering array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) j[ "pop"] = [89, nil, "" ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) j["pop"] = [89, nil, "" ] RUBY end end end context 'when EnforcedStyle is space' do let(:cop_config) { { 'EnforcedStyle' => 'space' } } it 'does not register offense for array literals' do expect_no_offenses(<<-RUBY.strip_indent) a = [1, 2 ] b = [ 3, 4] c = [5, 6] d = [ 7, 8 ] RUBY end it 'does not register offense for reference brackets with spaces' do expect_no_offenses(<<-RUBY.strip_indent) a[ 1 ] b[ index, 3 ] c[ "foo" ] d[ :bar ] RUBY end it 'does not register offense for ref bcts with spaces that assign' do expect_no_offenses(<<-RUBY.strip_indent) a[ 1 ] = 2 b[ 345 ] = [ 678, var, "", nil] c[ "foo" ] = "qux" d[ :bar ] = var RUBY end it 'accepts square brackets as method name' do expect_no_offenses(<<-RUBY.strip_indent) def Vector.[](*array) end RUBY end it 'accepts square brackets called with method call syntax' do expect_no_offenses('subject.[](0)') end it 'accepts an array as a reference object' do expect_no_offenses('a[ [1, 2] ]') end it 'registers offense in ref brackets with no leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[:key ] ^ Use space inside reference brackets. RUBY end it 'registers offense in ref brackets with no trailing whitespace' do expect_offense(<<-RUBY.strip_indent) b[ :key] ^ Use space inside reference brackets. RUBY end it 'registers offense in second ref brackets with no leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[ :key ]["key" ] ^ Use space inside reference brackets. RUBY end it 'registers offense in second ref brackets with no trailing whitespace' do expect_offense(<<-RUBY.strip_indent) a[ 5, 1 ][ :key] ^ Use space inside reference brackets. RUBY end it 'registers offense in third ref brackets with no leading whitespace' do expect_offense(<<-RUBY.strip_indent) a[ :key ][ 3 ][:key ] ^ Use space inside reference brackets. RUBY end it 'registers offense in third ref brackets with no trailing whitespace' do expect_offense(<<-RUBY.strip_indent) a[ var ][ "key" ][ :key] ^ Use space inside reference brackets. RUBY end it 'registers multiple offenses in one set of ref brackets' do inspect_source(<<-RUBY.strip_indent) b[89] RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq) .to eq(['Use space inside reference brackets.']) end it 'registers multiple offenses for multiple sets of ref brackets' do inspect_source(<<-RUBY.strip_indent) a[:key]["foo" ][0] RUBY expect(cop.offenses.size).to eq(5) expect(cop.messages.uniq) .to eq(['Use space inside reference brackets.']) end context 'auto-correct' do it 'fixes multiple offenses in one set of ref brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) bar[89] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) bar[ 89 ] RUBY end it 'fixes multiple offenses for multiple sets of ref brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) b[:key][ "foo"][0 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) b[ :key ][ "foo" ][ 0 ] RUBY end it 'avoids altering array brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) j[ "pop"] = [89, nil, "" ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) j[ "pop" ] = [89, nil, "" ] RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/layout/space_inside_string_interpolation_spec.rb000066400000000000000000000066411322072016200302750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::SpaceInsideStringInterpolation, :config do subject(:cop) { described_class.new(config) } let(:irregular_source) do ['"#{ var}"', '"#{var }"', '"#{ var }"', '"#{var }"', '"#{ var }"', '"#{ var}"', '"#{ var }"'] end shared_examples 'ill-formatted string interpolations' do let(:source_length) { source.class == String ? 1 : source.length } it 'registers an offense for any irregular spacing inside the braces' do inspect_source(source) expect(cop.messages).to eq([expected_message] * source_length) end it 'auto-corrects spacing within a string interpolation' do new_source = autocorrect_source(source) expected_source = ([corrected_source] * source_length).join("\n") expect(new_source).to eq(expected_source) end end context 'when EnforcedStyle is no_space' do let(:cop_config) { { 'EnforcedStyle' => 'no_space' } } let(:expected_message) do 'Space inside string interpolation detected.' end context 'for always ill-formatted string interpolations' do let(:source) { irregular_source } let(:corrected_source) { '"#{var}"' } it_behaves_like 'ill-formatted string interpolations' end context 'for "space" style formatted string interpolations' do let(:source) { '"#{ var }"' } let(:corrected_source) { '"#{var}"' } it_behaves_like 'ill-formatted string interpolations' end context 'for well-formatted string interpolations' do let(:source) do ['"Variable is #{var} "', '" Variable is #{var}"'] end it 'does not register an offense for excess literal spacing' do expect_no_offenses(<<-'RUBY'.strip_indent) "Variable is #{var} " " Variable is #{var}" RUBY end it 'does not correct valid string interpolations' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end it 'accepts empty interpolation' do expect_no_offenses("\"\#{}\"") end end context 'when EnforcedStyle is space' do let(:cop_config) { { 'EnforcedStyle' => 'space' } } let(:expected_message) do 'Missing space around string interpolation detected.' end context 'for always ill-formatted string interpolations' do let(:source) { irregular_source } let(:corrected_source) { '"#{ var }"' } it_behaves_like 'ill-formatted string interpolations' end context 'for "no_space" style formatted string interpolations' do let(:source) { '"#{var}"' } let(:corrected_source) { '"#{ var }"' } it_behaves_like 'ill-formatted string interpolations' end context 'for well-formatted string interpolations' do let(:source) do ['"Variable is #{ var } "', '" Variable is #{ var }"'] end it 'does not register an offense for excess literal spacing' do expect_no_offenses(<<-'RUBY'.strip_indent) "Variable is #{ var } " " Variable is #{ var }" RUBY end it 'does not correct valid string interpolations' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end it 'accepts empty interpolation' do expect_no_offenses("\"\#{}\"") end end end rubocop-0.52.1/spec/rubocop/cop/layout/tab_spec.rb000066400000000000000000000043721322072016200220570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::Tab do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end it 'registers an offense for a line indented with tab' do expect_offense(<<-RUBY.strip_indent) x = 0 ^ Tab detected. RUBY end it 'registers an offense for a line indented with multiple tabs' do expect_offense(<<-RUBY.strip_indent) x = 0 ^^^ Tab detected. RUBY end it 'registers an offense for a line indented with mixed whitespace' do expect_offense(<<-RUBY.strip_indent) x = 0 ^ Tab detected. RUBY end it 'registers offenses before __RUBY__ but not after' do expect_offense(<<-RUBY.strip_indent) \tx = 0 ^ Tab detected. __END__ \tx = 0 RUBY end it 'accepts a line with tab in a string' do expect_no_offenses("(x = \"\t\")") end it 'accepts a line which begins with tab in a string' do expect_no_offenses("x = '\n\thello'") end it 'accepts a line which begins with tab in a heredoc' do expect_no_offenses("x = < { 'IndentationWidth' => 3 }, 'Layout/IndentationWidth' => { 'Width' => 2 }) end it 'uses the configured number of spaces to replace a tab' do new_source = autocorrect_source("\tx = 0") expect(new_source).to eq(' x = 0') end end end rubocop-0.52.1/spec/rubocop/cop/layout/trailing_blank_lines_spec.rb000066400000000000000000000077171322072016200254710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::TrailingBlankLines, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is final_newline' do let(:cop_config) { { 'EnforcedStyle' => 'final_newline' } } it 'accepts final newline' do expect_no_offenses("x = 0\n") end it 'accepts an empty file' do expect_no_offenses('') end it 'accepts final blank lines if they come after __END__' do expect_no_offenses(<<-RUBY.strip_indent) x = 0 __END__ RUBY end it 'accepts final blank lines if they come after __END__ in empty file' do expect_no_offenses(<<-RUBY.strip_indent) __END__ RUBY end it 'registers an offense for multiple trailing blank lines' do inspect_source(['x = 0', '', '', '', '']) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['3 trailing blank lines detected.']) end it 'registers an offense for multiple blank lines in an empty file' do inspect_source(['', '', '', '', '']) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['3 trailing blank lines detected.']) end it 'registers an offense for no final newline after assignment' do inspect_source('x = 0') expect(cop.messages).to eq(['Final newline missing.']) end it 'registers an offense for no final newline after block comment' do inspect_source("puts 'testing rubocop when final new line is missing " \ "after block comments'\n\n=begin\nfirst line\nsecond " \ "line\nthird line\n=end") expect(cop.messages).to eq(['Final newline missing.']) end it 'auto-corrects unwanted blank lines' do new_source = autocorrect_source(['x = 0', '', '', '', '']) expect(new_source).to eq(['x = 0', ''].join("\n")) end it 'auto-corrects unwanted blank lines in an empty file' do new_source = autocorrect_source(['', '', '', '', '']) expect(new_source).to eq(['', ''].join("\n")) end it 'auto-corrects even if some lines have space' do new_source = autocorrect_source(['x = 0', '', ' ', '', '']) expect(new_source).to eq(['x = 0', ''].join("\n")) end end context 'when EnforcedStyle is final_blank_line' do let(:cop_config) { { 'EnforcedStyle' => 'final_blank_line' } } it 'registers an offense for final newline' do inspect_source(['x = 0', '']) expect(cop.messages).to eq(['Trailing blank line missing.']) end it 'registers an offense for multiple trailing blank lines' do inspect_source(['x = 0', '', '', '', '']) expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['3 trailing blank lines instead of 1 detected.']) end it 'registers an offense for multiple blank lines in an empty file' do inspect_source(['', '', '', '', '']) expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['3 trailing blank lines instead of 1 detected.']) end it 'registers an offense for no final newline' do inspect_source('x = 0') expect(cop.messages).to eq(['Final newline missing.']) end it 'accepts final blank line' do expect_no_offenses("x = 0\n\n") end it 'auto-corrects unwanted blank lines' do new_source = autocorrect_source(['x = 0', '', '', '', '']) expect(new_source).to eq(['x = 0', '', ''].join("\n")) end it 'auto-corrects unwanted blank lines in an empty file' do new_source = autocorrect_source(['', '', '', '', '']) expect(new_source).to eq(['', '', ''].join("\n")) end it 'auto-corrects missing blank line' do new_source = autocorrect_source(['x = 0', '']) expect(new_source).to eq(['x = 0', '', ''].join("\n")) end it 'auto-corrects missing newline' do new_source = autocorrect_source(['x = 0']) expect(new_source).to eq(['x = 0', '', ''].join("\n")) end end end rubocop-0.52.1/spec/rubocop/cop/layout/trailing_whitespace_spec.rb000066400000000000000000000042511322072016200253320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Layout::TrailingWhitespace do subject(:cop) { described_class.new } it 'registers an offense for a line ending with space' do inspect_source('x = 0 ') expect(cop.offenses.size).to eq(1) end it 'registers an offense for a blank line with space' do inspect_source(' ') expect(cop.offenses.size).to eq(1) end it 'registers an offense for a line ending with tab' do inspect_source("x = 0\t") expect(cop.offenses.size).to eq(1) end it 'registers an offense for trailing whitespace in a heredoc string' do inspect_source(['x = <(a) { bar a }' it_behaves_like 'accepts', 'some_method(a) { |el| puts el }' it_behaves_like 'accepts', 'some_method(a) do;puts a;end' it_behaves_like 'accepts', 'some_method a do;puts "dev";end' it_behaves_like 'accepts', 'some_method a do |e|;puts e;end' it_behaves_like 'accepts', 'Foo.bar(a) { |el| puts el }' it_behaves_like 'accepts', 'env ENV.fetch("ENV") { "dev" }' it_behaves_like 'accepts', 'env(ENV.fetch("ENV") { "dev" })' it_behaves_like 'accepts', '{ f: "b"}.fetch(:a) do |e|;puts e;end' it_behaves_like 'accepts', 'Hash[some_method(a) { |el| el }]' it_behaves_like 'accepts', 'foo = lambda do |diagnostic|;end' it_behaves_like 'accepts', 'Proc.new { puts "proc" }' it_behaves_like 'accepts', 'expect { order.save }.to(change { orders.size })' it_behaves_like 'accepts', 'scope :active, -> { where(status: "active") }' it_behaves_like( 'accepts', 'assert_equal posts.find { |p| p.title == "Foo" }, results.first' ) it_behaves_like( 'accepts', 'assert_equal(posts.find { |p| p.title == "Foo" }, results.first)' ) it_behaves_like( 'accepts', 'assert_equal(results.first, posts.find { |p| p.title == "Foo" })' ) it_behaves_like( 'accepts', 'allow(cop).to receive(:on_int) { raise RuntimeError }' ) it_behaves_like( 'accepts', 'allow(cop).to(receive(:on_int) { raise RuntimeError })' ) context 'without parentheses' do context 'without receiver' do let(:source) { 'some_method a { |el| puts el }' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, 'a { |el| puts el }', 'a')) ) end end context 'with receiver' do let(:source) { 'Foo.some_method a { |el| puts el }' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, 'a { |el| puts el }', 'a')) ) end end context 'rspec expect {}.to change {}' do let(:source) do 'expect { order.expire }.to change { order.events }' end it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, 'change { order.events }', 'change')) ) end end context 'as a hash key' do let(:source) { 'Hash[some_method a { |el| el }]' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, 'a { |el| el }', 'a')) ) end end context 'with assignment' do let(:source) { 'foo = some_method a { |el| puts el }' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, 'a { |el| puts el }', 'a')) ) end end end end rubocop-0.52.1/spec/rubocop/cop/lint/ambiguous_operator_spec.rb000066400000000000000000000051451322072016200246470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::AmbiguousOperator do subject(:cop) { described_class.new } context 'with a splat operator in the first argument' do context 'without parentheses' do context 'without whitespaces on the right of the operator' do let(:source) do <<-RUBY.strip_indent array = [1, 2, 3] puts *array RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Ambiguous splat operator. ' \ "Parenthesize the method arguments if it's surely a splat " \ 'operator, ' \ 'or add a whitespace to the right of the `*` if it should be a ' \ 'multiplication.' ) expect(cop.highlights).to eq(['*']) end end context 'with a whitespace on the right of the operator' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) array = [1, 2, 3] puts * array RUBY end end end context 'with parentheses' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) array = [1, 2, 3] puts(*array) RUBY end end end context 'with a block ampersand in the first argument' do context 'without parentheses' do context 'without whitespaces on the right of the operator' do let(:source) do <<-RUBY.strip_indent process = proc { do_something } 2.times &process RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Ambiguous block operator. ' \ "Parenthesize the method arguments if it's surely a block " \ 'operator, ' \ 'or add a whitespace to the right of the `&` if it should be a ' \ 'binary AND.' ) expect(cop.highlights).to eq(['&']) end end context 'with a whitespace on the right of the operator' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) process = proc { do_something } 2.times & process RUBY end end end context 'with parentheses' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) process = proc { do_something } 2.times(&process) RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/lint/ambiguous_regexp_literal_spec.rb000066400000000000000000000015011322072016200260120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::AmbiguousRegexpLiteral do subject(:cop) { described_class.new } context 'with a regexp literal in the first argument' do context 'without parentheses' do let(:source) { 'p /pattern/' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Ambiguous regexp literal. Parenthesize the method arguments ' \ "if it's surely a regexp literal, or add a whitespace to the " \ 'right of the `/` if it should be a division.' ) expect(cop.highlights).to eq(['/']) end end context 'with parentheses' do it 'accepts' do expect_no_offenses('p(/pattern/)') end end end end rubocop-0.52.1/spec/rubocop/cop/lint/assignment_in_condition_spec.rb000066400000000000000000000124431322072016200256440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::AssignmentInCondition, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowSafeAssignment' => true } } it 'registers an offense for lvar assignment in condition' do expect_offense(<<-RUBY.strip_indent) if test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for lvar assignment in while condition' do expect_offense(<<-RUBY.strip_indent) while test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for lvar assignment in until condition' do expect_offense(<<-RUBY.strip_indent) until test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for ivar assignment in condition' do expect_offense(<<-RUBY.strip_indent) if @test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for clvar assignment in condition' do expect_offense(<<-RUBY.strip_indent) if @@test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for gvar assignment in condition' do expect_offense(<<-RUBY.strip_indent) if $test = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for constant assignment in condition' do expect_offense(<<-RUBY.strip_indent) if TEST = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'registers an offense for collection element assignment in condition' do expect_offense(<<-RUBY.strip_indent) if a[3] = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'accepts == in condition' do expect_no_offenses(<<-RUBY.strip_indent) if test == 10 end RUBY end it 'registers an offense for assignment after == in condition' do expect_offense(<<-RUBY.strip_indent) if test == 10 || foobar = 1 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'accepts = in a block that is called in a condition' do expect_no_offenses('return 1 if any_errors? { o = inspect(file) }') end it 'accepts = in a block followed by method call' do expect_no_offenses('return 1 if any_errors? { o = file }.present?') end it 'accepts ||= in condition' do expect_no_offenses('raise StandardError unless foo ||= bar') end it 'registers an offense for assignment after ||= in condition' do expect_offense(<<-RUBY.strip_indent) raise StandardError unless (foo ||= bar) || a = b ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. RUBY end it 'registers an offense for assignment methods' do expect_offense(<<-RUBY.strip_indent) if test.method = 10 ^ Use `==` if you meant to do a comparison or wrap the expression in parentheses to indicate you meant to assign in a condition. end RUBY end it 'does not blow up for empty if condition' do expect_no_offenses(<<-RUBY.strip_indent) if () end RUBY end it 'does not blow up for empty unless condition' do expect_no_offenses(<<-RUBY.strip_indent) unless () end RUBY end context 'safe assignment is allowed' do it 'accepts = in condition surrounded with braces' do expect_no_offenses(<<-RUBY.strip_indent) if (test = 10) end RUBY end it 'accepts []= in condition surrounded with braces' do expect_no_offenses(<<-RUBY.strip_indent) if (test[0] = 10) end RUBY end end context 'safe assignment is not allowed' do let(:cop_config) { { 'AllowSafeAssignment' => false } } it 'does not accept = in condition surrounded with braces' do expect_offense(<<-RUBY.strip_indent) if (test = 10) ^ Use `==` if you meant to do a comparison or move the assignment up out of the condition. end RUBY end it 'does not accept []= in condition surrounded with braces' do expect_offense(<<-RUBY.strip_indent) if (test[0] = 10) ^ Use `==` if you meant to do a comparison or move the assignment up out of the condition. end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/block_alignment_spec.rb000066400000000000000000000501241322072016200240660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::BlockAlignment, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'EnforcedStyleAlignWith' => 'either' } end context 'when the block has no arguments' do it 'registers an offense for mismatched block end' do expect_offense(<<-RUBY.strip_indent) test do end ^^^ `end` at 2, 2 is not aligned with `test do` at 1, 0. RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do end RUBY end end context 'when the block has arguments' do it 'registers an offense for mismatched block end' do expect_offense(<<-RUBY.strip_indent) test do |ala| end ^^^ `end` at 2, 2 is not aligned with `test do |ala|` at 1, 0. RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source(<<-RUBY.strip_indent) test do |ala| end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) test do |ala| end RUBY end end it 'accepts a block end that does not begin its line' do expect_no_offenses(<<-RUBY.strip_indent) scope :bar, lambda { joins(:baz) .distinct } RUBY end context 'when the block is a logical operand' do it 'accepts a correctly aligned block end' do expect_no_offenses(<<-RUBY.strip_indent) (value.is_a? Array) && value.all? do |subvalue| type_check_value(subvalue, array_type) end a || b do end RUBY end end it 'accepts end aligned with a variable' do expect_no_offenses(<<-RUBY.strip_indent) variable = test do |ala| end RUBY end context 'when there is an assignment chain' do it 'registers an offense for an end aligned with the 2nd variable' do expect_offense(<<-RUBY.strip_indent) a = b = c = test do |ala| end ^^^ `end` at 2, 4 is not aligned with `a = b = c = test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with the first variable' do expect_no_offenses(<<-RUBY.strip_indent) a = b = c = test do |ala| end RUBY end it 'auto-corrects alignment to the first variable' do new_source = autocorrect_source(<<-RUBY.strip_indent) a = b = c = test do |ala| end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = b = c = test do |ala| end RUBY end end context 'and the block is an operand' do it 'accepts end aligned with a variable' do expect_no_offenses(<<-RUBY.strip_indent) b = 1 + preceding_line.reduce(0) do |a, e| a + e.length + newline_length end + 1 RUBY end end it 'registers an offense for mismatched block end with a variable' do expect_offense(<<-RUBY.strip_indent) variable = test do |ala| end ^^^ `end` at 2, 2 is not aligned with `variable = test do |ala|` at 1, 0. RUBY end context 'when the block is defined on the next line' do it 'accepts end aligned with the block expression' do expect_no_offenses(<<-RUBY.strip_indent) variable = a_long_method_that_dont_fit_on_the_line do |v| v.foo end RUBY end it 'registers an offenses for mismatched end alignment' do expect_offense(<<-RUBY.strip_indent) variable = a_long_method_that_dont_fit_on_the_line do |v| v.foo end ^^^ `end` at 4, 0 is not aligned with `a_long_method_that_dont_fit_on_the_line do |v|` at 2, 2. RUBY end it 'auto-corrects alignment' do new_source = autocorrect_source( <<-RUBY.strip_indent variable = a_long_method_that_dont_fit_on_the_line do |v| v.foo end RUBY ) expect(new_source) .to eq(<<-RUBY.strip_indent) variable = a_long_method_that_dont_fit_on_the_line do |v| v.foo end RUBY end end context 'when the method part is a call chain that spans several lines' do # Example from issue 346 of bbatsov/rubocop on github: it 'accepts pretty alignment style' do expect_no_offenses(<<-RUBY.strip_indent) def foo(bar) bar.get_stuffs .reject do |stuff| stuff.with_a_very_long_expression_that_doesnt_fit_the_line end.select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end .select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end end RUBY end it 'registers offenses for misaligned ends' do src = <<-RUBY.strip_indent def foo(bar) bar.get_stuffs .reject do |stuff| stuff.with_a_very_long_expression_that_doesnt_fit_the_line end.select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end .select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end end RUBY inspect_source(src) expect(cop.messages) .to eq(['`end` at 5, 8 is not aligned with `bar.get_stuffs` at 2, 2' \ ' or `.reject do |stuff|` at 3, 6.', '`end` at 7, 4 is not aligned with `bar.get_stuffs` at 2, 2' \ ' or `end.select do |stuff|` at 5, 8.', '`end` at 10, 8 is not aligned with `bar.get_stuffs` at 2, 2' \ ' or `.select do |stuff|` at 8, 6.']) end # Example from issue 393 of bbatsov/rubocop on github: it 'accepts end indented as the start of the block' do expect_no_offenses(<<-RUBY.strip_indent) my_object.chaining_this_very_long_method(with_a_parameter) .and_one_with_a_block do do_something end # Other variant: my_object.chaining_this_very_long_method( with_a_parameter).and_one_with_a_block do do_something end RUBY end # Example from issue 447 of bbatsov/rubocop on github: it 'accepts two kinds of end alignment' do expect_no_offenses(<<-RUBY.strip_indent) # Aligned with start of line where do is: params = default_options.merge(options) .delete_if { |k, v| v.nil? } .each_with_object({}) do |(k, v), new_hash| new_hash[k.to_s] = v.to_s end # Aligned with start of the whole expression: params = default_options.merge(options) .delete_if { |k, v| v.nil? } .each_with_object({}) do |(k, v), new_hash| new_hash[k.to_s] = v.to_s end RUBY end it 'auto-corrects misaligned ends with the start of the expression' do src = <<-RUBY.strip_indent def foo(bar) bar.get_stuffs .reject do |stuff| stuff.with_a_very_long_expression_that_doesnt_fit_the_line end.select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end .select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end end RUBY aligned_src = <<-RUBY.strip_indent def foo(bar) bar.get_stuffs .reject do |stuff| stuff.with_a_very_long_expression_that_doesnt_fit_the_line end.select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end .select do |stuff| stuff.another_very_long_expression_that_doesnt_fit_the_line end end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(aligned_src) end end context 'when variables of a mass assignment spans several lines' do it 'accepts end aligned with the variables' do expect_no_offenses(<<-RUBY.strip_indent) e, f = [5, 6].map do |i| i - 5 end RUBY end it 'registers an offense for end aligned with the block' do src = <<-RUBY.strip_indent e, f = [5, 6].map do |i| i - 5 end RUBY inspect_source(src) expect(cop.messages) .to eq(['`end` at 4, 4 is not aligned with `e,` at 1, 0 or' \ ' `f = [5, 6].map do |i|` at 2, 0.']) end it 'auto-corrects' do src = <<-RUBY.strip_indent e, f = [5, 6].map do |i| i - 5 end RUBY corrected = <<-RUBY.strip_indent e, f = [5, 6].map do |i| i - 5 end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(corrected) end end it 'accepts end aligned with an instance variable' do expect_no_offenses(<<-RUBY.strip_indent) @variable = test do |ala| end RUBY end it 'registers an offense for mismatched block end with' \ ' an instance variable' do inspect_source(<<-RUBY.strip_indent) @variable = test do |ala| end RUBY expect(cop.messages) .to eq(['`end` at 2, 2 is not aligned with `@variable = test do |ala|`' \ ' at 1, 0.']) end it 'accepts end aligned with a class variable' do expect_no_offenses(<<-RUBY.strip_indent) @@variable = test do |ala| end RUBY end it 'registers an offense for mismatched block end with a class variable' do expect_offense(<<-RUBY.strip_indent) @@variable = test do |ala| end ^^^ `end` at 2, 2 is not aligned with `@@variable = test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with a global variable' do expect_no_offenses(<<-RUBY.strip_indent) $variable = test do |ala| end RUBY end it 'registers an offense for mismatched block end with a global variable' do expect_offense(<<-RUBY.strip_indent) $variable = test do |ala| end ^^^ `end` at 2, 2 is not aligned with `$variable = test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with a constant' do expect_no_offenses(<<-RUBY.strip_indent) CONSTANT = test do |ala| end RUBY end it 'registers an offense for mismatched block end with a constant' do expect_offense(<<-RUBY.strip_indent) Module::CONSTANT = test do |ala| end ^^^ `end` at 2, 2 is not aligned with `Module::CONSTANT = test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with a method call' do expect_no_offenses(<<-RUBY.strip_indent) parser.children << lambda do |token| token << 1 end RUBY end it 'registers an offense for mismatched block end with a method call' do expect_offense(<<-RUBY.strip_indent) parser.children << lambda do |token| token << 1 end ^^^ `end` at 3, 2 is not aligned with `parser.children << lambda do |token|` at 1, 0. RUBY end it 'accepts end aligned with a method call with arguments' do expect_no_offenses(<<-RUBY.strip_indent) @h[:f] = f.each_pair.map do |f, v| v = 1 end RUBY end it 'registers an offense for mismatched end with a method call' \ ' with arguments' do inspect_source(<<-RUBY.strip_indent) @h[:f] = f.each_pair.map do |f, v| v = 1 end RUBY expect(cop.messages) .to eq(['`end` at 3, 2 is not aligned with' \ ' `@h[:f] = f.each_pair.map do |f, v|` at 1, 0.']) end it 'does not raise an error for nested block in a method call' do expect_no_offenses('expect(arr.all? { |o| o.valid? })') end it 'accepts end aligned with the block when the block is a method argument' do expect_no_offenses(<<-RUBY.strip_indent) expect(arr.all? do |o| o.valid? end) RUBY end it 'registers an offense for mismatched end not aligned with the block' \ ' that is an argument' do inspect_source(<<-RUBY.strip_indent) expect(arr.all? do |o| o.valid? end) RUBY expect(cop.messages) .to eq(['`end` at 3, 2 is not aligned with `arr.all? do |o|` at 1, 7 or' \ ' `expect(arr.all? do |o|` at 1, 0.']) end it 'accepts end aligned with an op-asgn (+=, -=)' do expect_no_offenses(<<-RUBY.strip_indent) rb += files.select do |file| file << something end RUBY end it 'registers an offense for mismatched block end with an op-asgn (+=, -=)' do expect_offense(<<-RUBY.strip_indent) rb += files.select do |file| file << something end ^^^ `end` at 3, 2 is not aligned with `rb` at 1, 0. RUBY end it 'accepts end aligned with an and-asgn (&&=)' do expect_no_offenses(<<-RUBY.strip_indent) variable &&= test do |ala| end RUBY end it 'registers an offense for mismatched block end with an and-asgn (&&=)' do expect_offense(<<-RUBY.strip_indent) variable &&= test do |ala| end ^^^ `end` at 2, 2 is not aligned with `variable &&= test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with an or-asgn (||=)' do expect_no_offenses(<<-RUBY.strip_indent) variable ||= test do |ala| end RUBY end it 'registers an offense for mismatched block end with an or-asgn (||=)' do expect_offense(<<-RUBY.strip_indent) variable ||= test do |ala| end ^^^ `end` at 2, 2 is not aligned with `variable ||= test do |ala|` at 1, 0. RUBY end it 'accepts end aligned with a mass assignment' do expect_no_offenses(<<-RUBY.strip_indent) var1, var2 = lambda do |test| [1, 2] end RUBY end it 'accepts end aligned with a call chain left hand side' do expect_no_offenses(<<-RUBY.strip_indent) parser.diagnostics.consumer = lambda do |diagnostic| diagnostics << diagnostic end RUBY end it 'registers an offense for mismatched block end with a mass assignment' do expect_offense(<<-RUBY.strip_indent) var1, var2 = lambda do |test| [1, 2] end ^^^ `end` at 3, 2 is not aligned with `var1, var2` at 1, 0. RUBY end context 'when multiple similar-looking blocks have misaligned ends' do it 'registers an offense for each of them' do expect_offense(<<-RUBY.strip_indent) a = test do end ^^^ `end` at 2, 1 is not aligned with `a = test do` at 1, 0. b = test do end ^^^ `end` at 4, 1 is not aligned with `b = test do` at 3, 0. RUBY end end context 'on a splatted method call' do it 'aligns end with the splat operator' do expect_no_offenses(<<-RUBY.strip_indent) def get_gems_by_name @gems ||= Hash[*get_latest_gems.map { |gem| [gem.name, gem, gem.full_name, gem] }.flatten] end RUBY end it 'autocorrects' do source = <<-RUBY.strip_indent def get_gems_by_name @gems ||= Hash[*get_latest_gems.map { |gem| [gem.name, gem, gem.full_name, gem] }.flatten] end RUBY corrected = <<-RUBY.strip_indent def get_gems_by_name @gems ||= Hash[*get_latest_gems.map { |gem| [gem.name, gem, gem.full_name, gem] }.flatten] end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected) end end context 'on a bit-flipped method call' do it 'aligns end with the ~ operator' do expect_no_offenses(<<-RUBY.strip_indent) def abc @abc ||= A[~xyz { |x| x }.flatten] end RUBY end it 'autocorrects' do source = <<-RUBY.strip_indent def abc @abc ||= A[~xyz { |x| x }.flatten] end RUBY corrected = <<-RUBY.strip_indent def abc @abc ||= A[~xyz { |x| x }.flatten] end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected) end end context 'on a logically negated method call' do it 'aligns end with the ! operator' do expect_no_offenses(<<-RUBY.strip_indent) def abc @abc ||= A[!xyz { |x| x }.flatten] end RUBY end it 'autocorrects' do source = <<-RUBY.strip_indent def abc @abc ||= A[!xyz { |x| x }.flatten] end RUBY corrected = <<-RUBY.strip_indent def abc @abc ||= A[!xyz { |x| x }.flatten] end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected) end end context 'on an arithmetically negated method call' do it 'aligns end with the - operator' do expect_no_offenses(<<-RUBY.strip_indent) def abc @abc ||= A[-xyz { |x| x }.flatten] end RUBY end it 'autocorrects' do source = <<-RUBY.strip_indent def abc @abc ||= A[-xyz { |x| x }.flatten] end RUBY corrected = <<-RUBY.strip_indent def abc @abc ||= A[-xyz { |x| x }.flatten] end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected) end end context 'when the block is terminated by }' do it 'mentions } (not end) in the message' do expect_offense(<<-RUBY.strip_indent) test { } ^ `}` at 2, 2 is not aligned with `test {` at 1, 0. RUBY end end context 'when configured to align with start_of_line' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_line' } end it 'allows when start_of_line aligned' do expect_no_offenses(<<-RUBY.strip_indent) foo.bar .each do baz end RUBY end it 'errors when do aligned' do src = <<-RUBY.strip_indent foo.bar .each do baz end RUBY inspect_source(src) expect(cop.messages) .to eq(['`end` at 4, 2 is not aligned with ' \ '`foo.bar` at 1, 0.']) end it 'autocorrects' do src = <<-RUBY.strip_indent foo.bar .each do baz end RUBY corrected = <<-RUBY.strip_indent foo.bar .each do baz end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(corrected) end end context 'when configured to align with do' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_block' } end it 'allows when do aligned' do expect_no_offenses(<<-RUBY.strip_indent) foo.bar .each do baz end RUBY end it 'errors when start_of_line aligned' do src = <<-RUBY.strip_indent foo.bar .each do baz end RUBY inspect_source(src) expect(cop.messages) .to eq(['`end` at 4, 0 is not aligned with ' \ '`.each do` at 2, 2.']) end it 'autocorrects' do src = <<-RUBY.strip_indent foo.bar .each do baz end RUBY corrected = <<-RUBY.strip_indent foo.bar .each do baz end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(corrected) end end end rubocop-0.52.1/spec/rubocop/cop/lint/boolean_symbol_spec.rb000066400000000000000000000026251322072016200237450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::BooleanSymbol, :config do subject(:cop) { described_class.new(config) } it 'registers an offense when using `:true`' do expect_offense(<<-RUBY.strip_indent) :true ^^^^^ Symbol with a boolean name - you probably meant to use `true`. RUBY end it 'registers an offense when using `:false`' do expect_offense(<<-RUBY.strip_indent) :false ^^^^^^ Symbol with a boolean name - you probably meant to use `false`. RUBY end context 'when using the new hash syntax' do it 'registers an offense when using `true:`' do expect_offense(<<-RUBY.strip_indent) { true: 'Foo' } ^^^^ Symbol with a boolean name - you probably meant to use `true`. RUBY end it 'registers an offense when using `false:`' do expect_offense(<<-RUBY.strip_indent) { false: 'Bar' } ^^^^^ Symbol with a boolean name - you probably meant to use `false`. RUBY end end it 'does not register an offense when using regular symbol' do expect_no_offenses(<<-RUBY.strip_indent) :something RUBY end it 'does not register an offense when using `true`' do expect_no_offenses(<<-RUBY.strip_indent) true RUBY end it 'does not register an offense when using `false`' do expect_no_offenses(<<-RUBY.strip_indent) false RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/circular_argument_reference_spec.rb000066400000000000000000000111551322072016200264630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::CircularArgumentReference do subject(:cop) { described_class.new } describe 'circular argument references in ordinal arguments' do before do inspect_source(source) end context 'when the method contains a circular argument reference' do let(:source) do <<-RUBY.strip_indent def omg_wow(msg = msg) puts msg end RUBY end it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Circular argument reference - `msg`.') expect(cop.highlights).to eq ['msg'] end end context 'when the method does not contain a circular argument reference' do let(:source) do <<-RUBY.strip_indent def omg_wow(msg) puts msg end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def omg_wow(msg) puts msg end RUBY end end context 'when the seemingly-circular default value is a method call' do let(:source) do <<-RUBY.strip_indent def omg_wow(msg = self.msg) puts msg end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def omg_wow(msg = self.msg) puts msg end RUBY end end end describe 'circular argument references in keyword arguments' do before do inspect_source(source) end context 'when the keyword argument is not circular' do let(:source) do <<-RUBY.strip_indent def some_method(some_arg: nil) puts some_arg end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def some_method(some_arg: nil) puts some_arg end RUBY end end context 'when the keyword argument is not circular, and calls a method' do let(:source) do <<-RUBY.strip_indent def some_method(some_arg: some_method) puts some_arg end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def some_method(some_arg: some_method) puts some_arg end RUBY end end context 'when there is one circular argument reference' do let(:source) do <<-RUBY.strip_indent def some_method(some_arg: some_arg) puts some_arg end RUBY end it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Circular argument reference - `some_arg`.') expect(cop.highlights).to eq ['some_arg'] end end context 'when the keyword argument is not circular, but calls a method ' \ 'of its own class with a self specification' do let(:source) do <<-RUBY.strip_indent def puts_value(value: self.class.value, smile: self.smile) puts value end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def puts_value(value: self.class.value, smile: self.smile) puts value end RUBY end end context 'when the keyword argument is not circular, but calls a method ' \ 'of some other object with the same name' do let(:source) do <<-RUBY.strip_indent def puts_length(length: mystring.length) puts length end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def puts_length(length: mystring.length) puts length end RUBY end end context 'when there are multiple offensive keyword arguments' do let(:source) do <<-RUBY.strip_indent def some_method(some_arg: some_arg, other_arg: other_arg) puts [some_arg, other_arg] end RUBY end it 'registers two offenses' do expect(cop.offenses.size).to eq(2) expect(cop.offenses.first.message) .to eq('Circular argument reference - `some_arg`.') expect(cop.offenses.last.message) .to eq('Circular argument reference - `other_arg`.') expect(cop.highlights).to eq %w[some_arg other_arg] end end end end rubocop-0.52.1/spec/rubocop/cop/lint/condition_position_spec.rb000066400000000000000000000021711322072016200246470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ConditionPosition do subject(:cop) { described_class.new } %w[if unless while until].each do |keyword| it 'registers an offense for condition on the next line' do expect_offense(<<-RUBY.strip_indent) #{keyword} x == 10 ^^^^^^^ Place the condition on the same line as `#{keyword}`. end RUBY end it 'accepts condition on the same line' do expect_no_offenses(<<-RUBY.strip_indent) #{keyword} x == 10 bala end RUBY end it 'accepts condition on a different line for modifiers' do expect_no_offenses(<<-RUBY.strip_indent) do_something #{keyword} something && something_else RUBY end end it 'registers an offense for elsif condition on the next line' do expect_offense(<<-RUBY.strip_indent) if something test elsif something ^^^^^^^^^ Place the condition on the same line as `elsif`. test end RUBY end it 'handles ternary ops' do expect_no_offenses('x ? a : b') end end rubocop-0.52.1/spec/rubocop/cop/lint/debugger_spec.rb000066400000000000000000000052711322072016200225250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::Debugger, :config do subject(:cop) { described_class.new(config) } include_examples 'debugger', 'debugger', 'debugger' include_examples 'debugger', 'byebug', 'byebug' include_examples 'debugger', 'pry binding', %w[binding.pry binding.remote_pry binding.pry_remote] include_examples 'debugger', 'capybara debug method', %w[save_and_open_page save_and_open_screenshot save_screenshot] include_examples 'debugger', 'debugger with an argument', 'debugger foo' include_examples 'debugger', 'byebug with an argument', 'byebug foo' include_examples 'debugger', 'pry binding with an argument', ['binding.pry foo', 'binding.remote_pry foo', 'binding.pry_remote foo'] include_examples 'debugger', 'capybara debug method with an argument', ['save_and_open_page foo', 'save_and_open_screenshot foo', 'save_screenshot foo'] include_examples 'non-debugger', 'a non-pry binding', 'binding.pirate' include_examples 'debugger', 'debugger with Kernel', 'Kernel.debugger' include_examples 'debugger', 'debugger with ::Kernel', '::Kernel.debugger' include_examples 'debugger', 'binding.pry with Kernel', 'Kernel.binding.pry' include_examples 'non-debugger', 'save_and_open_page with Kernel', 'Kernel.save_and_open_page' ALL_COMMANDS = %w[debugger byebug pry remote_pry pry_remote irb save_and_open_page save_and_open_screenshot save_screenshot].freeze ALL_COMMANDS.each do |src| include_examples 'non-debugger', "a #{src} in comments", "# #{src}" include_examples 'non-debugger', "a #{src} method", "code.#{src}" end it 'reports an offense for a Pry.rescue call' do expect_offense(<<-RUBY.strip_indent) def method Pry.rescue { puts 1 } ^^^^^^^^^^ Remove debugger entry point `Pry.rescue`. ::Pry.rescue { puts 1 } ^^^^^^^^^^^^ Remove debugger entry point `::Pry.rescue`. end RUBY end context 'target_ruby_version >= 2.4', :ruby24 do include_examples 'debugger', 'irb binding', 'binding.irb' include_examples 'debugger', 'binding.irb with Kernel', 'Kernel.binding.irb' ALL_COMMANDS.each do |src| include_examples 'non-debugger', "a #{src} in comments", "# #{src}" include_examples 'non-debugger', "a #{src} method", "code.#{src}" end end end rubocop-0.52.1/spec/rubocop/cop/lint/def_end_alignment_spec.rb000066400000000000000000000061171322072016200243630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::DefEndAlignment, :config do subject(:cop) { described_class.new(config) } let(:source) do <<-RUBY.strip_indent foo def a a1 end foo def b b1 end RUBY end context 'when EnforcedStyleAlignWith is start_of_line' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_line', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'def', 'test', ' end' include_examples 'misaligned', '', 'def', 'Test.test', ' end', 'defs' include_examples 'aligned', "\xef\xbb\xbfdef", 'test', 'end' include_examples 'aligned', 'def', 'test', 'end' include_examples 'aligned', 'def', 'Test.test', 'end', 'defs' context 'in ruby 2.1 or later' do include_examples 'aligned', 'foo def', 'test', 'end' include_examples 'aligned', 'foo bar def', 'test', 'end' include_examples('misaligned', '', 'foo def', 'test', ' end') end context 'correct + opposite' do it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages.first) .to eq('`end` at 7, 4 is not aligned with `foo def` at 5, 0.') expect(cop.highlights.first).to eq('end') expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) foo def a a1 end foo def b b1 end RUBY end end end context 'when EnforcedStyleAlignWith is def' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'def', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'def', 'test', ' end' include_examples 'misaligned', '', 'def', 'Test.test', ' end', 'defs' include_examples 'aligned', 'def', 'test', 'end' include_examples 'aligned', 'def', 'Test.test', 'end', 'defs' context 'in ruby 2.1 or later' do include_examples('aligned', 'foo def', 'test', ' end') include_examples('misaligned', 'foo ', 'def', 'test', 'end') context 'correct + opposite' do it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages.first) .to eq('`end` at 3, 0 is not aligned with `def` at 1, 4.') expect(cop.highlights.first).to eq('end') expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) foo def a a1 end foo def b b1 end RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/deprecated_class_methods_spec.rb000066400000000000000000000022601322072016200257440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::DeprecatedClassMethods do subject(:cop) { described_class.new } it 'registers an offense for File.exists?' do expect_offense(<<-RUBY.strip_indent) File.exists?(o) ^^^^^^^ `File.exists?` is deprecated in favor of `File.exist?`. RUBY end it 'registers an offense for ::File.exists?' do expect_offense(<<-RUBY.strip_indent) ::File.exists?(o) ^^^^^^^ `File.exists?` is deprecated in favor of `File.exist?`. RUBY end it 'does not register an offense for File.exist?' do expect_no_offenses('File.exist?(o)') end it 'registers an offense for Dir.exists?' do expect_offense(<<-RUBY.strip_indent) Dir.exists?(o) ^^^^^^^ `Dir.exists?` is deprecated in favor of `Dir.exist?`. RUBY end it 'auto-corrects File.exists? with File.exist?' do new_source = autocorrect_source('File.exists?(something)') expect(new_source).to eq('File.exist?(something)') end it 'auto-corrects Dir.exists? with Dir.exist?' do new_source = autocorrect_source('Dir.exists?(something)') expect(new_source).to eq('Dir.exist?(something)') end end rubocop-0.52.1/spec/rubocop/cop/lint/duplicate_case_condition_spec.rb000066400000000000000000000051561322072016200257560ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::DuplicateCaseCondition do subject(:cop) { described_class.new } it 'registers an offense for repeated case conditionals' do expect_offense(<<-RUBY.strip_indent) case x when false first_method when true second_method when false ^^^^^ Duplicate `when` condition detected. third_method end RUBY end it 'registers an offense for subsequent repeated case conditionals' do expect_offense(<<-RUBY.strip_indent) case x when false first_method when false ^^^^^ Duplicate `when` condition detected. second_method end RUBY end it 'registers multiple offenses for multiple repeated case conditionals' do expect_offense(<<-RUBY.strip_indent) case x when false first_method when true second_method when false ^^^^^ Duplicate `when` condition detected. third_method when true ^^^^ Duplicate `when` condition detected. fourth_method end RUBY end it 'registers multiple offenses for repeated multi-value condtionals' do expect_offense(<<-RUBY.strip_indent) case x when a, b first_method when b, a ^ Duplicate `when` condition detected. ^ Duplicate `when` condition detected. second_method end RUBY end it 'registers an offense for repeated logical operator when expressions' do expect_offense(<<-RUBY.strip_indent) case x when a && b first_method when a && b ^^^^^^ Duplicate `when` condition detected. second_method end RUBY end it 'accepts trivial case expressions' do expect_no_offenses(<<-RUBY.strip_indent) case x when false first_method end RUBY end it 'accepts non-redundant case expressions' do expect_no_offenses(<<-RUBY.strip_indent) case x when false first_method when true second_method end RUBY end it 'accepts non-redundant case expressions with an else expression' do expect_no_offenses(<<-RUBY.strip_indent) case x when false method_name when true second_method else third_method end RUBY end it 'accepts similar but not equivalent && expressions' do expect_no_offenses(<<-RUBY.strip_indent) case x when something && another && other first_method when something && another second_method end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/duplicate_methods_spec.rb000066400000000000000000000374141322072016200244420ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::DuplicateMethods do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples 'in scope' do |type, opening_line| it "registers an offense for duplicate method in #{type}" do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it "doesn't register an offense for non-duplicate method in #{type}" do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', ' def any_method', ' implement 2', ' end', 'end']) expect(cop.offenses.empty?).to be(true) end it "registers an offense for duplicate class methods in #{type}" do inspect_source([opening_line, ' def self.some_method', ' implement 1', ' end', ' def self.some_method', ' implement 2', ' end', 'end'], 'src.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Method `A.some_method` is defined at both src.rb:2 and src.rb:5.'] ) end it "doesn't register offense for non-duplicate class methods in #{type}" do inspect_source([opening_line, ' def self.some_method', ' implement 1', ' end', ' def self.any_method', ' implement 2', ' end', 'end']) expect(cop.offenses.empty?).to be(true) end it "recognizes difference between instance and class methods in #{type}" do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', ' def self.some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.empty?).to be(true) end it "registers an offense for duplicate private methods in #{type}" do inspect_source([opening_line, ' private def some_method', ' implement 1', ' end', ' private def some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it "registers an offense for duplicate private self methods in #{type}" do inspect_source([opening_line, ' private def self.some_method', ' implement 1', ' end', ' private def self.some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it "doesn't register an offense for different private methods in #{type}" do inspect_source([opening_line, ' private def some_method', ' implement 1', ' end', ' private def any_method', ' implement 2', ' end', 'end']) expect(cop.offenses.empty?).to be(true) end it "registers an offense for duplicate protected methods in #{type}" do inspect_source([opening_line, ' protected def some_method', ' implement 1', ' end', ' protected def some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it "registers 2 offenses for pair of duplicate methods in #{type}" do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', ' def any_method', ' implement 1', ' end', ' def any_method', ' implement 2', ' end', 'end'], 'dups.rb') expect(cop.offenses.size).to eq(2) expect(cop.messages).to contain_exactly( 'Method `A#any_method` is defined at both dups.rb:8 and dups.rb:11.', 'Method `A#some_method` is defined at both dups.rb:2 and dups.rb:5.' ) end it 'registers an offense for a duplicate instance method in separate ' \ "#{type} blocks" do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', 'end', opening_line, ' def some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it 'registers an offense for a duplicate class method in separate ' \ "#{type} blocks" do inspect_source([opening_line, ' def self.some_method', ' implement 1', ' end', 'end', opening_line, ' def self.some_method', ' implement 2', ' end', 'end']) expect(cop.offenses.size).to eq(1) end it 'registers offense for a duplicate instance method in separate files' do inspect_source([opening_line, ' def some_method', ' implement 1', ' end', 'end'], 'first.rb') inspect_source([opening_line, ' def some_method', ' implement 2', ' end', 'end'], 'second.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Method `A#some_method` is defined at both ' \ 'first.rb:2 and second.rb:2.']) end it 'understands class << self' do inspect_source([opening_line, ' class << self', ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', ' end', 'end'], 'test.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Method `A.some_method` is defined at both test.rb:3 and test.rb:6.'] ) end it 'understands nested modules' do inspect_source(['module B', " #{opening_line}", ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', ' def self.another', ' end', ' def self.another', ' end', ' end', 'end'], 'test.rb') expect(cop.offenses.size).to eq(2) expect(cop.messages).to eq( ['Method `B::A#some_method` is defined at both test.rb:3 and ' \ 'test.rb:6.', 'Method `B::A.another` is defined at both test.rb:9 and test.rb:11.'] ) end it 'registers an offense when class << exp is used' do pending inspect_source([opening_line, ' class << blah', ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', ' end', 'end'], 'test.rb') expect(cop.offenses.empty?).to be(false) end it "registers an offense for duplicate alias in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} def some_method implement 1 end alias some_method any_method ^^^^^ Method `A#some_method` is defined at both example.rb:2 and example.rb:5. end RUBY end it "doesn't register an offense for non-duplicate alias in #{type}" do expect_no_offenses(<<-RUBY) #{opening_line} def some_method implement 1 end alias any_method some_method end RUBY end it "registers an offense for duplicate alias_method in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} def some_method implement 1 end alias_method :some_method, :any_method ^^^^^^^^^^^^ Method `A#some_method` is defined at both example.rb:2 and example.rb:5. end RUBY end it "accepts for non-duplicate alias_method in #{type}" do expect_no_offenses(<<-RUBY) #{opening_line} def some_method implement 1 end alias_method :any_method, :some_method end RUBY end it "doesn't register an offense for alias for gvar in #{type}" do expect_no_offenses(<<-RUBY) #{opening_line} alias $foo $bar end RUBY end it "registers an offense for duplicate attr_reader in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} def something end attr_reader :something ^^^^^^^^^^^ Method `A#something` is defined at both example.rb:2 and example.rb:4. end RUBY end it "registers an offense for duplicate attr_writer in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} def something=(right) end attr_writer :something ^^^^^^^^^^^ Method `A#something=` is defined at both example.rb:2 and example.rb:4. end RUBY end it "registers offenses for duplicate attr_accessor in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} attr_accessor :something def something ^^^ Method `A#something` is defined at both example.rb:2 and example.rb:4. end def something=(right) ^^^ Method `A#something=` is defined at both example.rb:2 and example.rb:6. end end RUBY end it "registers an offense for duplicate attr in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} def something end attr :something ^^^^ Method `A#something` is defined at both example.rb:2 and example.rb:4. end RUBY end it "registers offenses for duplicate assignable attr in #{type}" do expect_offense(<<-RUBY, 'example.rb') #{opening_line} attr :something, true def something ^^^ Method `A#something` is defined at both example.rb:2 and example.rb:4. end def something=(right) ^^^ Method `A#something=` is defined at both example.rb:2 and example.rb:6. end end RUBY end it "accepts for attr_reader and setter in #{type}" do expect_no_offenses(<<-RUBY) #{opening_line} def something=(right) end attr_reader :something end RUBY end it "accepts for attr_writer and getter in #{type}" do expect_no_offenses(<<-RUBY) #{opening_line} def something end attr_writer :something end RUBY end end include_examples('in scope', 'class', 'class A') include_examples('in scope', 'module', 'module A') include_examples('in scope', 'dynamic class', 'A = Class.new do') include_examples('in scope', 'dynamic module', 'A = Module.new do') include_examples('in scope', 'class_eval block', 'A.class_eval do') it 'registers an offense for duplicate methods at top level' do inspect_source([' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end'], 'toplevel.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Method `Object#some_method` is defined at both toplevel.rb:1 and ' \ 'toplevel.rb:4.'] ) end it 'understands class << A' do inspect_source(['class << A', ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', 'end'], 'test.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Method `A.some_method` is defined at both test.rb:2 and test.rb:5.'] ) end it 'handles class_eval with implicit receiver' do inspect_source(['module A', ' class_eval do', ' def some_method', ' implement 1', ' end', ' def some_method', ' implement 2', ' end', ' end', 'end'], 'test.rb') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Method `A#some_method` is defined at both test.rb:3 and test.rb:6.'] ) end it 'ignores method definitions in RSpec `describe` blocks' do expect_no_offenses(<<-RUBY.strip_indent) describe "something" do def some_method implement 1 end def some_method implement 2 end end RUBY end it 'ignores Class.new blocks which are assigned to local variables' do expect_no_offenses(<<-RUBY.strip_indent) a = Class.new do def foo end end b = Class.new do def foo end end RUBY end context 'when path is in the project root' do before do allow(Dir).to receive(:pwd).and_return('/path/to/project/root') allow_any_instance_of(Parser::Source::Buffer).to receive(:name) .and_return('/path/to/project/root/lib/foo.rb') end it 'adds a message with relative path' do expect_offense(<<-RUBY.strip_indent) def something end def something ^^^ Method `Object#something` is defined at both lib/foo.rb:1 and lib/foo.rb:3. end RUBY end end context 'when path is not in the project root' do before do allow(Dir).to receive(:pwd).and_return('/path/to/project/root') allow_any_instance_of(Parser::Source::Buffer).to receive(:name) .and_return('/no/project/root/foo.rb') end it 'adds a message with absolute path' do expect_offense(<<-RUBY.strip_indent) def something end def something ^^^ Method `Object#something` is defined at both /no/project/root/foo.rb:1 and /no/project/root/foo.rb:3. end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/duplicated_key_spec.rb000066400000000000000000000073651322072016200237350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::DuplicatedKey do subject(:cop) { described_class.new } context 'When there is a duplicated key in the hash literal' do let(:source) do "hash = { 'otherkey' => 'value', 'key' => 'value', 'key' => 'hi' }" end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Duplicated key in hash literal.') expect(cop.highlights).to eq ["'key'"] end end context 'When there are two duplicated keys in a hash' do let(:source) do "hash = { fruit: 'apple', veg: 'kale', veg: 'cuke', fruit: 'orange' }" end it 'registers two offenses' do inspect_source(source) expect(cop.offenses.size).to eq(2) expect(cop.messages).to eq(['Duplicated key in hash literal.'] * 2) expect(cop.highlights).to eq %w[veg fruit] end end context 'When a key is duplicated three times in a hash literal' do let(:source) do 'hash = { 1 => 2, 1 => 3, 1 => 4 }' end it 'registers two offenses' do inspect_source(source) expect(cop.offenses.size).to eq(2) expect(cop.messages).to eq(['Duplicated key in hash literal.'] * 2) expect(cop.highlights).to eq %w[1 1] end end context 'When there is no duplicated key in the hash' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) hash = { ['one', 'two'] => ['hello, bye'], ['two'] => ['yes, no'] } RUBY end end shared_examples :duplicated_literal_key do |key| it "registers an offense for duplicated `#{key}` hash keys" do inspect_source("hash = { #{key} => 1, #{key} => 4}") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Duplicated key in hash literal.') expect(cop.highlights).to eq [key] end end it_behaves_like :duplicated_literal_key, '!true' it_behaves_like :duplicated_literal_key, '"#{2}"' it_behaves_like :duplicated_literal_key, '(1)' it_behaves_like :duplicated_literal_key, '(false && true)' it_behaves_like :duplicated_literal_key, '(false <=> true)' it_behaves_like :duplicated_literal_key, '(false or true)' it_behaves_like :duplicated_literal_key, '[1, 2, 3]' it_behaves_like :duplicated_literal_key, '{ :a => 1, :b => 2 }' it_behaves_like :duplicated_literal_key, '{ a: 1, b: 2 }' it_behaves_like :duplicated_literal_key, '/./' it_behaves_like :duplicated_literal_key, '%r{abx}ixo' it_behaves_like :duplicated_literal_key, '1.0' it_behaves_like :duplicated_literal_key, '1' it_behaves_like :duplicated_literal_key, 'false' it_behaves_like :duplicated_literal_key, 'nil' it_behaves_like :duplicated_literal_key, "'str'" shared_examples :duplicated_non_literal_key do |key| it "does not register an offense for duplicated `#{key}` hash keys" do inspect_source("hash = { #{key} => 1, #{key} => 4}") expect(cop.offenses.empty?).to be(true) end end it_behaves_like :duplicated_non_literal_key, '"#{some_method_call}"' it_behaves_like :duplicated_non_literal_key, '(x && false)' it_behaves_like :duplicated_non_literal_key, '(x == false)' it_behaves_like :duplicated_non_literal_key, '(x or false)' it_behaves_like :duplicated_non_literal_key, '[some_method_call]' it_behaves_like :duplicated_non_literal_key, '{ :sym => some_method_call }' it_behaves_like :duplicated_non_literal_key, '{ some_method_call => :sym }' it_behaves_like :duplicated_non_literal_key, '/.#{some_method_call}/' it_behaves_like :duplicated_non_literal_key, '%r{abx#{foo}}ixo' it_behaves_like :duplicated_non_literal_key, 'some_method_call' it_behaves_like :duplicated_non_literal_key, 'some_method_call(x, y)' end rubocop-0.52.1/spec/rubocop/cop/lint/each_with_object_argument_spec.rb000066400000000000000000000025311322072016200261200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EachWithObjectArgument do subject(:cop) { described_class.new } it 'registers an offense for fixnum argument' do expect_offense(<<-RUBY.strip_indent) collection.each_with_object(0) { |e, a| a + e } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The argument to each_with_object can not be immutable. RUBY end it 'registers an offense for float argument' do expect_offense(<<-RUBY.strip_indent) collection.each_with_object(0.1) { |e, a| a + e } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The argument to each_with_object can not be immutable. RUBY end it 'registers an offense for bignum argument' do expect_offense(<<-RUBY.strip_indent) c.each_with_object(100000000000000000000) { |e, o| o + e } ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The argument to each_with_object can not be immutable. RUBY end it 'accepts a variable argument' do expect_no_offenses('collection.each_with_object(x) { |e, a| a.add(e) }') end it 'accepts two arguments' do # Two arguments would indicate that this is not Enumerable#each_with_object. expect_no_offenses('collection.each_with_object(1, 2) { |e, a| a.add(e) }') end it 'accepts a string argument' do expect_no_offenses("collection.each_with_object('') { |e, a| a << e.to_s }") end end rubocop-0.52.1/spec/rubocop/cop/lint/else_layout_spec.rb000066400000000000000000000022421322072016200232610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ElseLayout do subject(:cop) { described_class.new } it 'registers an offense for expr on same line as else' do expect_offense(<<-RUBY.strip_indent) if something test else ala ^^^ Odd `else` layout detected. Did you mean to use `elsif`? something test end RUBY end it 'accepts proper else' do expect_no_offenses(<<-RUBY.strip_indent) if something test else something test end RUBY end it 'accepts single-expr else regardless of layout' do expect_no_offenses(<<-RUBY.strip_indent) if something test else bala end RUBY end it 'can handle elsifs' do expect_offense(<<-RUBY.strip_indent) if something test elsif something bala else ala ^^^ Odd `else` layout detected. Did you mean to use `elsif`? something test end RUBY end it 'handles ternary ops' do expect_no_offenses('x ? a : b') end it 'handles modifier forms' do expect_no_offenses('x if something') end end rubocop-0.52.1/spec/rubocop/cop/lint/empty_ensure_spec.rb000066400000000000000000000014411322072016200234530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EmptyEnsure do subject(:cop) { described_class.new } it 'registers an offense for empty ensure' do expect_offense(<<-RUBY.strip_indent) begin something ensure ^^^^^^ Empty `ensure` block detected. end RUBY end it 'autocorrects for empty ensure' do corrected = autocorrect_source(<<-RUBY.strip_indent) begin something ensure end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) begin something end RUBY end it 'does not register an offense for non-empty ensure' do expect_no_offenses(<<-RUBY.strip_indent) begin something return ensure file.close end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/empty_expression_spec.rb000066400000000000000000000041751322072016200243600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EmptyExpression, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected = nil| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end end end end let(:message) { 'Avoid empty expressions.' } context 'when used as a standalone expression' do it_behaves_like 'code with offense', '()' context 'with nested empty expressions' do it_behaves_like 'code with offense', '(())' end end context 'when used in a condition' do it_behaves_like 'code with offense', 'if (); end' it_behaves_like 'code with offense', <<-RUBY.strip_indent if foo 1 elsif () 2 end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case () when :foo then 1 end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when () then 1 end RUBY it_behaves_like 'code with offense', '() ? true : false' it_behaves_like 'code with offense', 'foo ? () : bar' end context 'when used as a return value' do it_behaves_like 'code with offense', <<-RUBY.strip_indent def foo () end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent if foo () end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar then () end RUBY end context 'when used as an assignment' do it_behaves_like 'code with offense', 'foo = ()' end end rubocop-0.52.1/spec/rubocop/cop/lint/empty_interpolation_spec.rb000066400000000000000000000016611322072016200250450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EmptyInterpolation do subject(:cop) { described_class.new } it 'registers an offense for #{} in interpolation' do expect_offense(<<-'RUBY'.strip_indent) "this is the #{}" ^^^ Empty interpolation detected. RUBY end it 'registers an offense for #{ } in interpolation' do expect_offense(<<-'RUBY'.strip_indent) "this is the #{ }" ^^^^ Empty interpolation detected. RUBY end it 'accepts non-empty interpolation' do expect_no_offenses('"this is #{top} silly"') end it 'autocorrects empty interpolation' do new_source = autocorrect_source('"this is the #{}"') expect(new_source).to eq('"this is the "') end it 'autocorrects empty interpolation containing a space' do new_source = autocorrect_source('"this is the #{ }"') expect(new_source).to eq('"this is the "') end end rubocop-0.52.1/spec/rubocop/cop/lint/empty_when_spec.rb000066400000000000000000000056471322072016200231270ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EmptyWhen, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected = nil| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end let(:message) { 'Avoid `when` branches without a body.' } context 'when a `when` body is missing' do it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz # nothing end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz # nothing else 3 end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz then # nothing end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz then # nothing else 3 end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar 1 when :baz # nothing end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case foo when :bar 1 when :baz # nothing else 3 end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent case when :bar 1 when :baz # nothing else 3 end RUBY end context 'when a `when` body is present' do it_behaves_like 'code without offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz then 2 end RUBY it_behaves_like 'code without offense', <<-RUBY.strip_indent case foo when :bar then 1 when :baz then 2 else 3 end RUBY it_behaves_like 'code without offense', <<-RUBY.strip_indent case foo when :bar 1 when :baz 2 end RUBY it_behaves_like 'code without offense', <<-RUBY.strip_indent case foo when :bar 1 when :baz 2 else 3 end RUBY it_behaves_like 'code without offense', <<-RUBY.strip_indent case when :bar 1 when :baz 2 else 3 end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/end_alignment_spec.rb000066400000000000000000000314471322072016200235510ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EndAlignment, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'EnforcedStyleAlignWith' => 'keyword', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'class', 'Test', ' end' include_examples 'misaligned', '', 'module', 'Test', ' end' include_examples 'misaligned', '', 'if', 'test', ' end' include_examples 'misaligned', '', 'unless', 'test', ' end' include_examples 'misaligned', '', 'while', 'test', ' end' include_examples 'misaligned', '', 'until', 'test', ' end' include_examples 'misaligned', '', 'case', 'a when b', ' end' include_examples 'aligned', "\xef\xbb\xbfclass", 'Test', 'end' include_examples 'aligned', 'class', 'Test', 'end' include_examples 'aligned', 'module', 'Test', 'end' include_examples 'aligned', 'if', 'test', 'end' include_examples 'aligned', 'unless', 'test', 'end' include_examples 'aligned', 'while', 'test', 'end' include_examples 'aligned', 'until', 'test', 'end' include_examples 'aligned', 'case', 'a when b', 'end' include_examples 'misaligned', 'puts 1; ', 'class', 'Test', 'end' include_examples 'misaligned', 'puts 1; ', 'module', 'Test', 'end' include_examples 'misaligned', 'puts 1; ', 'if', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'unless', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'while', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'until', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'case', 'a when b', 'end' include_examples 'aligned', 'puts 1; class', 'Test', ' end' include_examples 'aligned', 'puts 1; module', 'Test', ' end' include_examples 'aligned', 'puts 1; if', 'Test', ' end' include_examples 'aligned', 'puts 1; unless', 'Test', ' end' include_examples 'aligned', 'puts 1; while', 'Test', ' end' include_examples 'aligned', 'puts 1; until', 'Test', ' end' include_examples 'aligned', 'puts 1; case', 'a when b', ' end' it 'can handle ternary if' do expect_no_offenses('a = cond ? x : y') end it 'can handle modifier if' do expect_no_offenses('a = x if cond') end context 'when EnforcedStyleAlignWith is start_of_line' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_line', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'class Test', '', ' end' include_examples 'misaligned', '', 'module Test', '', ' end' include_examples 'misaligned', '', 'if test', '', ' end' include_examples 'misaligned', '', 'unless test', '', ' end' include_examples 'misaligned', '', 'while test', '', ' end' include_examples 'misaligned', '', 'until test', '', ' end' include_examples 'misaligned', '', 'case a when b', '', ' end' include_examples 'aligned', 'puts 1; class', 'Test', 'end' include_examples 'aligned', 'puts 1; module', 'Test', 'end' include_examples 'aligned', 'puts 1; if', 'test', 'end' include_examples 'aligned', 'puts 1; unless', 'test', 'end' include_examples 'aligned', 'puts 1; while', 'test', 'end' include_examples 'aligned', 'puts 1; until', 'test', 'end' include_examples 'aligned', 'puts 1; case', 'a when b', 'end' include_examples 'misaligned', '', 'puts 1; class Test', '', ' end' include_examples 'misaligned', '', 'puts 1; module Test', '', ' end' include_examples 'misaligned', '', 'puts 1; if test', '', ' end' include_examples 'misaligned', '', 'puts 1; unless test', '', ' end' include_examples 'misaligned', '', 'puts 1; while test', '', ' end' include_examples 'misaligned', '', 'puts 1; until test', '', ' end' include_examples 'misaligned', '', 'puts 1; case a when b', '', ' end' end context 'when EnforcedStyleAlignWith is variable' do # same as 'EnforcedStyleAlignWith' => 'keyword', # as long as assignments or `case` are not involved let(:cop_config) do { 'EnforcedStyleAlignWith' => 'variable', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'class', 'Test', ' end' include_examples 'misaligned', '', 'module', 'Test', ' end' include_examples 'misaligned', '', 'if', 'test', ' end' include_examples 'misaligned', '', 'unless', 'test', ' end' include_examples 'misaligned', '', 'while', 'test', ' end' include_examples 'misaligned', '', 'until', 'test', ' end' include_examples 'misaligned', '', 'case', 'a when b', ' end' include_examples 'aligned', 'class', 'Test', 'end' include_examples 'aligned', 'module', 'Test', 'end' include_examples 'aligned', 'if', 'test', 'end' include_examples 'aligned', 'unless', 'test', 'end' include_examples 'aligned', 'while', 'test', 'end' include_examples 'aligned', 'until', 'test', 'end' include_examples 'aligned', 'case', 'a when b', 'end' include_examples 'misaligned', 'puts 1; ', 'class', 'Test', 'end' include_examples 'misaligned', 'puts 1; ', 'module', 'Test', 'end' include_examples 'misaligned', 'puts 1; ', 'if', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'unless', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'while', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'until', 'test', 'end' include_examples 'misaligned', 'puts 1; ', 'case', 'a when b', 'end' include_examples 'aligned', 'puts 1; class', 'Test', ' end' include_examples 'aligned', 'puts 1; module', 'Test', ' end' include_examples 'aligned', 'puts 1; if', 'Test', ' end' include_examples 'aligned', 'puts 1; unless', 'Test', ' end' include_examples 'aligned', 'puts 1; while', 'Test', ' end' include_examples 'aligned', 'puts 1; until', 'Test', ' end' include_examples 'aligned', 'puts 1; case', 'a when b', ' end' end context 'correct + opposite' do let(:source) do <<-RUBY.strip_indent x = if a a1 end y = if b b1 end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages.first) .to eq('`end` at 6, 0 is not aligned with `if` at 4, 4.') expect(cop.highlights.first).to eq('end') expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) x = if a a1 end y = if b b1 end RUBY end end context 'when end is preceded by something else than whitespace' do let(:source) do <<-RUBY.strip_indent module A puts a end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages.first) .to eq('`end` at 2, 7 is not aligned with `module` at 1, 0.') expect(cop.highlights.first).to eq('end') end it "doesn't auto-correct" do expect(autocorrect_source(source)) .to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'case as argument' do context 'when EnforcedStyleAlignWith is keyword' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'keyword', 'AutoCorrect' => true } end include_examples 'aligned', 'test case', 'a when b', ' end' include_examples 'misaligned', 'test ', 'case', 'a when b', 'end' end context 'when EnforcedStyleAlignWith is variable' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'variable', 'AutoCorrect' => true } end include_examples 'aligned', 'test case', 'a when b', 'end' include_examples 'misaligned', '', 'test case', 'a when b', ' end' end context 'when EnforcedStyleAlignWith is start_of_line' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_line', 'AutoCorrect' => true } end include_examples 'aligned', 'test case a when b', '', 'end' include_examples 'misaligned', '', 'test case a when b', '', ' end' end end context 'regarding assignment' do context 'when EnforcedStyleAlignWith is keyword' do include_examples 'misaligned', 'var = ', 'if', 'test', 'end' include_examples 'misaligned', 'var = ', 'unless', 'test', 'end' include_examples 'misaligned', 'var = ', 'while', 'test', 'end' include_examples 'misaligned', 'var = ', 'until', 'test', 'end' include_examples 'misaligned', 'var = ', 'case', 'a when b', 'end' include_examples 'aligned', 'var = if', 'test', ' end' include_examples 'aligned', 'var = unless', 'test', ' end' include_examples 'aligned', 'var = while', 'test', ' end' include_examples 'aligned', 'var = until', 'test', ' end' include_examples 'aligned', 'var = case', 'a when b', ' end' end context 'when EnforcedStyleAlignWith is variable' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'variable', 'AutoCorrect' => true } end include_examples 'aligned', 'var = if', 'test', 'end' include_examples 'aligned', 'var = unless', 'test', 'end' include_examples 'aligned', 'var = while', 'test', 'end' include_examples 'aligned', 'var = until', 'test', 'end' include_examples 'aligned', 'var = until', 'test', 'end.ab.join("")' include_examples 'aligned', 'var = until', 'test', 'end.ab.tap {}' include_examples 'aligned', 'var = case', 'a when b', 'end' include_examples 'aligned', "var =\n if", 'test', ' end' include_examples 'misaligned', '', 'var = if', 'test', ' end' include_examples 'misaligned', '', 'var = unless', 'test', ' end' include_examples 'misaligned', '', 'var = while', 'test', ' end' include_examples 'misaligned', '', 'var = until', 'test', ' end' include_examples 'misaligned', '', 'var = until', 'test', ' end.j' include_examples 'misaligned', '', 'var = case', 'a when b', ' end' include_examples 'aligned', '@var = if', 'test', 'end' include_examples 'aligned', '@@var = if', 'test', 'end' include_examples 'aligned', '$var = if', 'test', 'end' include_examples 'aligned', 'CNST = if', 'test', 'end' include_examples 'aligned', 'a, b = if', 'test', 'end' include_examples 'aligned', 'var ||= if', 'test', 'end' include_examples 'aligned', 'var &&= if', 'test', 'end' include_examples 'aligned', 'var += if', 'test', 'end' include_examples 'aligned', 'h[k] = if', 'test', 'end' include_examples 'aligned', 'h.k = if', 'test', 'end' include_examples 'misaligned', '', '@var = if', 'test', ' end' include_examples 'misaligned', '', '@@var = if', 'test', ' end' include_examples 'misaligned', '', '$var = if', 'test', ' end' include_examples 'misaligned', '', 'CNST = if', 'test', ' end' include_examples 'misaligned', '', 'a, b = if', 'test', ' end' include_examples 'misaligned', '', 'var ||= if', 'test', ' end' include_examples 'misaligned', '', 'var &&= if', 'test', ' end' include_examples 'misaligned', '', 'var += if', 'test', ' end' include_examples 'misaligned', '', 'h[k] = if', 'test', ' end' include_examples 'misaligned', '', 'h.k = if', 'test', ' end' end end context 'when EnforcedStyleAlignWith is start_of_line' do let(:cop_config) do { 'EnforcedStyleAlignWith' => 'start_of_line', 'AutoCorrect' => true } end include_examples 'misaligned', '', 'var = if test', '', ' end' include_examples 'misaligned', '', 'var = unless test', '', ' end' include_examples 'misaligned', '', 'var = while test', '', ' end' include_examples 'misaligned', '', 'var = until test', '', ' end' include_examples 'misaligned', '', 'var = case a when b', '', ' end' include_examples 'aligned', 'var = if', 'test', 'end' include_examples 'aligned', 'var = unless', 'test', 'end' include_examples 'aligned', 'var = while', 'test', 'end' include_examples 'aligned', 'var = until', 'test', 'end' include_examples 'aligned', 'var = case', 'a when b', 'end' end end rubocop-0.52.1/spec/rubocop/cop/lint/end_in_method_spec.rb000066400000000000000000000012221322072016200235250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EndInMethod do subject(:cop) { described_class.new } it 'reports an offense for def with an RUBY inside' do src = <<-RUBY.strip_indent def test END { something } end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs with an RUBY inside' do src = <<-RUBY.strip_indent def self.test END { something } end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts END outside of def(s)' do expect_no_offenses('END { something }') end end rubocop-0.52.1/spec/rubocop/cop/lint/ensure_return_spec.rb000066400000000000000000000014521322072016200236360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::EnsureReturn do subject(:cop) { described_class.new } it 'registers an offense for return in ensure' do expect_offense(<<-RUBY.strip_indent) begin something ensure file.close return ^^^^^^ Do not return from an `ensure` block. end RUBY end it 'does not register an offense for return outside ensure' do expect_no_offenses(<<-RUBY.strip_indent) begin something return ensure file.close end RUBY end it 'does not check when ensure block has no body' do expect do inspect_source(<<-RUBY.strip_indent) begin something ensure end RUBY end.not_to raise_exception end end rubocop-0.52.1/spec/rubocop/cop/lint/float_out_of_range_spec.rb000066400000000000000000000016761322072016200246020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::FloatOutOfRange do subject(:cop) { described_class.new } it 'does not register an offense for 0.0' do expect_no_offenses('0.0') end it 'does not register an offense for tiny little itty bitty floats' do expect_no_offenses('1.1e-100') end it 'does not register an offense for respectably sized floats' do expect_no_offenses('55.7e89') end context 'on whopping big floats which tip the scales' do let(:source) { '9.9999e999' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) 9.9999e999 ^^^^^^^^^^ Float out of range. RUBY end end context 'on floats so close to zero that nobody can tell the difference' do let(:source) { '1.0e-400' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) 1.0e-400 ^^^^^^^^ Float out of range. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/format_parameter_mismatch_spec.rb000066400000000000000000000247311322072016200261600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::FormatParameterMismatch do subject(:cop) { described_class.new } shared_examples 'variables' do |variable| it 'does not register an offense for % called on a variable' do inspect_source(<<-RUBY.strip_indent) #{variable} = '%s' #{variable} % [foo] RUBY expect(cop.messages.empty?).to be(true) end it 'does not register an offense for format called on a variable' do inspect_source(<<-RUBY.strip_indent) #{variable} = '%s' format(#{variable}, foo) RUBY expect(cop.messages.empty?).to be(true) end it 'does not register an offense for format called on a variable' do inspect_source(<<-RUBY.strip_indent) #{variable} = '%s' sprintf(#{variable}, foo) RUBY expect(cop.messages.empty?).to be(true) end end it_behaves_like 'variables', 'CONST' it_behaves_like 'variables', 'var' it_behaves_like 'variables', '@var' it_behaves_like 'variables', '@@var' it_behaves_like 'variables', '$var' it 'registers an offense when calling Kernel.format ' \ 'and the fields do not match' do inspect_source('Kernel.format("%s %s", 1)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (1) to `format` doesn't match the number of " \ 'fields (2).'] ) end it 'registers an offense when calling Kernel.sprintf ' \ 'and the fields do not match' do inspect_source('Kernel.sprintf("%s %s", 1)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (1) to `sprintf` doesn't match the number of " \ 'fields (2).'] ) end it 'registers an offense when there are less arguments than expected' do inspect_source('format("%s %s", 1)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (1) to `format` doesn't match the number of " \ 'fields (2).'] ) end it 'registers an offense when there are more arguments than expected' do inspect_source('format("%s %s", 1, 2, 3)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (3) to `format` doesn't match the number of " \ 'fields (2).'] ) end it 'does not register an offense when arguments and fields match' do expect_no_offenses('format("%s %d %i", 1, 2, 3)') end it 'correctly ignores double percent' do expect_no_offenses("format('%s %s %% %s %%%% %%%%%% %%5B', 1, 2, 3)") end it 'constants do not register offenses' do expect_no_offenses('format(A_CONST, 1, 2, 3)') end it 'registers offense with sprintf' do inspect_source('sprintf("%s %s", 1, 2, 3)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (3) to `sprintf` doesn't match the number of " \ 'fields (2).'] ) end it 'correctly parses different sprintf formats' do expect_no_offenses('sprintf("%020x%+g:% g %%%#20.8x %#.0e", 1, 2, 3, 4, 5)') end it 'registers an offense for String#%' do inspect_source('"%s %s" % [1, 2, 3]') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ["Number of arguments (3) to `String#%` doesn't match the number of " \ 'fields (2).'] ) end it 'does not register offense for `String#%` when arguments, fields match' do expect_no_offenses('"%s %s" % [1, 2]') end it 'does not register an offense when single argument is a hash' do expect_no_offenses('puts "%s" % {"a" => 1}') end it 'does not register an offense when single argument is not an array' do expect_no_offenses('puts "%s" % CONST') end context 'when splat argument is present' do it 'does not register an offense when args count is less than expected' do expect_no_offenses('sprintf("%s, %s, %s", 1, *arr)') end it 'does register an offense when args count is more than expected' do inspect_source('puts "%s, %s, %s" % [1, 2, 3, 4, *arr]') expect(cop.offenses.empty?).to be(false) inspect_source('format("%s, %s, %s", 1, 2, 3, 4, *arr)') expect(cop.offenses.empty?).to be(false) inspect_source('sprintf("%s, %s, %s", 1, 2, 3, 4, *arr)') expect(cop.offenses.empty?).to be(false) end end context 'when multiple arguments are called for' do context 'and a single variable argument is passed' do it 'does not register an offense' do # the variable could evaluate to an array expect_no_offenses('puts "%s %s" % var') end end context 'and a single send node is passed' do it 'does not register an offense' do expect_no_offenses('puts "%s %s" % ("ab".chars)') end end end context 'when format is not a string literal' do it 'does not register an offense' do expect_no_offenses('puts str % [1, 2]') end end # Regression: https://github.com/bbatsov/rubocop/issues/3869 context 'when passed an empty array' do it 'does not register an offense' do expect_no_offenses("'%' % []") end end it 'ignores percent right next to format string' do expect_no_offenses('format("%0.1f%% percent", 22.5)') end it 'accepts an extra argument for dynamic width' do expect_no_offenses('format("%*d", max_width, id)') end it 'registers an offense if extra argument for dynamic width not given' do inspect_source('format("%*d", id)') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(["Number of arguments (1) to `format` doesn't " \ 'match the number of fields (2).']) end it 'accepts an extra arg for dynamic width with other preceding flags' do expect_no_offenses('format("%0*x", max_width, id)') end it 'accepts an extra arg for dynamic width with other following flags' do expect_no_offenses('format("%*0x", max_width, id)') end it 'does not register an offense argument is the result of a message send' do expect_no_offenses('format("%s", "a b c".gsub(" ", "_"))') end it 'does not register an offense when using named parameters' do expect_no_offenses('"foo %{bar} baz" % { bar: 42 }') end it 'identifies correctly digits for spacing in format' do expect_no_offenses('"duration: %10.fms" % 42') end it 'finds faults even when the string looks like a HEREDOC' do # heredocs are ignored at the moment inspect_source('format("<< %s bleh", 1, 2)') expect(cop.offenses.size).to eq(1) end it 'does not register an offense for sprintf with splat argument' do expect_no_offenses('sprintf("%d%d", *test)') end it 'does not register an offense for format with splat argument' do expect_no_offenses('format("%d%d", *test)') end context 'on format with %{} interpolations' do context 'and 1 argument' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) params = { y: '2015', m: '01', d: '01' } puts format('%{y}-%{m}-%{d}', params) RUBY end end context 'and multiple arguments' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) params = { y: '2015', m: '01', d: '01' } puts format('%{y}-%{m}-%{d}', 2015, 1, 1) ^^^^^^ Number of arguments (3) to `format` doesn't match the number of fields (1). RUBY end end end context 'on format with %<> interpolations' do context 'and 1 argument' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) params = { y: '2015', m: '01', d: '01' } puts format('%d-%d-%d', params) RUBY end end context 'and multiple arguments' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) params = { y: '2015', m: '01', d: '01' } puts format('%d-%d-%d', 2015, 1, 1) ^^^^^^ Number of arguments (3) to `format` doesn't match the number of fields (1). RUBY end end end context 'with wildcard' do it 'does not register an offence for width' do expect_no_offenses('format("%*d", 10, 3)') end it 'does not register an offence for precision' do expect_no_offenses('format("%.*f", 2, 20.19)') end it 'does not register an offense for width and precision' do expect_no_offenses('format("%*.*f", 10, 3, 20.19)') end it 'does not register an offense for multiple wildcards' do expect_no_offenses('format("%*.*f %*.*f", 10, 2, 20.19, 5, 1, 11.22)') end end it 'finds the correct number of fields' do expect(''.scan(described_class::FIELD_REGEX).size) .to eq(0) expect('%s'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%s %s'.scan(described_class::FIELD_REGEX).size) .to eq(2) expect('%s %s %%'.scan(described_class::FIELD_REGEX).size) .to eq(3) expect('%s %s %%'.scan(described_class::FIELD_REGEX).size) .to eq(3) expect('% d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%+d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%+o'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%#o'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%.0e'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%#.0e'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('% 020d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%20d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%+20d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%020d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%+020d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('% 020d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%-20d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%-+20d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%- 20d'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%020x'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%#20.8x'.scan(described_class::FIELD_REGEX).size) .to eq(1) expect('%+g:% g:%-g'.scan(described_class::FIELD_REGEX).size) .to eq(3) expect('%+-d'.scan(described_class::FIELD_REGEX).size) # multiple flags .to eq(1) end end rubocop-0.52.1/spec/rubocop/cop/lint/handle_exceptions_spec.rb000066400000000000000000000010631322072016200244300ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::HandleExceptions do subject(:cop) { described_class.new } it 'registers an offense for empty rescue block' do expect_offense(<<-RUBY.strip_indent) begin something rescue ^^^^^^ Do not suppress exceptions. #do nothing end RUBY end it 'does not register an offense for rescue with body' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue file.close end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/implicit_string_concatenation_spec.rb000066400000000000000000000057701322072016200270520ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ImplicitStringConcatenation do subject(:cop) { described_class.new } context 'on a single string literal' do it 'does not register an offense' do expect_no_offenses('abc') end end context 'on adjacent string literals on the same line' do let(:source) { 'class A; "abc" "def"; end' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Combine "abc" and "def" into a single ' \ 'string literal, rather than using ' \ 'implicit string concatenation.']) expect(cop.highlights).to eq(['"abc" "def"']) end end context 'on adjacent string literals on different lines' do it 'does not register an offense' do expect_no_offenses(<<-'RUBY'.strip_indent) array = [ 'abc'\ 'def' ] RUBY end end context 'when the string literals contain newlines' do let(:source) { "def method; 'ab\nc' 'de\nf'; end" } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Combine "ab\nc" and "de\nf" into a ' \ 'single string literal, rather than using ' \ 'implicit string concatenation.']) expect(cop.highlights).to eq(["'ab\nc' 'de\nf'"]) end end context 'on a string with interpolations' do it 'does register an offense' do expect_no_offenses("array = [\"abc\#{something}def\#{something_else}\"]") end end context 'when inside an array' do let(:source) { 'array = ["abc" "def"]' } it 'notes that the strings could be separated by a comma instead' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Combine "abc" and "def" into a single ' \ 'string literal, rather than using ' \ 'implicit string concatenation. Or, if they' \ ' were intended to be separate array ' \ 'elements, separate them with a comma.']) expect(cop.highlights).to eq(['"abc" "def"']) end end context "when in a method call's argument list" do let(:source) { 'method("abc" "def")' } it 'notes that the strings could be separated by a comma instead' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Combine "abc" and "def" into a single ' \ 'string literal, rather than using ' \ 'implicit string concatenation. Or, if they' \ ' were intended to be separate method ' \ 'arguments, separate them with a comma.']) expect(cop.highlights).to eq(['"abc" "def"']) end end end rubocop-0.52.1/spec/rubocop/cop/lint/ineffective_access_modifier_spec.rb000066400000000000000000000040501322072016200264210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::IneffectiveAccessModifier do subject(:cop) { described_class.new } context 'when `private` is applied to a class method' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class C private def self.method ^^^ `private` (on line 2) does not make singleton methods private. Use `private_class_method` or `private` inside a `class << self` block instead. puts "hi" end end RUBY end end context 'when `protected` is applied to a class method' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class C protected def self.method ^^^ `protected` (on line 2) does not make singleton methods protected. Use `protected` inside a `class << self` block instead. puts "hi" end end RUBY end end context 'when `private_class_method` is used' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) class C private def self.method puts "hi" end private_class_method :method end RUBY end end context 'when a `class << self` block is used' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) class C private class << self def self.method puts "hi" end end end RUBY end end context 'when there is an intervening instance method' do it 'still registers an offense' do expect_offense(<<-RUBY.strip_indent) class C private def instance_method end def self.method ^^^ `private` (on line 3) does not make singleton methods private. Use `private_class_method` or `private` inside a `class << self` block instead. puts "hi" end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/inherit_exception_spec.rb000066400000000000000000000024461322072016200244620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::InheritException, :config do subject(:cop) { described_class.new(config) } shared_examples 'registers an offense' do |message| it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end end shared_examples 'auto-correct' do |expected| it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(expected) end end context 'when class inherits from `Exception`' do let(:source) do 'class C < Exception; end' end context 'with enforced style set to `runtime_error`' do let(:cop_config) { { 'EnforcedStyle' => 'runtime_error' } } it_behaves_like 'registers an offense', 'Inherit from `RuntimeError` instead of `Exception`.' it_behaves_like 'auto-correct', 'class C < RuntimeError; end' end context 'with enforced style set to `standard_error`' do let(:cop_config) { { 'EnforcedStyle' => 'standard_error' } } it_behaves_like 'registers an offense', 'Inherit from `StandardError` instead of `Exception`.' it_behaves_like 'auto-correct', 'class C < StandardError; end' end end end rubocop-0.52.1/spec/rubocop/cop/lint/interpolation_check_spec.rb000066400000000000000000000020201322072016200247520ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::InterpolationCheck do subject(:cop) { described_class.new } it 'registers an offense for interpolation in single quoted string' do expect_offense(<<-'RUBY'.strip_indent) 'foo #{bar}' ^^^^^^^^^^^^ Interpolation in single quoted string detected. Use double quoted strings if you need interpolation. RUBY end it 'does not register an offense for properly interpolation strings' do expect_no_offenses(<<-'RUBY'.strip_indent) hello = "foo #{bar}" RUBY end it 'does not register an offense for interpolation in nested strings' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = "bar '#{baz}' qux" RUBY end it 'does not crash for \xff' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = "\xff" RUBY end it 'does not register an offense for escaped crab claws in dstr' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = "alpha #{variable} beta \#{gamma}\" delta" RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/literal_as_condition_spec.rb000066400000000000000000000106771322072016200251340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::LiteralAsCondition do subject(:cop) { described_class.new } %w(1 2.0 [1] {} :sym :"#{a}").each do |lit| it "registers an offense for literal #{lit} in if" do inspect_source(<<-RUBY.strip_indent) if #{lit} top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in while" do inspect_source(<<-RUBY.strip_indent) while #{lit} top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in post-loop while" do inspect_source(<<-RUBY.strip_indent) begin top end while(#{lit}) RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in until" do inspect_source(<<-RUBY.strip_indent) until #{lit} top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in post-loop until" do inspect_source(<<-RUBY.strip_indent) begin top end until #{lit} RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in case" do inspect_source(<<-RUBY.strip_indent) case #{lit} when x then top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in a when " \ 'of a case without anything after case keyword' do inspect_source(<<-RUBY.strip_indent) case when #{lit} then top end RUBY expect(cop.offenses.size).to eq(1) end it "accepts literal #{lit} in a when of a case with " \ 'something after case keyword' do inspect_source(<<-RUBY.strip_indent) case x when #{lit} then top end RUBY expect(cop.offenses.empty?).to be(true) end it "registers an offense for literal #{lit} in &&" do inspect_source(<<-RUBY.strip_indent) if x && #{lit} top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in complex cond" do inspect_source(<<-RUBY.strip_indent) if x && !(a && #{lit}) && y && z top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in !" do inspect_source(<<-RUBY.strip_indent) if !#{lit} top end RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for literal #{lit} in complex !" do inspect_source(<<-RUBY.strip_indent) if !(x && (y && #{lit})) top end RUBY expect(cop.offenses.size).to eq(1) end it "accepts literal #{lit} if it's not an and/or operand" do inspect_source(<<-RUBY.strip_indent) if test(#{lit}) top end RUBY expect(cop.offenses.empty?).to be(true) end it "accepts literal #{lit} in non-toplevel and/or" do inspect_source(<<-RUBY.strip_indent) if (a || #{lit}).something top end RUBY expect(cop.offenses.empty?).to be(true) end it "registers an offense for `!#{lit}`" do inspect_source(<<-RUBY.strip_indent) !#{lit} RUBY expect(cop.offenses.size).to eq(1) end it "registers an offense for `not #{lit}`" do inspect_source(<<-RUBY.strip_indent) not(#{lit}) RUBY expect(cop.offenses.size).to eq(1) end end it 'accepts array literal in case, if it has non-literal elements' do expect_no_offenses(<<-RUBY.strip_indent) case [1, 2, x] when [1, 2, 5] then top end RUBY end it 'accepts array literal in case, if it has nested non-literal element' do expect_no_offenses(<<-RUBY.strip_indent) case [1, 2, [x, 1]] when [1, 2, 5] then top end RUBY end it 'registers an offense for case with a primitive array condition' do expect_offense(<<-RUBY.strip_indent) case [1, 2, [3, 4]] ^^^^^^^^^^^^^^ Literal `[1, 2, [3, 4]]` appeared as a condition. when [1, 2, 5] then top end RUBY end it 'accepts dstr literal in case' do expect_no_offenses(<<-'RUBY'.strip_indent) case "#{x}" when [1, 2, 5] then top end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb000066400000000000000000000127741322072016200260400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::LiteralInInterpolation do subject(:cop) { described_class.new } it 'accepts empty interpolation' do expect_no_offenses('"this is #{a} silly"') end it 'accepts interpolation of xstr' do expect_no_offenses('"this is #{`a`} silly"') end it 'accepts interpolation of irange where endpoints are not literals' do expect_no_offenses('"this is an irange: #{var1..var2}"') end it 'accepts interpolation of erange where endpoints are not literals' do expect_no_offenses('"this is an erange: #{var1...var2}"') end shared_examples 'literal interpolation' do |literal, expected = literal| it "registers an offense for #{literal} in interpolation" do inspect_source(%("this is the \#{#{literal}}")) expect(cop.offenses.size).to eq(1) end it "should have #{literal} as the message highlight" do inspect_source(%("this is the \#{#{literal}}")) expect(cop.highlights).to eq([literal.to_s]) end it "removes interpolation around #{literal}" do corrected = autocorrect_source(%("this is the \#{#{literal}}")) expect(corrected).to eq(%("this is the #{expected}")) end it "removes interpolation around #{literal} when there is more text" do corrected = autocorrect_source(%("this is the \#{#{literal}} literally")) expect(corrected).to eq(%("this is the #{expected} literally")) end it "removes interpolation around multiple #{literal}" do corrected = autocorrect_source(%("some \#{#{literal}} with \#{#{literal}} too")) expect(corrected).to eq(%("some #{expected} with #{expected} too")) end context 'when there is non-literal and literal interpolation' do context 'when literal interpolation is before non-literal' do it 'only remove interpolation around literal' do corrected = autocorrect_source(%("this is \#{#{literal}} with \#{a} now")) expect(corrected).to eq(%("this is #{expected} with \#{a} now")) end end context 'when literal interpolation is after non-literal' do it 'only remove interpolation around literal' do corrected = autocorrect_source(%("this is \#{a} with \#{#{literal}} now")) expect(corrected).to eq(%("this is \#{a} with #{expected} now")) end end end it "registers an offense only for final #{literal} in interpolation" do inspect_source(%("this is the \#{#{literal};#{literal}}")) expect(cop.offenses.size).to eq(1) end end it_behaves_like('literal interpolation', 1) it_behaves_like('literal interpolation', -1) it_behaves_like('literal interpolation', 1_123) it_behaves_like('literal interpolation', 123_456_789_123_456_789) it_behaves_like('literal interpolation', 1.2e-3) it_behaves_like('literal interpolation', 0xaabb) it_behaves_like('literal interpolation', 0o377) it_behaves_like('literal interpolation', 2.0) it_behaves_like('literal interpolation', '[]', '[]') it_behaves_like('literal interpolation', '["a", "b"]', '[\"a\", \"b\"]') it_behaves_like('literal interpolation', '{"a" => "b"}', '{\"a\" => \"b\"}') it_behaves_like('literal interpolation', true) it_behaves_like('literal interpolation', false) it_behaves_like('literal interpolation', 'nil') it_behaves_like('literal interpolation', ':symbol', 'symbol') it_behaves_like('literal interpolation', ':"symbol"', 'symbol') it_behaves_like('literal interpolation', 1..2) it_behaves_like('literal interpolation', 1...2) it 'handles nested interpolations when auto-correction' do corrected = autocorrect_source(%("this is \#{"\#{1}"} silly")) # next iteration fixes this expect(corrected).to eq %("this is \#{"1"} silly") end shared_examples 'special keywords' do |keyword| it "accepts strings like #{keyword}" do inspect_source(%("this is \#{#{keyword}} silly")) expect(cop.offenses.empty?).to be(true) end it "does not try to autocorrect strings like #{keyword}" do corrected = autocorrect_source(%("this is the \#{#{keyword}} silly")) expect(corrected).to eq(%("this is the \#{#{keyword}} silly")) end it "registers an offense for interpolation after #{keyword}" do inspect_source(%("this is the \#{#{keyword}} \#{1}")) expect(cop.offenses.size).to eq(1) end it "auto-corrects literal interpolation after #{keyword}" do corrected = autocorrect_source(%("this is the \#{#{keyword}} \#{1}")) expect(corrected).to eq(%("this is the \#{#{keyword}} 1")) end end it_behaves_like('special keywords', '__FILE__') it_behaves_like('special keywords', '__LINE__') it_behaves_like('special keywords', '__RUBY__') it_behaves_like('special keywords', '__ENCODING__') shared_examples 'non-special string literal interpolation' do |string| it "registers an offense for #{string}" do inspect_source(%("this is the \#{#{string}}")) expect(cop.offenses.size).to eq(1) end it "should have #{string} in the message highlight" do inspect_source(%("this is the \#{#{string}}")) expect(cop.highlights).to eq([string]) end it "should remove the interpolation and quotes around #{string}" do corrected = autocorrect_source(%("this is the \#{#{string}}")) expect(corrected).to eq(%("this is the #{string.gsub(/'|"/, '')}")) end end it_behaves_like('non-special string literal interpolation', %('foo')) it_behaves_like('non-special string literal interpolation', %("foo")) end rubocop-0.52.1/spec/rubocop/cop/lint/loop_spec.rb000066400000000000000000000014701322072016200217070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::Loop do subject(:cop) { described_class.new } it 'registers an offense for begin/end/while' do expect_offense(<<-RUBY.strip_indent) begin something; top; end while test ^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`). RUBY end it 'registers an offense for begin/end/until' do expect_offense(<<-RUBY.strip_indent) begin something; top; end until test ^^^^^ Use `Kernel#loop` with `break` rather than `begin/end/until`(or `while`). RUBY end it 'accepts normal while' do expect_no_offenses('while test; one; two; end') end it 'accepts normal until' do expect_no_offenses('until test; one; two; end') end end rubocop-0.52.1/spec/rubocop/cop/lint/missing_cop_enable_directive_spec.rb000066400000000000000000000040241322072016200266120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::MissingCopEnableDirective, :config do subject(:cop) { described_class.new(config) } context 'when the maximum range size is infinite' do let(:cop_config) { { 'MaximumRangeSize' => Float::INFINITY } } it 'registers an offense when a cop is disabled and never re-enabled' do expect_offense(<<-RUBY.strip_indent) # rubocop:disable Layout/SpaceAroundOperators ^ Re-enable Layout/SpaceAroundOperators cop with `# rubocop:enable` after disabling it. x = 0 # Some other code RUBY end it 'does not register an offense when the disable cop is re-enabled' do expect_no_offenses(<<-RUBY.strip_indent) # rubocop:disable Layout/SpaceAroundOperators x = 0 # rubocop:enable Layout/SpaceAroundOperators # Some other code RUBY end end context 'when the maximum range size is finite' do let(:cop_config) { { 'MaximumRangeSize' => 2 } } it 'registers an offense when a cop is disabled for too many lines' do expect_offense(<<-RUBY.strip_indent) # rubocop:disable Layout/SpaceAroundOperators ^ Re-enable Layout/SpaceAroundOperators cop within 2 lines after disabling it. x = 0 y = 1 # Some other code # rubocop:enable Layout/SpaceAroundOperators RUBY end it 'registers an offense when a cop is disabled and never re-enabled' do expect_offense(<<-RUBY.strip_indent) # rubocop:disable Layout/SpaceAroundOperators ^ Re-enable Layout/SpaceAroundOperators cop within 2 lines after disabling it. x = 0 # Some other code RUBY end it 'does not register an offense when the disable cop is re-enabled ' \ 'within the limit' do expect_no_offenses(<<-RUBY.strip_indent) # rubocop:disable Layout/SpaceAroundOperators x = 0 y = 1 # rubocop:enable Layout/SpaceAroundOperators # Some other code RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/multiple_compare_spec.rb000066400000000000000000000020221322072016200242710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::MultipleCompare do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples 'Check to use two comparison operator' do |op1, op2| bad_source = "x #{op1} y #{op2} z" good_source = "x #{op1} y && y #{op2} z" it "registers an offense for #{bad_source}" do inspect_source(bad_source) expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Use the `&&` operator to compare multiple values.']) end it 'autocorrects' do new_source = autocorrect_source(bad_source) expect(new_source).to eq(good_source) end it "accepts for #{good_source}" do inspect_source(good_source) expect(cop.offenses.empty?).to be(true) end end %w[< > <= >=].repeated_permutation(2) do |op1, op2| include_examples 'Check to use two comparison operator', op1, op2 end it 'accepts to use one compare operator' do expect_no_offenses('x < 1') end end rubocop-0.52.1/spec/rubocop/cop/lint/nested_method_definition_spec.rb000066400000000000000000000110441322072016200257660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::NestedMethodDefinition do subject(:cop) { described_class.new } it 'registers an offense for a nested method definition' do expect_offense(<<-RUBY.strip_indent) def x; def y; end; end ^^^^^^^^^^ Method definitions must not be nested. Use `lambda` instead. RUBY end it 'registers an offense for a nested singleton method definition' do inspect_source(<<-RUBY.strip_indent) class Foo end foo = Foo.new def foo.bar def baz end end RUBY expect(cop.offenses.size).to eq(1) end it 'registers an offense for a nested method definition inside lambda' do expect_offense(<<-RUBY.strip_indent) def foo bar = -> { def baz; puts; end } ^^^^^^^^^^^^^^^^^^ Method definitions must not be nested. Use `lambda` instead. end RUBY end it 'registers an offense for a nested class method definition' do inspect_source(<<-RUBY.strip_indent) class Foo def self.x def self.y end end end RUBY expect(cop.offenses.size).to eq(1) end it 'does not register an offense for a lambda definition inside method' do expect_no_offenses(<<-RUBY.strip_indent) def foo bar = -> { puts } bar.call end RUBY end it 'does not register offense for nested definition inside instance_eval' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def x(obj) obj.instance_eval do def y end end end end RUBY end it 'does not register offense for nested definition inside instance_exec' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def x(obj) obj.instance_exec do def y end end end end RUBY end it 'does not register offense for definition of method on local var' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def x(obj) def obj.y end end end RUBY end it 'does not register offense for nested definition inside class_eval' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def x(klass) klass.class_eval do def y end end end end RUBY end it 'does not register offense for nested definition inside class_exec' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def x(klass) klass.class_exec do def y end end end end RUBY end it 'does not register offense for nested definition inside module_eval' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.define(mod) mod.module_eval do def y end end end end RUBY end it 'does not register offense for nested definition inside module_exec' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.define(mod) mod.module_exec do def y end end end end RUBY end it 'does not register offense for nested definition inside class shovel' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def bar class << self def baz end end end end RUBY end it 'does not register offense for nested definition inside Class.new' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.define Class.new(S) do def y end end end end class Foo def self.define Class.new do def y end end end end RUBY end it 'does not register offense for nested definition inside Module.new' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.define Module.new do def y end end end end RUBY end it 'does not register offense for nested definition inside Struct.new' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.define Struct.new(:name) do def y end end end end class Foo def self.define Struct.new do def y end end end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/nested_percent_literal_spec.rb000066400000000000000000000032661322072016200254610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::NestedPercentLiteral do subject(:cop) { described_class.new } let(:message) do 'Within percent literals, nested percent literals do not function and ' \ 'may be unwanted in the result.' end def expect_offense(source) inspect_source(source) expect(cop.offenses.map(&:message)).to eq([message]) expect(cop.highlights).to eq([source]) end it 'registers no offense for empty array' do expect_no_offenses('%i[]') end it 'registers no offense for array' do expect_no_offenses('%i[a b c d xyz]') end it 'registers no offense for percent modifier character in isolation' do expect_no_offenses('%i[% %i %I %q %Q %r %s %w %W %x]') end it 'registers no offense for nestings under percent' do expect_no_offenses('%[a b %[c d] xyz]') expect_no_offenses('%[a b %i[c d] xyz]') end it 'registers offense for nested percent literals' do expect_offense('%i[a b %i[c d] xyz]') end it 'registers offense for repeated nested percent literals' do expect_offense('%i[a b %i[c d] %i[xyz]]') end it 'registers offense for multiply nested percent literals' do # TODO: This emits only one offense for the entire snippet, though it # would be more correct to emit two offenses. This is tricky to fix, as # the AST parses %i[b, %i[c, and d]] as separate tokens. expect_offense('%i[a %i[b %i[c d]] xyz]') end context 'when handling invalid UTF8 byte sequence' do it 'registers no offense for array' do expect_no_offenses('%W[\xff]') end it 'registers offense for nested percent literal' do expect_offense('%W[\xff %W[]]') end end end rubocop-0.52.1/spec/rubocop/cop/lint/next_without_accumulator_spec.rb000066400000000000000000000036371322072016200261050ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::NextWithoutAccumulator do subject(:cop) { described_class.new } def code_without_accumulator(method_name) <<-SOURCE (1..4).#{method_name}(0) do |acc, i| next if i.odd? acc + i end SOURCE end def code_with_accumulator(method_name) <<-SOURCE (1..4).#{method_name}(0) do |acc, i| next acc if i.odd? acc + i end SOURCE end def code_with_nested_block(method_name) <<-SOURCE [(1..3), (4..6)].#{method_name}(0) do |acc, elems| elems.each_with_index do |elem, i| next if i == 1 acc << elem end acc end SOURCE end shared_examples 'reduce/inject' do |reduce_alias| context "given a #{reduce_alias} block" do it 'registers an offense for a bare next' do inspect_source(code_without_accumulator(reduce_alias)) expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(['next']) end it 'accepts next with a value' do inspect_source(code_with_accumulator(reduce_alias)) expect(cop.offenses.empty?).to be(true) end it 'accepts next within a nested block' do inspect_source(code_with_nested_block(reduce_alias)) expect(cop.offenses.empty?).to be(true) end end end it_behaves_like 'reduce/inject', :reduce it_behaves_like 'reduce/inject', :inject context 'given an unrelated block' do it 'accepts a bare next' do expect_no_offenses(<<-RUBY.strip_indent) (1..4).foo(0) do |acc, i| next if i.odd? acc + i end RUBY end it 'accepts next with a value' do expect_no_offenses(<<-RUBY.strip_indent) (1..4).foo(0) do |acc, i| next acc if i.odd? acc + i end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/non_local_exit_from_iterator_spec.rb000066400000000000000000000130021322072016200266610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::NonLocalExitFromIterator do subject(:cop) { described_class.new } context 'inspection' do before do inspect_source(source) end let(:message) do 'Non-local exit from iterator, without return value. ' \ '`next`, `break`, `Array#find`, `Array#any?`, etc. is preferred.' end shared_examples_for 'offense detector' do it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq(message) expect(cop.offenses.first.severity.name).to eq(:warning) expect(cop.highlights).to eq(['return']) end end context 'when block is followed by method chain' do context 'and has single argument' do let(:source) { <<-RUBY } items.each do |item| return if item.stock == 0 item.update!(foobar: true) end RUBY it_behaves_like('offense detector') it { expect(cop.offenses.first.line).to eq(2) } end context 'and has multiple arguments' do let(:source) { <<-RUBY } items.each_with_index do |item, i| return if item.stock == 0 item.update!(foobar: true) end RUBY it_behaves_like('offense detector') it { expect(cop.offenses.first.line).to eq(2) } end context 'and has no argument' do let(:source) { <<-RUBY } item.with_lock do return if item.stock == 0 item.update!(foobar: true) end RUBY it { expect(cop.offenses.empty?).to be(true) } end end context 'when block is not followed by method chain' do let(:source) { <<-RUBY } transaction do return unless update_necessary? find_each do |item| return if item.stock == 0 # false-negative... item.update!(foobar: true) end end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when block is lambda' do let(:source) { <<-RUBY } items.each(lambda do |item| return if item.stock == 0 item.update!(foobar: true) end) items.each -> (item) { return if item.stock == 0 item.update!(foobar: true) } RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when lambda is inside of block followed by method chain' do let(:source) { <<-RUBY } RSpec.configure do |config| # some configuration if Gem.loaded_specs["paper_trail"].version < Gem::Version.new("4.0.0") current_behavior = ActiveSupport::Deprecation.behavior ActiveSupport::Deprecation.behavior = lambda do |message, callstack| return if message =~ /foobar/ Array.wrap(current_behavior).each do |behavior| behavior.call(message, callstack) end end # more configuration end end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when block in middle of nest is followed by method chain' do let(:source) { <<-RUBY } transaction do return unless update_necessary? items.each do |item| return if item.nil? item.with_lock do return if item.stock == 0 item.very_complicated_update_operation! end end end RUBY it 'registers offenses' do expect(cop.offenses.size).to eq(2) expect(cop.offenses[0].message).to eq(message) expect(cop.offenses[0].severity.name).to eq(:warning) expect(cop.offenses[0].line).to eq(4) expect(cop.offenses[1].message).to eq(message) expect(cop.offenses[1].severity.name).to eq(:warning) expect(cop.offenses[1].line).to eq(6) expect(cop.highlights).to eq(%w[return return]) end end context 'when return with value' do let(:source) { <<-RUBY } def find_first_sold_out_item(items) items.each do |item| return item if item.stock == 0 item.foobar! end end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when the message is define_method' do let(:source) { <<-RUBY } [:method_one, :method_two].each do |method_name| define_method(method_name) do return if predicate? end end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when the message is define_singleton_method' do let(:source) { <<-RUBY } str = 'foo' str.define_singleton_method :bar do |baz| return unless baz replace baz end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'when the return is within a nested method definition' do context 'with an instance method definition' do let(:source) { <<-RUBY } Foo.configure do |c| def bar return if baz? end end RUBY it { expect(cop.offenses.empty?).to be(true) } end context 'with a class method definition' do let(:source) { <<-RUBY } Foo.configure do |c| def self.bar return if baz? end end RUBY it { expect(cop.offenses.empty?).to be(true) } end end end end rubocop-0.52.1/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb000066400000000000000000000030411322072016200277420ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ParenthesesAsGroupedExpression do subject(:cop) { described_class.new } it 'registers an offense for method call with space before the ' \ 'parenthesis' do inspect_source('a.func (x)') expect(cop.offenses.size).to eq(1) end it 'registers an offense for predicate method call with space ' \ 'before the parenthesis' do inspect_source('is? (x)') expect(cop.offenses.size).to eq(1) end it 'registers an offense for math expression' do expect_offense(<<-RUBY.strip_indent) puts (2 + 3) * 4 ^ `(...)` interpreted as grouped expression. RUBY end it 'accepts a method call without arguments' do expect_no_offenses('func') end it 'accepts a method call with arguments but no parentheses' do expect_no_offenses('puts x') end it 'accepts a chain of method calls' do expect_no_offenses(<<-RUBY.strip_indent) a.b a.b 1 a.b(1) RUBY end it 'accepts method with parens as arg to method without' do expect_no_offenses('a b(c)') end it 'accepts an operator call with argument in parentheses' do expect_no_offenses(<<-RUBY.strip_indent) a % (b + c) a.b = (c == d) RUBY end it 'accepts a space inside opening paren followed by left paren' do expect_no_offenses('a( (b) )') end it "doesn't register an offense for a call with multiple arguments" do # there is no ambiguity here expect_no_offenses('assert_equal (0..1.9), acceleration.domain') end end rubocop-0.52.1/spec/rubocop/cop/lint/percent_string_array_spec.rb000066400000000000000000000043311322072016200251610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::PercentStringArray do subject(:cop) { described_class.new } let(:message) do "Within `%w`/`%W`, quotes and ',' are unnecessary and may be " \ 'unwanted in the resulting strings.' end def expect_offense(source) inspect_source(source) expect(cop.offenses.map(&:message)).to eq([message]) expect(cop.highlights).to eq([source]) end context 'detecting quotes or commas in a %w/%W string' do %w[w W].each do |char| it 'accepts tokens without quotes or commas' do inspect_source("%#{char}(foo bar baz)") expect(cop.offenses.empty?).to be(true) end [ %(%#{char}(' ")), %(%#{char}(' " ! = # ,)), ':"#{a}"', %(%#{char}(\#{a} b)) ].each do |false_positive| it "accepts likely false positive #{false_positive}" do inspect_source(false_positive) expect(cop.offenses.empty?).to be(true) end end it 'adds an offense if tokens contain quotes and are comma separated' do expect_offense("%#{char}('foo', 'bar', 'baz')") end it 'adds an offense if tokens contain both types of quotes' do expect_offense(%{%#{char}('foo' "bar" 'baz')}) end it 'adds an offense if one token is quoted but there are no commas' do expect_offense("%#{char}('foo' bar baz)") end it 'adds an offense if there are no quotes but one comma' do expect_offense("%#{char}(foo, bar baz)") end end end context 'autocorrection' do let(:source) do <<-SOURCE %w('a', "b", c', "d, e f) %W('a', "b", c', "d, e f) SOURCE end let(:expected_corrected_source) do <<-CORRECTED_SOURCE %w(a b c d e f) %W(a b c d e f) CORRECTED_SOURCE end it 'removes undesirable characters' do expect(autocorrect_source(source)).to eq(expected_corrected_source) end end context 'with invalid byte sequence in UTF-8' do it 'add an offences if tokens contain quotes' do expect_offense('%W("a\255\255")') end it 'accepts if tokens contain invalid byte sequence only' do expect_no_offenses('%W(\255)') end end end rubocop-0.52.1/spec/rubocop/cop/lint/percent_symbol_array_spec.rb000066400000000000000000000032031322072016200251550ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::PercentSymbolArray do subject(:cop) { described_class.new } let(:message) do "Within `%i`/`%I`, ':' and ',' are unnecessary and may be " \ 'unwanted in the resulting symbols.' end def expect_offense(source) inspect_source(source) expect(cop.offenses.map(&:message)).to eq([message]) expect(cop.highlights).to eq([source]) end context 'detecting colons or commas in a %i/%I string' do %w[i I].each do |char| it 'accepts tokens without colons or commas' do inspect_source("%#{char}(foo bar baz)") expect(cop.offenses.empty?).to be(true) end it 'accepts likely false positive $,' do inspect_source("%#{char}{$,}") expect(cop.offenses.empty?).to be(true) end it 'adds an offense if symbols contain colons and are comma separated' do expect_offense("%#{char}(:foo, :bar, :baz)") end it 'adds an offense if one symbol has a colon but there are no commas' do expect_offense("%#{char}(:foo bar baz)") end it 'adds an offense if there are no colons but one comma' do expect_offense("%#{char}(foo, bar baz)") end end end context 'autocorrection' do let(:source) do <<-SOURCE %i(:a, :b, c, d e :f) %I(:a, :b, c, d e :f) SOURCE end let(:expected_corrected_source) do <<-CORRECTED_SOURCE %i(a b c d e f) %I(a b c d e f) CORRECTED_SOURCE end it 'removes undesirable characters' do expect(autocorrect_source(source)).to eq(expected_corrected_source) end end end rubocop-0.52.1/spec/rubocop/cop/lint/rand_one_spec.rb000066400000000000000000000025421322072016200225240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RandOne do subject(:cop) { described_class.new } before { inspect_source(source) } shared_examples 'offenses' do |source| describe source do let(:source) { source } it 'registers an offense' do expect(cop.messages).to eq( [ "`#{source}` always returns `0`. " \ 'Perhaps you meant `rand(2)` or `rand`?' ] ) expect(cop.highlights).to eq([source]) end end end shared_examples 'no offense' do |source| describe source do let(:source) { source } it "doesn't register an offense" do expect(cop.messages.empty?).to be(true) end end end it_behaves_like 'offenses', 'rand 1' it_behaves_like 'offenses', 'rand(-1)' it_behaves_like 'offenses', 'rand(1.0)' it_behaves_like 'offenses', 'rand(-1.0)' it_behaves_like 'no offense', 'rand' it_behaves_like 'no offense', 'rand(2)' it_behaves_like 'no offense', 'rand(-1..1)' it_behaves_like 'offenses', 'Kernel.rand(1)' it_behaves_like 'offenses', 'Kernel.rand(-1)' it_behaves_like 'offenses', 'Kernel.rand 1.0' it_behaves_like 'offenses', 'Kernel.rand(-1.0)' it_behaves_like 'no offense', 'Kernel.rand' it_behaves_like 'no offense', 'Kernel.rand 2' it_behaves_like 'no offense', 'Kernel.rand(-1..1)' end rubocop-0.52.1/spec/rubocop/cop/lint/redundant_with_index_spec.rb000066400000000000000000000040141322072016200251410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RedundantWithIndex do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `ary.each_with_index { |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each_with_index { |v| v } ^^^^^^^^^^^^^^^ Use `each` instead of `each_with_index`. RUBY end it 'registers an offense when using `ary.each.with_index { |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each.with_index { |v| v } ^^^^^^^^^^ Remove redundant `with_index`. RUBY end it 'registers an offense when using `ary.each.with_index(1) { |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each.with_index(1) { |v| v } ^^^^^^^^^^^^^ Remove redundant `with_index`. RUBY end it 'registers an offense when using `ary.each_with_object([]).with_index ' \ '{ |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each_with_object([]).with_index { |v| v } ^^^^^^^^^^ Remove redundant `with_index`. RUBY end it 'autocorrects to ary.each from ary.each_with_index' do new_source = autocorrect_source('ary.each_with_index { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each.with_index' do new_source = autocorrect_source('ary.each.with_index { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each.with_index(1)' do new_source = autocorrect_source('ary.each.with_index(1) { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each_with_object([]).with_index' do new_source = autocorrect_source('ary.each_with_object([]) { |v| v }') expect(new_source).to eq 'ary.each_with_object([]) { |v| v }' end it 'an index is used as a block argument' do expect_no_offenses('ary.each_with_index { |v, i| v; i }') end end rubocop-0.52.1/spec/rubocop/cop/lint/redundant_with_object_spec.rb000066400000000000000000000042461322072016200253070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RedundantWithObject do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `ary.each_with_object { |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each_with_object([]) { |v| v } ^^^^^^^^^^^^^^^^^^^^ Use `each` instead of `each_with_object`. RUBY end it 'registers an offense when using `ary.each.with_object([]) { |v| v }`' do expect_offense(<<-RUBY.strip_indent) ary.each.with_object([]) { |v| v } ^^^^^^^^^^^^^^^ Remove redundant `with_object`. RUBY end it 'autocorrects to ary.each from ary.each_with_object([])' do new_source = autocorrect_source('ary.each_with_object([]) { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each_with_object []' do new_source = autocorrect_source('ary.each_with_object [] { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each_with_object([]) do-end block' do new_source = autocorrect_source(<<-RUBY.strip_indent) ary.each_with_object([]) do |v| v end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) ary.each do |v| v end RUBY end it 'autocorrects to ary.each from ary.each_with_object do-end block' do new_source = autocorrect_source(<<-RUBY.strip_indent) ary.each_with_object [] do |v| v end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) ary.each do |v| v end RUBY end it 'autocorrects to ary.each from ary.each.with_object([]) { |v| v }' do new_source = autocorrect_source('ary.each.with_object([]) { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'autocorrects to ary.each from ary.each.with_object [] { |v| v }' do new_source = autocorrect_source('ary.each.with_object [] { |v| v }') expect(new_source).to eq 'ary.each { |v| v }' end it 'an object is used as a block argument' do expect_no_offenses('ary.each_with_object([]) { |v, o| v; o }') end end rubocop-0.52.1/spec/rubocop/cop/lint/regexp_as_condition_spec.rb000066400000000000000000000013641322072016200247630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RegexpAsCondition do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense for a regexp literal in `if` condition' do expect_offense(<<-RUBY.strip_indent) if /foo/ ^^^^^ Do not use regexp literal as a condition. The regexp literal matches `$_` implicitly. end RUBY end it 'does not register an offense for a regexp literal outside conditions' do expect_no_offenses(<<-RUBY.strip_indent) /foo/ RUBY end it 'does not register an offense for a regexp literal with `=~` operator' do expect_no_offenses(<<-RUBY.strip_indent) if /foo/ =~ str end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/require_parentheses_spec.rb000066400000000000000000000045701322072016200250170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RequireParentheses do subject(:cop) { described_class.new } it 'registers an offense for missing parentheses around expression with ' \ '&& operator' do inspect_source(<<-RUBY.strip_indent) if day.is? 'monday' && month == :jan foo end RUBY expect(cop.highlights).to eq(["day.is? 'monday' && month == :jan"]) expect(cop.messages) .to eq(['Use parentheses in the method call to avoid confusion about ' \ 'precedence.']) end it 'registers an offense for missing parentheses around expression with ' \ '|| operator' do inspect_source("day_is? 'tuesday' || true") expect(cop.highlights).to eq(["day_is? 'tuesday' || true"]) end it 'registers an offense for missing parentheses around expression in ' \ 'ternary' do inspect_source("wd.include? 'tuesday' && true == true ? a : b") expect(cop.highlights).to eq(["wd.include? 'tuesday' && true == true"]) end it 'accepts missing parentheses around expression with + operator' do expect_no_offenses(<<-RUBY.strip_indent) if day_is? 'tuesday' + rest end RUBY end it 'accepts method calls without parentheses followed by keyword and/or' do expect_no_offenses(<<-RUBY.strip_indent) if day.is? 'tuesday' and month == :jan end if day.is? 'tuesday' or month == :jan end RUBY end it 'accepts method calls that are all operations' do expect_no_offenses(<<-RUBY.strip_indent) if current_level == max + 1 end RUBY end it 'accepts condition that is not a call' do expect_no_offenses(<<-RUBY.strip_indent) if @debug end RUBY end it 'accepts parentheses around expression with boolean operator' do expect_no_offenses(<<-RUBY.strip_indent) if day.is?('tuesday' && true == true) end RUBY end it 'accepts method call with parentheses in ternary' do expect_no_offenses("wd.include?('tuesday' && true == true) ? a : b") end it 'accepts missing parentheses when method is not a predicate' do expect_no_offenses("weekdays.foo 'tuesday' && true == true") end it 'accepts calls to methods that are setters' do expect_no_offenses('s.version = @version || ">= 1.8.5"') end it 'accepts calls to methods that are operators' do expect_no_offenses('a[b || c]') end end rubocop-0.52.1/spec/rubocop/cop/lint/rescue_exception_spec.rb000066400000000000000000000060121322072016200242770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RescueException do subject(:cop) { described_class.new } it 'registers an offense for rescue from Exception' do expect_offense(<<-RUBY.strip_indent) begin something rescue Exception ^^^^^^^^^^^^^^^^ Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`? #do nothing end RUBY end it 'registers an offense for rescue with ::Exception' do expect_offense(<<-RUBY.strip_indent) begin something rescue ::Exception ^^^^^^^^^^^^^^^^^^ Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`? #do nothing end RUBY end it 'registers an offense for rescue with StandardError, Exception' do expect_offense(<<-RUBY.strip_indent) begin something rescue StandardError, Exception ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`? #do nothing end RUBY end it 'registers an offense for rescue with Exception => e' do expect_offense(<<-RUBY.strip_indent) begin something rescue Exception => e ^^^^^^^^^^^^^^^^^^^^^ Avoid rescuing the `Exception` class. Perhaps you meant to rescue `StandardError`? #do nothing end RUBY end it 'does not register an offense for rescue with no class' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue file.close end RUBY end it 'does not register an offense for rescue with no class and => e' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue => e file.close end RUBY end it 'does not register an offense for rescue with other class' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue ArgumentError => e file.close end RUBY end it 'does not register an offense for rescue with other classes' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue EOFError, ArgumentError => e file.close end RUBY end it 'does not register an offense for rescue with a module prefix' do expect_no_offenses(<<-RUBY.strip_indent) begin something return rescue Test::Exception => e file.close end RUBY end it 'does not crash when the splat operator is used in a rescue' do expect_no_offenses(<<-RUBY.strip_indent) ERRORS = [Exception] begin a = 3 / 0 rescue *ERRORS puts e end RUBY end it 'does not crash when the namespace of a rescued class is in a local ' \ 'variable' do inspect_source(<<-RUBY.strip_indent) adapter = current_adapter begin rescue adapter::ParseError end RUBY expect(cop.offenses.empty?).to be(true) end end rubocop-0.52.1/spec/rubocop/cop/lint/rescue_type_spec.rb000066400000000000000000000141651322072016200232720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::RescueType do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'accepts rescue modifier' do expect_no_offenses('foo rescue nil') end it 'accepts rescuing nothing' do expect_no_offenses(<<-RUBY) begin foo rescue bar end RUBY end it 'accepts rescuing a single exception' do expect_no_offenses(<<-RUBY) def foobar foo rescue NameError bar end RUBY end it 'accepts rescuing nothing within a method definition' do expect_no_offenses(<<-RUBY) def foobar foo rescue bar end RUBY end shared_examples :offenses do |rescues| context 'begin rescue' do context "rescuing from #{rescues}" do let(:source) do <<-RUBY begin foo rescue #{rescues} bar end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue #{rescues}"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) begin foo rescue bar end RUBY end end context "rescuing from #{rescues} before another exception" do let(:source) do <<-RUBY begin foo rescue #{rescues}, StandardError bar end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue #{rescues}, StandardError"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) begin foo rescue StandardError bar end RUBY end end context "rescuing from #{rescues} after another exception" do let(:source) do <<-RUBY begin foo rescue StandardError, #{rescues} bar end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue StandardError, #{rescues}"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) begin foo rescue StandardError bar end RUBY end end end context 'begin rescue ensure' do context "rescuing from #{rescues}" do let(:source) do <<-RUBY begin foo rescue #{rescues} bar ensure baz end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue #{rescues}"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) begin foo rescue bar ensure baz end RUBY end end end context 'def rescue' do context "rescuing from #{rescues}" do let(:source) do <<-RUBY def foobar foo rescue #{rescues} bar end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue #{rescues}"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) def foobar foo rescue bar end RUBY end end end context 'def rescue ensure' do context "rescuing from #{rescues}" do let(:source) do <<-RUBY def foobar foo rescue #{rescues} bar ensure baz end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.highlights).to eq(["rescue #{rescues}"]) expect(cop.messages) .to eq(["Rescuing from `#{rescues}` will raise a `TypeError` " \ 'instead of catching the actual exception.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY) def foobar foo rescue bar ensure baz end RUBY end end end end it_behaves_like :offenses, 'nil' it_behaves_like :offenses, "'string'" it_behaves_like :offenses, '"#{string}"' it_behaves_like :offenses, '0' it_behaves_like :offenses, '0.0' it_behaves_like :offenses, '[]' it_behaves_like :offenses, '{}' it_behaves_like :offenses, ':symbol' end rubocop-0.52.1/spec/rubocop/cop/lint/return_in_void_context_spec.rb000066400000000000000000000037611322072016200255350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ReturnInVoidContext do subject(:cop) { described_class.new } context 'with an initialize method containing a return with a value' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class A def initialize return :qux if bar? ^^^^^^ Do not return a value in `initialize`. end end RUBY end end context 'with an initialize method containing a return without a value' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) class A def initialize return if bar? end end RUBY end end context 'with a setter method containing a return with a value' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class A def foo=(bar) return 42 ^^^^^^ Do not return a value in `foo=`. end end RUBY end end context 'with a setter method containing a return without a value' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) class A def foo=(bar) return end end RUBY end end context 'with a non initialize method containing a return' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) class A def bar foo return :qux if bar? foo end end RUBY end end context 'with a class method called initialize containing a return' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) class A def self.initialize foo return :qux if bar? foo end end RUBY end end context 'when return is in top scope' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) return if true RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/safe_navigation_chain_spec.rb000066400000000000000000000104071322072016200252350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::SafeNavigationChain, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Whitelist' => %w[present? blank? try presence] } end shared_examples :accepts do |name, code| it "accepts usages of #{name}" do inspect_source(code) expect(cop.offenses.empty?).to be(true) end end shared_examples :offense do |name, code| it "registers an offense for #{name}" do inspect_source(code) expect(cop.messages) .to eq( ['Do not chain ordinary method call after safe navigation operator.'] ) end end shared_examples :autocorrect do |name, source, correction| it "corrects #{name}" do new_source = autocorrect_source_with_loop(source) expect(new_source).to eq(correction) end end context 'TargetRubyVersion >= 2.3', :ruby23 do [ ['ordinary method chain', 'x.foo.bar.baz'], ['ordinary method chain with argument', 'x.foo(x).bar(y).baz(z)'], ['method chain with safe navigation only', 'x&.foo&.bar&.baz'], ['method chain with safe navigation only with argument', 'x&.foo(x)&.bar(y)&.baz(z)'], ['safe navigation at last only', 'x.foo.bar&.baz'], ['safe navigation at last only with argument', 'x.foo(x).bar(y)&.baz(z)'], ['safe navigation with == operator', 'x&.foo == bar'], ['safe navigation with === operator', 'x&.foo === bar'], ['safe navigation with || operator', 'x&.foo || bar'], ['safe navigation with && operator', 'x&.foo && bar'], ['safe navigation with | operator', 'x&.foo | bar'], ['safe navigation with & operator', 'x&.foo & bar'], ['safe navigation with `nil?` method', 'x&.foo.nil?'], ['safe navigation with `present?` method', 'x&.foo.present?'], ['safe navigation with `blank?` method', 'x&.foo.blank?'], ['safe navigation with `try` method', 'a&.b.try(:c)'], ['safe navigation with assignment method', 'x&.foo = bar'], ['safe navigation with self assignment method', 'x&.foo += bar'] ].each do |name, code| include_examples :accepts, name, code end [ ['ordinary method call exists after safe navigation method call', 'x&.foo.bar'], ['ordinary method call exists after safe navigation method call' \ 'with argument', 'x&.foo(x).bar(y)'], ['ordinary method chain exists after safe navigation method call', 'x&.foo.bar.baz'], ['ordinary method chain exists after safe navigation method call' \ 'with argument', 'x&.foo(x).bar(y).baz(z)'], ['safe navigation with < operator', 'x&.foo < bar'], ['safe navigation with > operator', 'x&.foo > bar'], ['safe navigation with <= operator', 'x&.foo <= bar'], ['safe navigation with >= operator', 'x&.foo >= bar'], ['safe navigation with + operator', 'x&.foo + bar'], ['safe navigation with []', 'x&.foo[bar]'], ['safe navigation with []=', 'x&.foo[bar] = baz'] ].each do |name, code| include_examples :offense, name, code end [ ['ordinary method call exists after safe navigation method call', 'x&.foo.bar', 'x&.foo&.bar'], ['ordinary method call exists after safe navigation method call' \ 'with argument', 'x&.foo(x).bar(y)', 'x&.foo(x)&.bar(y)'], ['ordinary method chain exists after safe navigation method call', 'x&.foo.bar.baz', 'x&.foo&.bar&.baz'], ['ordinary method chain exists after safe navigation method call' \ 'with argument', 'x&.foo(x).bar(y).baz(z)', 'x&.foo(x)&.bar(y)&.baz(z)'], # Do not autocorrect the followings ['safe navigation with < operator', 'x&.foo < bar', 'x&.foo < bar'], ['safe navigation with > operator', 'x&.foo > bar', 'x&.foo > bar'], ['safe navigation with <= operator', 'x&.foo <= bar', 'x&.foo <= bar'], ['safe navigation with >= operator', 'x&.foo >= bar', 'x&.foo >= bar'], ['safe navigation with + operator', 'x&.foo + bar', 'x&.foo + bar'], ['safe navigation with []', 'x&.foo[bar]', 'x&.foo[bar]'], ['safe navigation with []=', 'x&.foo[bar] = baz', 'x&.foo[bar] = baz'] ].each do |name, code, correction| include_examples :autocorrect, name, code, correction end end end rubocop-0.52.1/spec/rubocop/cop/lint/script_permission_spec.rb000066400000000000000000000037631322072016200245210ustar00rootroot00000000000000# frozen_string_literal: true # rubocop:disable Style/NumericLiteralPrefix RSpec.describe RuboCop::Cop::Lint::ScriptPermission do subject(:cop) { described_class.new(config, options) } let(:config) { RuboCop::Config.new } let(:options) { nil } let(:file) { Tempfile.new('') } let(:filename) { file.path.split('/').last } after do file.close file.unlink end context 'with file permission 0644' do let(:source) { '#!/usr/bin/ruby' } before do File.write(file.path, source) FileUtils.chmod(0644, file.path) end if RuboCop::Platform.windows? context 'Windows' do it 'allows any file permissions' do expect_no_offenses(<<-RUBY.strip_indent, file) #!/usr/bin/ruby RUBY end end else it 'registers an offense for script permission' do expect_offense(<<-RUBY.strip_indent, file) #!/usr/bin/ruby ^^^^^^^^^^^^^^^ Script file #{filename} doesn't have execute permission. RUBY end end end context 'with file permission 0755' do before do FileUtils.chmod(0755, file.path) end it 'accepts with shebang line' do File.write(file.path, '#!/usr/bin/ruby') expect_no_offenses(file.read, file) end it 'accepts without shebang line' do File.write(file.path, 'puts "hello"') expect_no_offenses(file.read, file) end it 'accepts with blank' do File.write(file.path, '') expect_no_offenses(file.read, file) end end context 'with stdin' do let(:options) { { stdin: '' } } it 'skips investigation' do expect_no_offenses('#!/usr/bin/ruby') end end unless RuboCop::Platform.windows? context 'auto-correct' do it 'adds execute permissions to the file' do File.write(file.path, '#!/usr/bin/ruby') autocorrect_source(file.read, file) expect(file.stat.executable?).to be_truthy end end end end # rubocop:enable Style/NumericLiteralPrefix rubocop-0.52.1/spec/rubocop/cop/lint/shadowed_argument_spec.rb000066400000000000000000000473311322072016200244440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ShadowedArgument, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'IgnoreImplicitReferences' => false } } describe 'method argument shadowing' do context 'when a single argument is shadowed' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) foo = 42 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. puts foo end RUBY end context 'when zsuper is used' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) foo = 42 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. super end RUBY end context 'when IgnoreImplicitReferences config option is set to true' do let(:cop_config) { { 'IgnoreImplicitReferences' => true } } it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) foo = 42 super end RUBY end end end context 'when binding is used' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) foo = 42 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. binding end RUBY end context 'when IgnoreImplicitReferences config option is set to true' do let(:cop_config) { { 'IgnoreImplicitReferences' => true } } it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) foo = 42 binding end RUBY end end end context 'and the argument is not used' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) puts 'done something' end RUBY end end context 'and shadowed within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. if bar foo = 43 end foo = 42 puts foo end RUBY end context 'and was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) if bar puts foo foo = 43 end foo = 42 puts foo end RUBY end end context 'and the argument was not shadowed outside the conditional' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) if bar foo = 42 end puts foo end RUBY end end context 'and the conditional occurs after the reassignment' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. if bar foo = 42 end puts foo end RUBY end end context 'and the conditional is nested within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. if bar if baz foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) if bar puts foo if baz foo = 43 end end foo = 42 puts foo end RUBY end end end context 'and the conditional is nested within a lambda' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. lambda do if baz foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) lambda do puts foo if baz foo = 43 end end foo = 42 puts foo end RUBY end end end end context 'and shadowed within a block' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. something { foo = 43 } foo = 42 puts foo end RUBY end context 'and was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) lambda do puts foo foo = 43 end foo = 42 puts foo end RUBY end end context 'and the argument was not shadowed outside the block' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) something { foo = 43 } puts foo end RUBY end end context 'and the block occurs after the reassignment' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. something { foo = 42 } puts foo end RUBY end end context 'and the block is nested within a block' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. something do lambda do foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) lambda do puts foo something do foo = 43 end end foo = 42 puts foo end RUBY end end end context 'and the block is nested within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) def do_something(foo) ^^^ Argument `foo` was shadowed by a local variable before it was used. if baz lambda do foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def do_something(foo) if baz puts foo lambda do foo = 43 end end foo = 42 puts foo end RUBY end end end end end context 'when multiple arguments are shadowed' do context 'and one of them shadowed within a lambda while another is ' \ 'shadowed outside' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def do_something(foo, bar) lambda do bar = 42 end foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. puts(foo, bar) end RUBY end end end end describe 'block argument shadowing' do context 'when a single argument is shadowed' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| foo = 42 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. puts foo end RUBY end context 'when zsuper is used' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| foo = 42 super end RUBY end end context 'when binding is used' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| foo = 42 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. binding end RUBY end context 'when IgnoreImplicitReferences config option is set to true' do let(:cop_config) { { 'IgnoreImplicitReferences' => true } } it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| foo = 42 binding end RUBY end end end context 'and the argument is not used' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| puts 'done something' end RUBY end end context 'and shadowed within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. if bar foo = 43 end foo = 42 puts foo end RUBY end context 'and was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| if bar puts foo foo = 43 end foo = 42 puts foo end RUBY end end context 'and the argument was not shadowed outside the conditional' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| if bar foo = 42 end puts foo end RUBY end end context 'and the conditional occurs after the reassignment' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. if bar foo = 42 end puts foo end RUBY end end context 'and the conditional is nested within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. if bar if baz foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| if bar puts foo if baz foo = 43 end end foo = 42 puts foo end RUBY end end end context 'and the conditional is nested within a lambda' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. lambda do if baz foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| lambda do puts foo if baz foo = 43 end end foo = 42 puts foo end RUBY end end end end context 'and shadowed within a block' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. something { foo = 43 } foo = 42 puts foo end RUBY end context 'and was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| lambda do puts foo foo = 43 end foo = 42 puts foo end RUBY end end context 'and the argument was not shadowed outside the block' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| something { foo = 43 } puts foo end RUBY end end context 'and the block occurs after the reassignment' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. something { foo = 42 } puts foo end RUBY end end context 'and the block is nested within a block' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. something do lambda do foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| lambda do puts foo something do foo = 43 end end foo = 42 puts foo end RUBY end end end context 'and the block is nested within a conditional' do it 'registers an offense without specifying where '\ 'the reassignment took place' do expect_offense(<<-RUBY.strip_indent) do_something do |foo| ^^^ Argument `foo` was shadowed by a local variable before it was used. if baz lambda do foo = 43 end end foo = 42 puts foo end RUBY end context 'and the argument was used before shadowing' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) do_something do |foo| if baz puts foo lambda do foo = 43 end end foo = 42 puts foo end RUBY end end end end end context 'when multiple arguments are shadowed' do context 'and one of them shadowed within a lambda while another is ' \ 'shadowed outside' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) do_something do |foo, bar| lambda do bar = 42 end foo = 43 ^^^^^^^^ Argument `foo` was shadowed by a local variable before it was used. puts(foo, bar) end RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/shadowed_exception_spec.rb000066400000000000000000000336321322072016200246170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ShadowedException do subject(:cop) { described_class.new } context 'modifier rescue' do it 'accepts rescue in its modifier form' do expect_no_offenses('foo rescue nil') end end context 'single rescue' do it 'accepts an empty rescue' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue handle_exception end RUBY end it 'accepts rescuing a single exception' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Exception handle_exception end RUBY end it 'accepts rescuing a single custom exception' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue NonStandardException handle_exception end RUBY end it 'accepts rescuing a custom exception and a standard exception' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Error, NonStandardException handle_exception end RUBY end it 'accepts rescuing multiple custom exceptions' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue CustomError, NonStandardException handle_exception end RUBY end it 'accepts rescue containing multiple same error code exceptions' do # System dependent error code depends on runtime environment. stub_const('Errno::EAGAIN::Errno', 35) stub_const('Errno::EWOULDBLOCK::Errno', 35) stub_const('Errno::ECONNABORTED::Errno', 53) expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Errno::EAGAIN, Errno::EWOULDBLOCK, Errno::ECONNABORTED handle_exception end RUBY end it 'registers an offense rescuing exceptions that are ' \ 'ancestors of each other ' do inspect_source(<<-RUBY.strip_indent) def something rescue StandardError, RuntimeError handle_exception end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) end it 'registers an offense rescuing Exception with any other error or ' \ 'exception' do inspect_source(<<-RUBY.strip_indent) begin something rescue NonStandardError, Exception handle_exception end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) end it 'accepts rescuing a single exception that is assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Exception => e handle_exception(e) end RUBY end it 'accepts rescuing a single exception that has an ensure' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Exception handle_exception ensure everything_is_ok end RUBY end it 'accepts rescuing a single exception that has an else' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue Exception handle_exception else handle_non_exception end RUBY end it 'accepts rescuing a multiple exceptions that are not ancestors that ' \ 'have an else' do inspect_source(<<-RUBY.strip_indent) begin something rescue NoMethodError, ZeroDivisionError handle_exception else handle_non_exception end RUBY expect(cop.offenses.empty?).to be(true) end context 'when there are multiple levels of exceptions in the same rescue' do it 'registers an offense for two exceptions' do expect_offense(<<-RUBY.strip_indent) begin something rescue StandardError, NameError ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not shadow rescued Exceptions. foo end RUBY end it 'registers an offense for more than two exceptions' do expect_offense(<<-RUBY.strip_indent) begin something rescue StandardError, NameError, NoMethodError ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not shadow rescued Exceptions. foo end RUBY end end it 'registers an offense for the same exception multiple times' do expect_offense(<<-RUBY.strip_indent) begin something rescue NameError, NameError ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not shadow rescued Exceptions. foo end RUBY end it 'accepts splat arguments passed to rescue' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue *FOO b end RUBY end it 'accepts rescuing nil' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue nil b end RUBY end it 'accepts rescuing nil and another exception' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue nil, Exception b end RUBY end it 'registers an offense when rescuing nil multiple exceptions of ' \ 'different levels' do inspect_source(<<-RUBY.strip_indent) begin a rescue nil, StandardError, Exception b end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq(['rescue nil, StandardError, Exception']) end end context 'multiple rescues' do it 'registers an offense when a higher level exception is rescued before' \ ' a lower level exception' do inspect_source(<<-RUBY.strip_indent) begin something rescue Exception handle_exception rescue StandardError handle_standard_error end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq([['rescue Exception', ' handle_exception', 'rescue StandardError'].join("\n")]) end it 'registers an offense when a higher level exception is rescued before ' \ 'a lower level exception when there are multiple exceptions ' \ 'rescued in a group' do inspect_source(<<-RUBY.strip_indent) begin something rescue Exception handle_exception rescue NoMethodError, ZeroDivisionError handle_standard_error end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq([['rescue Exception', ' handle_exception', 'rescue NoMethodError, ZeroDivisionError'] .join("\n")]) end it 'registers an offense rescuing out of order exceptions when there ' \ 'is an ensure' do inspect_source(<<-RUBY.strip_indent) begin something rescue Exception handle_exception rescue StandardError handle_standard_error ensure everything_is_ok end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq([['rescue Exception', ' handle_exception', 'rescue StandardError'].join("\n")]) end it 'accepts rescuing exceptions in order of level' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue StandardError handle_standard_error rescue Exception handle_exception end RUBY end it 'accepts many (>= 7) rescue groups' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue StandardError handle_error rescue ErrorA handle_error rescue ErrorB handle_error rescue ErrorC handle_error rescue ErrorD handle_error rescue ErrorE handle_error rescue ErrorF handle_error end RUBY end it 'accepts rescuing exceptions in order of level with multiple ' \ 'exceptions in a group' do inspect_source(<<-RUBY.strip_indent) begin something rescue NoMethodError, ZeroDivisionError handle_standard_error rescue Exception handle_exception end RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts rescuing exceptions in order of level with multiple ' \ 'exceptions in a group with custom exceptions' do inspect_source(<<-RUBY.strip_indent) begin something rescue NonStandardError, NoMethodError handle_standard_error rescue Exception handle_exception end RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts rescuing custom exceptions in multiple rescue groups' do expect_no_offenses(<<-RUBY.strip_indent) begin something rescue NonStandardError, OtherError handle_standard_error rescue CustomError handle_exception end RUBY end context 'splat arguments' do it 'accepts splat arguments passed to multiple rescues' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue *FOO b rescue *BAR c end RUBY end it 'registers an offense for splat arguments rescued after ' \ 'rescuing a known exception' do inspect_source(<<-RUBY.strip_indent) begin a rescue StandardError b rescue *BAR c end RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for splat arguments rescued after ' \ 'rescuing Exception' do inspect_source(<<-RUBY.strip_indent) begin a rescue Exception b rescue *BAR c end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq([['rescue Exception', ' b', 'rescue *BAR'].join("\n")]) end end context 'exceptions from different ancestry chains' do it 'accepts rescuing exceptions in one order' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue ArgumentError b rescue Interrupt c end RUBY end it 'accepts rescuing exceptions in another order' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue Interrupt b rescue ArgumentError c end RUBY end end it 'accepts rescuing nil before another exception' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue nil b rescue c end RUBY end it 'accepts rescuing nil after another exception' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue b rescue nil c end RUBY end it 'accepts rescuing a known exception after an unknown exceptions' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue UnknownException b rescue StandardError c end RUBY end it 'accepts rescuing a known exception before an unknown exceptions' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue StandardError b rescue UnknownException c end RUBY end it 'accepts rescuing a known exception between unknown exceptions' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue UnknownException b rescue StandardError c rescue AnotherUnknownException d end RUBY end it 'registers an offense rescuing Exception before an unknown exceptions' do inspect_source(<<-RUBY.strip_indent) begin a rescue Exception b rescue UnknownException c end RUBY expect(cop.messages).to eq(['Do not shadow rescued Exceptions.']) expect(cop.highlights).to eq([['rescue Exception', ' b', 'rescue UnknownException'].join("\n")]) end it 'ignores expressions of non-const' do expect_no_offenses(<<-RUBY.strip_indent) begin a rescue foo b rescue [bar] c end RUBY end context 'last rescue does not specify exception class' do let(:source) do <<-RUBY.strip_indent begin rescue A, B do_something rescue C do_something rescue do_something end RUBY end it 'does not raise error' do expect { inspect_source(source) }.not_to raise_error end it 'highlights range ending at rescue keyword' do expect_no_offenses(<<-RUBY.strip_indent) begin rescue A, B do_something rescue C do_something rescue do_something end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/lint/shadowing_outer_local_variable_spec.rb000066400000000000000000000122631322072016200271600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::ShadowingOuterLocalVariable do subject(:cop) { described_class.new } context 'when a block argument has same name ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do |foo| end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Shadowing outer local variable - `foo`.') expect(cop.offenses.first.line).to eq(4) end include_examples 'mimics MRI 2.1' end context 'when a splat block argument has same name ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do |*foo| end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Shadowing outer local variable - `foo`.') expect(cop.offenses.first.line).to eq(4) end include_examples 'mimics MRI 2.1' end context 'when a block block argument has same name ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo proc_taking_block = proc do |&foo| end proc_taking_block.call do end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Shadowing outer local variable - `foo`.') expect(cop.offenses.first.line).to eq(4) end include_examples 'mimics MRI 2.1' end context 'when a block local variable has same name ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do |i; foo| puts foo end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Shadowing outer local variable - `foo`.') expect(cop.offenses.first.line).to eq(4) end include_examples 'mimics MRI 2.1', 'shadowing' end context 'when a block argument has different name ' \ 'with outer scope variables' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do |bar| end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when an outer scope variable is reassigned in a block' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do foo = 2 end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when an outer scope variable is referenced in a block' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do puts foo end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when multiple block arguments have same name "_"' do let(:source) do <<-RUBY.strip_indent def some_method 1.times do |_, foo, _| end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when multiple block arguments have ' \ 'a same name starts with "_"' do let(:source) do <<-RUBY.strip_indent def some_method 1.times do |_foo, bar, _foo| end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a block argument has same name "_" ' \ 'as outer scope variable "_"' do let(:source) do <<-RUBY.strip_indent def some_method _ = 1 puts _ 1.times do |_| end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a block argument has a same name starts with "_" ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent def some_method _foo = 1 puts _foo 1.times do |_foo| end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a method argument has same name ' \ 'as an outer scope variable' do let(:source) do <<-RUBY.strip_indent class SomeClass foo = 1 puts foo def some_method(foo) end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end end rubocop-0.52.1/spec/rubocop/cop/lint/string_conversion_in_interpolation_spec.rb000066400000000000000000000027411322072016200301500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::StringConversionInInterpolation do subject(:cop) { described_class.new } it 'registers an offense for #to_s in interpolation' do expect_offense(<<-'RUBY'.strip_indent) "this is the #{result.to_s}" ^^^^ Redundant use of `Object#to_s` in interpolation. RUBY end it 'detects #to_s in an interpolation with several expressions' do expect_offense(<<-'RUBY'.strip_indent) "this is the #{top; result.to_s}" ^^^^ Redundant use of `Object#to_s` in interpolation. RUBY end it 'accepts #to_s with arguments in an interpolation' do expect_no_offenses('"this is a #{result.to_s(8)}"') end it 'accepts interpolation without #to_s' do expect_no_offenses('"this is the #{result}"') end it 'does not explode on implicit receiver' do expect_offense(<<-'RUBY'.strip_indent) "#{to_s}" ^^^^ Use `self` instead of `Object#to_s` in interpolation. RUBY end it 'does not explode on empty interpolation' do expect_no_offenses('"this is #{} silly"') end it 'autocorrects by removing the redundant to_s' do corrected = autocorrect_source(['"some #{something.to_s}"']) expect(corrected).to eq '"some #{something}"' end it 'autocorrects implicit receiver by replacing to_s with self' do corrected = autocorrect_source(['"some #{to_s}"']) expect(corrected).to eq '"some #{self}"' end end rubocop-0.52.1/spec/rubocop/cop/lint/syntax_spec.rb000066400000000000000000000046141322072016200222670ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::Syntax do let(:options) { nil } let(:ruby_version) { 2.4 } let(:path) { 'test.rb' } let(:processed_source) do RuboCop::ProcessedSource.new(source, ruby_version, path) end describe '.offenses_from_processed_source' do let(:offenses) do described_class.offenses_from_processed_source(processed_source, nil, options) end context 'with a diagnostic error' do let(:source) { '(' } it 'returns an offense' do expect(offenses.size).to eq(1) message = <<-MESSAGE.chomp.strip_indent unexpected token $end (Using Ruby 2.4 parser; configure using `TargetRubyVersion` parameter, under `AllCops`) MESSAGE offense = offenses.first expect(offense.message).to eq(message) expect(offense.severity).to eq(:error) end context 'with --display-cop-names option' do let(:options) { { display_cop_names: true } } it 'returns an offense with cop name' do expect(offenses.size).to eq(1) message = <<-MESSAGE.chomp.strip_indent Lint/Syntax: unexpected token $end (Using Ruby 2.4 parser; configure using `TargetRubyVersion` parameter, under `AllCops`) MESSAGE offense = offenses.first expect(offense.message).to eq(message) expect(offense.severity).to eq(:error) end end end context 'with a parser error' do let(:source) { <<-RUBY } # encoding: utf-8 # \xf9 RUBY it 'returns an offense' do expect(offenses.size).to eq(1) offense = offenses.first expect(offense.message).to eq('Invalid byte sequence in utf-8.') expect(offense.severity).to eq(:fatal) expect(offense.location).to eq(described_class::ERROR_SOURCE_RANGE) end context 'with --display-cop-names option' do let(:options) { { display_cop_names: true } } it 'returns an offense with cop name' do expect(offenses.size).to eq(1) message = <<-MESSAGE.chomp.strip_indent Lint/Syntax: Invalid byte sequence in utf-8. MESSAGE offense = offenses.first expect(offense.message).to eq(message) expect(offense.severity).to eq(:fatal) end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/underscore_prefixed_variable_name_spec.rb000066400000000000000000000107421322072016200276440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnderscorePrefixedVariableName do subject(:cop) { described_class.new } context 'when an underscore-prefixed variable is used' do let(:source) { <<-RUBY } def some_method _foo = 1 puts _foo end RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Do not use prefix `_` for a variable that is used.') expect(cop.offenses.first.severity.name).to eq(:warning) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['_foo']) end end context 'when non-underscore-prefixed variable is used' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def some_method foo = 1 puts foo end RUBY end end context 'when an underscore-prefixed variable is reassigned' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def some_method _foo = 1 _foo = 2 end RUBY end end context 'when an underscore-prefixed method argument is used' do let(:source) { <<-RUBY } def some_method(_foo) puts _foo end RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['_foo']) end end context 'when an underscore-prefixed block argument is used' do let(:source) { <<-RUBY } 1.times do |_foo| puts _foo end RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['_foo']) end end context 'when an underscore-prefixed variable in top-level scope is used' do let(:source) { <<-RUBY } _foo = 1 puts _foo RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['_foo']) end end context 'when an underscore-prefixed variable is captured by a block' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) _foo = 1 1.times do _foo = 2 end RUBY end end context 'when an underscore-prefixed named capture variable is used' do let(:source) { <<-RUBY } /(?<_foo>\\w+)/ =~ 'FOO' puts _foo RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['/(?<_foo>\\w+)/']) end end %w[super binding].each do |keyword| context "in a method calling `#{keyword}` without arguments" do context 'when an underscore-prefixed argument is not used explicitly' do let(:source) { <<-RUBY } def some_method(*_) #{keyword} end RUBY it 'accepts' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end context 'when an underscore-prefixed argument is used explicitly' do let(:source) { <<-RUBY } def some_method(*_) #{keyword} puts _ end RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['_']) end end end context "in a method calling `#{keyword}` with arguments" do context 'when an underscore-prefixed argument is not used' do let(:source) { <<-RUBY } def some_method(*_) #{keyword}(:something) end RUBY it 'accepts' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end context 'when an underscore-prefixed argument is used explicitly' do let(:source) { <<-RUBY } def some_method(*_) #{keyword}(*_) end RUBY it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['_']) end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/unified_integer_spec.rb000066400000000000000000000035471322072016200241050ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnifiedInteger do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples 'registers an offence' do |klass| context "when #{klass}" do context 'without any decorations' do let(:source) { "1.is_a?(#{klass})" } it 'registers an offence' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(["Use `Integer` instead of `#{klass}`."]) end it 'autocorrects' do new_source = autocorrect_source(source) expect(new_source).to eq('1.is_a?(Integer)') end end context 'when explicitly specified as toplevel constant' do let(:source) { "1.is_a?(::#{klass})" } it 'registers an offence' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(["Use `Integer` instead of `#{klass}`."]) end it 'autocorrects' do new_source = autocorrect_source(source) expect(new_source).to eq('1.is_a?(::Integer)') end end context 'with MyNamespace' do let(:source) { "1.is_a?(MyNamespace::#{klass})" } include_examples 'accepts' end end end include_examples 'registers an offence', 'Fixnum' include_examples 'registers an offence', 'Bignum' context 'when Integer' do context 'without any decorations' do let(:source) { '1.is_a?(Integer)' } include_examples 'accepts' end context 'when explicitly specified as toplevel constant' do let(:source) { '1.is_a?(::Integer)' } include_examples 'accepts' end context 'with MyNamespace' do let(:source) { '1.is_a?(MyNamespace::Integer)' } include_examples 'accepts' end end end rubocop-0.52.1/spec/rubocop/cop/lint/unneeded_disable_spec.rb000066400000000000000000000366131322072016200242170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnneededDisable do describe '.check' do let(:cop) do cop = described_class.new cop.instance_variable_get(:@options)[:auto_correct] = true cop.processed_source = processed_source cop end let(:processed_source) do RuboCop::ProcessedSource.new(source, ruby_version) end let(:comments) { processed_source.comments } let(:corrected_source) do RuboCop::Cop::Corrector .new(processed_source.buffer, cop.corrections) .rewrite end before do cop.check(offenses, cop_disabled_line_ranges, comments) end context 'when there are no disabled lines' do let(:offenses) { [] } let(:cop_disabled_line_ranges) { {} } let(:source) { '' } it 'returns an empty array' do expect(cop.offenses).to eq([]) end end context 'when there are disabled lines' do context 'and there are no offenses' do let(:offenses) { [] } context 'and a comment disables' do context 'one cop' do let(:source) { "# rubocop:disable Metrics/MethodLength\n" } let(:cop_disabled_line_ranges) do { 'Metrics/MethodLength' => [1..Float::INFINITY] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Metrics/MethodLength`.']) expect(cop.highlights) .to eq(['# rubocop:disable Metrics/MethodLength']) end it 'gives the right cop name' do expect(cop.name).to eq('Lint/UnneededDisable') end it 'autocorrects' do expect(corrected_source).to eq('') end end context 'an unknown cop' do let(:source) { '# rubocop:disable UnknownCop' } let(:cop_disabled_line_ranges) do { 'UnknownCop' => [1..Float::INFINITY] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `UnknownCop` (unknown cop).']) expect(cop.highlights) .to eq(['# rubocop:disable UnknownCop']) end end context 'itself' do let(:source) { '# rubocop:disable Lint/UnneededDisable' } let(:cop_disabled_line_ranges) do { 'Lint/UnneededDisable' => [1..Float::INFINITY] } end it 'does not return an offense' do expect(cop.offenses.empty?).to be(true) end end context 'itself and another cop' do context 'disabled on the same range' do let(:source) do '# rubocop:disable Lint/UnneededDisable, Metrics/ClassLength' end let(:cop_disabled_line_ranges) do { 'Lint/UnneededDisable' => [1..Float::INFINITY], 'Metrics/ClassLength' => [1..Float::INFINITY] } end it 'does not return an offense' do expect(cop.offenses.empty?).to be(true) end end context 'disabled on different ranges' do let(:source) do ['# rubocop:disable Lint/UnneededDisable', '# rubocop:disable Metrics/ClassLength'].join("\n") end let(:cop_disabled_line_ranges) do { 'Lint/UnneededDisable' => [1..Float::INFINITY], 'Metrics/ClassLength' => [2..Float::INFINITY] } end it 'does not return an offense' do expect(cop.offenses.empty?).to be(true) end end context 'and the other cop is disabled a second time' do let(:source) do ['# rubocop:disable Lint/UnneededDisable', '# rubocop:disable Metrics/ClassLength', '# rubocop:disable Metrics/ClassLength'].join("\n") end let(:cop_disabled_line_ranges) do { 'Lint/UnneededDisable' => [1..Float::INFINITY], 'Metrics/ClassLength' => [(2..3), (3..Float::INFINITY)] } end it 'does not return an offense' do expect(cop.offenses.empty?).to be(true) end end end context 'multiple cops' do let(:source) do '# rubocop:disable Metrics/MethodLength, Metrics/ClassLength' end let(:cop_disabled_line_ranges) do { 'Metrics/ClassLength' => [1..Float::INFINITY], 'Metrics/MethodLength' => [1..Float::INFINITY] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Metrics/ClassLength`, ' \ '`Metrics/MethodLength`.']) end end context 'multiple cops, and one of them has offenses' do let(:source) do '# rubocop:disable Metrics/MethodLength, Metrics/ClassLength, ' \ 'Lint/Debugger, Lint/AmbiguousOperator' end let(:cop_disabled_line_ranges) do { 'Metrics/ClassLength' => [1..Float::INFINITY], 'Metrics/MethodLength' => [1..Float::INFINITY], 'Lint/Debugger' => [1..Float::INFINITY], 'Lint/AmbiguousOperator' => [1..Float::INFINITY] } end let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Class has too many lines.', 'Metrics/ClassLength') ] end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Metrics/MethodLength`.', 'Unnecessary disabling of `Lint/Debugger`.', 'Unnecessary disabling of `Lint/AmbiguousOperator`.']) expect(cop.highlights).to eq(['Metrics/MethodLength', 'Lint/Debugger', 'Lint/AmbiguousOperator']) end it 'autocorrects' do expect(corrected_source).to eq( '# rubocop:disable Metrics/ClassLength' ) end end context 'multiple cops, and the leftmost one has no offenses' do let(:source) do '# rubocop:disable Metrics/ClassLength, Metrics/MethodLength' end let(:cop_disabled_line_ranges) do { 'Metrics/ClassLength' => [1..Float::INFINITY], 'Metrics/MethodLength' => [1..Float::INFINITY] } end let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Method has too many lines.', 'Metrics/MethodLength') ] end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Metrics/ClassLength`.']) expect(cop.highlights).to eq(['Metrics/ClassLength']) end it 'autocorrects' do expect(corrected_source).to eq( '# rubocop:disable Metrics/MethodLength' ) end end context 'multiple cops, with abbreviated names' do context 'one of them has offenses' do let(:source) do '# rubocop:disable MethodLength, ClassLength, Debugger' end let(:cop_disabled_line_ranges) do { 'Metrics/ClassLength' => [1..Float::INFINITY], 'Metrics/MethodLength' => [1..Float::INFINITY], 'Lint/Debugger' => [1..Float::INFINITY] } end let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Method has too many lines.', 'Metrics/MethodLength') ] end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Metrics/ClassLength`.', 'Unnecessary disabling of `Lint/Debugger`.']) expect(cop.highlights).to eq(%w[ClassLength Debugger]) end end end context 'comment is not at the beginning of the file' do context 'and not all cops have offenses' do let(:source) do ['puts 1', '# rubocop:disable MethodLength, ClassLength'].join("\n") end let(:cop_disabled_line_ranges) do { 'Metrics/ClassLength' => [2..Float::INFINITY], 'Metrics/MethodLength' => [2..Float::INFINITY] } end let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Method has too many lines.', 'Metrics/MethodLength') ] end it 'registers an offense' do expect(cop.messages).to eq( ['Unnecessary disabling of `Metrics/ClassLength`.'] ) expect(cop.highlights).to eq(['ClassLength']) end end end context 'misspelled cops' do let(:source) do '# rubocop:disable Metrics/MethodLenght, KlassLength' end let(:cop_disabled_line_ranges) do { 'KlassLength' => [1..Float::INFINITY], 'Metrics/MethodLenght' => [1..Float::INFINITY] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `KlassLength` (unknown ' \ 'cop), `Metrics/MethodLenght` (did you mean ' \ '`Metrics/MethodLength`?).']) end end context 'all cops' do let(:source) { '# rubocop : disable all' } let(:cop_disabled_line_ranges) do { 'Metrics/MethodLength' => [1..Float::INFINITY], 'Metrics/ClassLength' => [1..Float::INFINITY], # etc... (no need to include all cops here) } end it 'returns an offense' do expect(cop.messages).to eq(['Unnecessary disabling of all cops.']) expect(cop.highlights).to eq([source]) end end context 'itself and all cops' do context 'disabled on different ranges' do let(:source) do ['# rubocop:disable Lint/UnneededDisable', '# rubocop:disable all'].join("\n") end let(:cop_disabled_line_ranges) do { 'Lint/UnneededDisable' => [1..Float::INFINITY], 'all' => [2..Float::INFINITY] } end it 'does not return an offense' do expect(cop.offenses.empty?).to be(true) end end end end end context 'and there are two offenses' do let(:message) do 'Replace class var @@class_var with a class instance var.' end let(:cop_name) { 'Style/ClassVars' } let(:offenses) do offense_lines.map do |line| RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: line, column: 3), message, cop_name) end end context 'and a comment disables' do context 'one cop twice' do let(:source) do ['class One', ' # rubocop:disable Style/ClassVars', ' @@class_var = 1', 'end', '', 'class Two', ' # rubocop:disable Style/ClassVars', ' @@class_var = 2', 'end'].join("\n") end let(:offense_lines) { [3, 8] } let(:cop_disabled_line_ranges) do { 'Style/ClassVars' => [2..7, 7..9] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Style/ClassVars`.']) expect(cop.highlights) .to eq(['# rubocop:disable Style/ClassVars']) end end context 'one cop and then all cops' do let(:source) do ['class One', ' # rubocop:disable Style/ClassVars', ' # rubocop:disable all', ' @@class_var = 1', 'end'].join("\n") end let(:offense_lines) { [4] } let(:cop_disabled_line_ranges) do { 'Style/ClassVars' => [2..3, 3..Float::INFINITY] } end it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Style/ClassVars`.']) expect(cop.highlights) .to eq(['# rubocop:disable Style/ClassVars']) end end end end context 'and there is an offense' do let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, OpenStruct.new(line: 7, column: 0), 'Tab detected.', 'Layout/Tab') ] end context 'and a comment disables' do context 'that cop' do let(:source) { '# rubocop:disable Layout/Tab' } let(:cop_disabled_line_ranges) { { 'Layout/Tab' => [1..100] } } it 'returns an empty array' do expect(cop.offenses.empty?).to be(true) end end context 'that cop but on other lines' do let(:source) { ("\n" * 9) << '# rubocop:disable Layout/Tab' } let(:cop_disabled_line_ranges) { { 'Layout/Tab' => [10..12] } } it 'returns an offense' do expect(cop.messages) .to eq(['Unnecessary disabling of `Layout/Tab`.']) expect(cop.highlights).to eq(['# rubocop:disable Layout/Tab']) end end context 'all cops' do let(:source) { '# rubocop : disable all' } let(:cop_disabled_line_ranges) do { 'Metrics/MethodLength' => [1..Float::INFINITY], 'Metrics/ClassLength' => [1..Float::INFINITY] # etc... (no need to include all cops here) } end it 'returns an empty array' do expect(cop.offenses.empty?).to be(true) end end end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/unneeded_require_statement_spec.rb000066400000000000000000000016641322072016200263520ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnneededRequireStatement, :config do subject(:cop) { described_class.new(config) } context 'target ruby version < 2.2', :ruby21 do it "does not registers an offense when using `require 'enumerator'`" do expect_no_offenses(<<-RUBY.strip_indent) require 'enumerator' RUBY end end context 'target ruby version >= 2.2', :ruby22 do it "registers an offense when using `require 'enumerator'`" do expect_offense(<<-RUBY.strip_indent) require 'enumerator' ^^^^^^^^^^^^^^^^^^^^ Remove unnecessary `require` statement. RUBY end it 'autocorrects remove unnecessary require statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) require 'enumerator' require 'uri' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) require 'uri' RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/unneeded_splat_expansion_spec.rb000066400000000000000000000300531322072016200260130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnneededSplatExpansion do subject(:cop) { described_class.new } let(:message) { 'Unnecessary splat expansion.' } let(:array_param_message) { 'Pass array contents as separate arguments.' } it 'allows assigning to a splat' do expect_no_offenses('*, rhs = *node') end it 'allows assigning to a splat variable' do expect_no_offenses('lhs, *args = *node') end it 'allows assigning a variable to a splat expansion of a variable' do expect_no_offenses('a = *b') end it 'allows assigning to an expanded range' do expect_no_offenses('a = *1..10') end it 'allows splat expansion inside of an array' do expect_no_offenses('a = [10, 11, *1..9]') end it 'accepts expanding a variable as a method parameter' do expect_no_offenses(<<-RUBY.strip_indent) foo = [1, 2, 3] array.push(*foo) RUBY end shared_examples 'splat literal assignment' do |literal| it 'registers an offense for ' do inspect_source("a = *#{literal}") expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(["*#{literal}"]) end end shared_examples 'array splat expansion' do |literal| context 'method parameters' do it 'registers an offense' do inspect_source("array.push(*#{literal})") expect(cop.messages).to eq([array_param_message]) expect(cop.highlights).to eq(["*#{literal}"]) end end it_behaves_like 'splat literal assignment', literal end shared_examples 'splat expansion' do |literal| context 'method parameters' do it 'registers an offense' do inspect_source("array.push(*#{literal})") expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(["*#{literal}"]) end end it_behaves_like 'splat literal assignment', literal end it_behaves_like 'array splat expansion', '[1, 2, 3]' it_behaves_like 'array splat expansion', '%w(one two three)' it_behaves_like 'array splat expansion', '%W(one #{two} three)' it_behaves_like 'splat expansion', "'a'" it_behaves_like 'splat expansion', '"#{a}"' it_behaves_like 'splat expansion', '1' it_behaves_like 'splat expansion', '1.1' context 'assignment to splat expansion' do it 'registers an offense for an array using a constructor' do expect_offense(<<-RUBY.strip_indent) a = *Array.new(3) { 42 } ^^^^^^^^^^^^^^^^^^^^ Unnecessary splat expansion. RUBY end end context 'expanding an array literal in a when condition' do it 'registers an offense for an array using []' do expect_offense(<<-RUBY.strip_indent) case foo when *[first, second] ^^^^^^^^^^^^^^^^ Unnecessary splat expansion. bar end RUBY end it 'registers an offense for an array using %w' do expect_offense(<<-RUBY.strip_indent) case foo when *%w(first second) ^^^^^^^^^^^^^^^^^ Unnecessary splat expansion. bar end RUBY end it 'registers an offense for an array using %W' do expect_offense(<<-'RUBY'.strip_indent) case foo when *%W(#{first} second) ^^^^^^^^^^^^^^^^^^^^ Unnecessary splat expansion. bar end RUBY end it 'allows an array that is assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) baz = [1, 2, 3] case foo when *baz bar end RUBY end it 'allows an array using a constructor' do expect_no_offenses(<<-RUBY.strip_indent) case foo when *Array.new(3) { 42 } bar end RUBY end end it 'registers an offense for an array literal being expanded in a rescue' do expect_offense(<<-RUBY.strip_indent) begin foo rescue *[First, Second] ^^^^^^^^^^^^^^^^ Unnecessary splat expansion. bar end RUBY end it 'allows expansions of an array that is assigned to a variable in rescue' do expect_no_offenses(<<-RUBY.strip_indent) ERRORS = [FirstError, SecondError] begin foo rescue *ERRORS bar end RUBY end it 'allows an array using a constructor' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue *Array.new(3) { 42 } bad_example end RUBY end it 'registers an offense for the expansion of an array literal' \ 'inside of an array literal' do inspect_source('[1, 2, *[3, 4, 5], 6, 7]') expect(cop.messages).to eq([array_param_message]) expect(cop.highlights).to eq(['*[3, 4, 5]']) end it 'allows expanding a method call on an array literal' do expect_no_offenses('[1, 2, *[3, 4, 5].map(&:to_s), 6, 7]') end describe 'expanding Array.new call on array literal' do context 'when the array literal contains exactly one element' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) [*Array.new(foo)] ^^^^^^^^^^^^^^^ Unnecessary splat expansion. RUBY end end context 'when the array literal contains more than one element' do it 'accepts' do expect_no_offenses('[1, 2, *Array.new(foo), 6]') end end end context 'autocorrect' do context 'assignment to a splat expanded variable' do it 'removes the splat from an array using []' do new_source = autocorrect_source('a = *[1, 2, 3]') expect(new_source).to eq('a = [1, 2, 3]') end it 'removes the splat from an array using %w' do new_source = autocorrect_source('a = *%w(one two three)') expect(new_source).to eq('a = %w(one two three)') end it 'removes the splat from an array using %W' do new_source = autocorrect_source('a = *%W(one two three)') expect(new_source).to eq('a = %W(one two three)') end it 'converts an expanded string to an array' do new_source = autocorrect_source("a = *'a'") expect(new_source).to eq("a = ['a']") end it 'converts an expanded string with interpolation to an array' do new_source = autocorrect_source('a = *"#{a}"') expect(new_source).to eq('a = ["#{a}"]') end it 'converts an expanded integer to an array' do new_source = autocorrect_source('a = *1') expect(new_source).to eq('a = [1]') end it 'converts an expanded float to an array' do new_source = autocorrect_source('a = *1.1') expect(new_source).to eq('a = [1.1]') end end context 'splat expansion in when condition' do it 'removes the square brackets' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *[1, 2, 3] bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 1, 2, 3 bar end RUBY end it 'changes %w to a list of words' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *%w(one two three) bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 'one', 'two', 'three' bar end RUBY end it 'changes %W to a list of words' do new_source = autocorrect_source(<<-'RUBY'.strip_indent) case foo when *%W(one #{two} three) bar end RUBY expect(new_source).to eq(<<-'RUBY'.strip_indent) case foo when "one", "#{two}", "three" bar end RUBY end end context 'rescuing splat expansion' do it 'changes an array literal to a list of constants' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin foo rescue *[First, Second] bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue First, Second bar end RUBY end end context 'splat expansion of method parameters' do it 'removes the splat and brackets from []' do new_source = autocorrect_source('foo(*[1, 2, 3])') expect(new_source).to eq('foo(1, 2, 3)') end it 'changes %w to a list of words' do new_source = autocorrect_source('foo(*%w(one two three))') expect(new_source).to eq("foo('one', 'two', 'three')") end it 'changes %W to a list of words' do new_source = autocorrect_source('foo(*%W(#{one} two three))') expect(new_source).to eq('foo("#{one}", "two", "three")') end end context 'splat expansion inside of an array' do it 'removes the splat and brackets from []' do new_source = autocorrect_source('[1, 2, *[3, 4, 5], 6, 7]') expect(new_source).to eq('[1, 2, 3, 4, 5, 6, 7]') end it 'changes %w to a list of words' do new_source = autocorrect_source("['a', 'b', *%w(c d e), 'f', 'g']") expect(new_source).to eq("['a', 'b', 'c', 'd', 'e', 'f', 'g']") end it 'changes %W to a list of words' do new_source = autocorrect_source('["a", "b", *%W(#{one} two)]') expect(new_source).to eq('["a", "b", "#{one}", "two"]') end end end it_behaves_like 'array splat expansion', '%i(first second)' it_behaves_like 'array splat expansion', '%I(first second #{third})' context 'arrays being expanded with %i variants using splat expansion' do it 'registers an offense for an array literal being expanded in a ' \ 'when condition' do inspect_source(<<-'RUBY'.strip_indent) case foo when *%i(first second) bar when *%I(#{first} second) baz end RUBY expect(cop.offenses.size).to eq(2) expect(cop.highlights).to eq(['*%i(first second)', '*%I(#{first} second)']) end context 'splat expansion of method parameters' do it 'registers an offense for an array literal %i' do expect_offense(<<-RUBY.strip_indent) array.push(*%i(first second)) ^^^^^^^^^^^^^^^^^ Pass array contents as separate arguments. RUBY end it 'registers an offense for an array literal %I' do expect_offense(<<-'RUBY'.strip_indent) array.push(*%I(#{first} second)) ^^^^^^^^^^^^^^^^^^^^ Pass array contents as separate arguments. RUBY end end context 'autocorrect' do it 'changes %i to a list of symbols' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *%i(first second) baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when :first, :second baz end RUBY end it 'changes %I to a list of symbols' do new_source = autocorrect_source(<<-'RUBY'.strip_indent) case foo when *%I(#{first} second) baz end RUBY expect(new_source).to eq(<<-'RUBY'.strip_indent) case foo when :"#{first}", :"second" baz end RUBY end end context 'splat expansion inside of an array' do it 'changes %i to a list of symbols' do new_source = autocorrect_source('[:a, :b, *%i(c d), :e]') expect(new_source).to eq('[:a, :b, :c, :d, :e]') end it 'changes %I to a list of symbols' do new_source = autocorrect_source('[:a, :b, *%I(#{one} two), :e]') expect(new_source).to eq('[:a, :b, :"#{one}", :"two", :e]') end context 'when Array.new is expanded' do context 'and the array contains exactly one element' do it 'removes the splat and brackets' do new_source = autocorrect_source('[*Array.new(foo)]') expect(new_source).to eq 'Array.new(foo)' end end end end end end rubocop-0.52.1/spec/rubocop/cop/lint/unreachable_code_spec.rb000066400000000000000000000072611322072016200242050ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnreachableCode do subject(:cop) { described_class.new } def wrap(str) head = <<-RUBY.strip_indent def something array.each do |item| RUBY tail = <<-RUBY.strip_indent end end RUBY body = str.strip_indent.each_line.map { |line| " #{line}" }.join head + body + tail end %w[return next break retry redo throw raise fail].each do |t| it "registers an offense for `#{t}` before other statements" do expect_offense(wrap(<<-RUBY)) #{t} bar ^^^ Unreachable code detected. RUBY end it "registers an offense for `#{t}` in `begin`" do expect_offense(wrap(<<-RUBY)) begin #{t} bar ^^^ Unreachable code detected. end RUBY end it "registers an offense for `#{t}` in all `if` branches" do expect_offense(wrap(<<-RUBY)) if cond #{t} else #{t} end bar ^^^ Unreachable code detected. RUBY end it "registers an offense for `#{t}` in all `if` branches" \ 'with other expressions' do expect_offense(wrap(<<-RUBY)) if cond something #{t} else something2 #{t} end bar ^^^ Unreachable code detected. RUBY end it "registers an offense for `#{t}` in all `if` and `elsif` branches" do expect_offense(wrap(<<-RUBY)) if cond something #{t} elsif cond2 something2 #{t} else something3 #{t} end bar ^^^ Unreachable code detected. RUBY end it "registers an offense for `#{t}` in all `case` branches" do expect_offense(wrap(<<-RUBY)) case cond when 1 something #{t} when 2 something2 #{t} else something3 #{t} end bar ^^^ Unreachable code detected. RUBY end it "accepts code with conditional `#{t}`" do expect_no_offenses(wrap(<<-RUBY)) #{t} if cond bar RUBY end it "accepts `#{t}` as the final expression" do expect_no_offenses(wrap(<<-RUBY)) #{t} if cond RUBY end it "accepts `#{t}` is in all `if` branchsi" do expect_no_offenses(wrap(<<-RUBY)) if cond #{t} else #{t} end RUBY end it "accepts `#{t}` is in `if` branch only" do expect_no_offenses(wrap(<<-RUBY)) if cond something #{t} else something2 end bar RUBY end it "accepts `#{t}` is in `if`, and without `else`" do expect_no_offenses(wrap(<<-RUBY)) if cond something #{t} end bar RUBY end it "accepts `#{t}` is in `else` branch only" do expect_no_offenses(wrap(<<-RUBY)) if cond something else something2 #{t} end bar RUBY end it "accepts `#{t}` is not in `elsif` branch" do expect_no_offenses(wrap(<<-RUBY)) if cond something #{t} elsif cond2 something2 else something3 #{t} end bar RUBY end it "accepts `#{t}` is in `case` branch without else" do expect_no_offenses(wrap(<<-RUBY)) case cond when 1 something #{t} when 2 something2 #{t} end bar RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/unused_block_argument_spec.rb000066400000000000000000000305761322072016200253260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnusedBlockArgument, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowUnusedKeywordArguments' => false } } shared_examples 'auto-correction' do |name, old_source, new_source| it "auto-corrects #{name}" do corrected_source = autocorrect_source(old_source) expect(corrected_source).to eq(new_source) end end context 'inspection' do context 'when a block takes multiple arguments' do context 'and an argument is unused' do it 'registers an offense' do message = "Unused block argument - `value`. If it's " \ 'necessary, use `_` or `_value` as an argument ' \ "name to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) hash.each do |key, value| ^^^^^ #{message} puts key end RUBY end end context 'and arguments are swap-assigned' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) hash.each do |key, value| key, value = value, key end RUBY end end context "and one argument is assigned to another, whilst other's value " \ 'is not used' do it 'registers an offense' do message = 'Unused block argument - `key`. ' \ "If it's necessary, use `_` or `_key` as an argument " \ "name to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) hash.each do |key, value| ^^^ #{message} key, value = value, 42 end RUBY end end context 'and all the arguments are unused' do it 'registers offenses and suggests omitting them' do (key_message, value_message) = %w[key value].map do |arg| "Unused block argument - `#{arg}`. You can omit all the " \ "arguments if you don't care about them." end expect_offense(<<-RUBY.strip_indent) hash = { foo: 'FOO', bar: 'BAR' } hash.each do |key, value| ^^^^^ #{value_message} ^^^ #{key_message} puts :something end RUBY end end end context 'when a block takes single argument' do context 'and the argument is unused' do it 'registers an offense and suggests omitting that' do message = 'Unused block argument - `index`. ' \ "You can omit the argument if you don't care about it." expect_offense(<<-RUBY.strip_indent) 1.times do |index| ^^^^^ #{message} puts :something end RUBY end end context 'and the method call is `define_method`' do it 'registers an offense' do message = 'Unused block argument - `bar`. ' \ "If it's necessary, use `_` or `_bar` as an argument " \ "name to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) define_method(:foo) do |bar| ^^^ #{message} puts 'baz' end RUBY end end end context 'when a block have a block local variable' do context 'and the variable is unused' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) 1.times do |index; block_local_variable| ^^^^^^^^^^^^^^^^^^^^ Unused block local variable - `block_local_variable`. puts index end RUBY end end end context 'when a lambda block takes arguments' do context 'and all the arguments are unused' do it 'registers offenses and suggests using a proc' do (foo_message, bar_message) = %w[foo bar].map do |arg| "Unused block argument - `#{arg}`. " \ "If it's necessary, use `_` or `_#{arg}` as an argument name " \ "to indicate that it won't be used. " \ 'Also consider using a proc without arguments instead of a ' \ "lambda if you want it to accept any arguments but don't care " \ 'about them.' end expect_offense(<<-RUBY.strip_indent) -> (foo, bar) { do_something } ^^^ #{bar_message} ^^^ #{foo_message} RUBY end end context 'and an argument is unused' do it 'registers an offense' do message = 'Unused block argument - `foo`. ' \ "If it's necessary, use `_` or `_foo` as an argument " \ "name to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) -> (foo, bar) { puts bar } ^^^ #{message} RUBY end end end context 'when an underscore-prefixed block argument is not used' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) 1.times do |_index| puts 'foo' end RUBY end end context 'when an optional keyword argument is unused' do context 'when the method call is `define_method`' do it 'registers an offense' do message = 'Unused block argument - `bar`. ' \ "If it's necessary, use `_` or `_bar` as an argument name " \ "to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) define_method(:foo) do |bar: 'default'| ^^^ #{message} puts 'bar' end RUBY end context 'when AllowUnusedKeywordArguments set' do let(:cop_config) { { 'AllowUnusedKeywordArguments' => true } } it 'does not care' do expect_no_offenses(<<-RUBY.strip_indent) define_method(:foo) do |bar: 'default'| puts 'bar' end RUBY end end end context 'when the method call is not `define_method`' do it 'registers an offense' do message = 'Unused block argument - `bar`. ' \ "You can omit the argument if you don't care about it." expect_offense(<<-RUBY.strip_indent) foo(:foo) do |bar: 'default'| ^^^ #{message} puts 'bar' end RUBY end context 'when AllowUnusedKeywordArguments set' do let(:cop_config) { { 'AllowUnusedKeywordArguments' => true } } it 'does not care' do expect_no_offenses(<<-RUBY.strip_indent) foo(:foo) do |bar: 'default'| puts 'bar' end RUBY end end end end context 'when a method argument is not used' do it 'does not care' do expect_no_offenses(<<-RUBY.strip_indent) def some_method(foo) end RUBY end end context 'when a variable is not used' do it 'does not care' do expect_no_offenses(<<-RUBY.strip_indent) 1.times do foo = 1 end RUBY end end context 'in a method calling `binding` without arguments' do it 'accepts all arguments' do expect_no_offenses(<<-RUBY.strip_indent) test do |key, value| puts something(binding) end RUBY end context 'inside a method definition' do it 'registers offenses' do (key_message, value_message) = %w[key value].map do |arg| "Unused block argument - `#{arg}`. You can omit all the " \ "arguments if you don't care about them." end expect_offense(<<-RUBY.strip_indent) test do |key, value| ^^^^^ #{value_message} ^^^ #{key_message} def other(a) puts something(binding) end end RUBY end end end context 'in a method calling `binding` with arguments' do context 'when a method argument is unused' do it 'registers an offense' do (key_message, value_message) = %w[key value].map do |arg| "Unused block argument - `#{arg}`. You can omit all the " \ "arguments if you don't care about them." end expect_offense(<<-RUBY.strip_indent) test do |key, value| ^^^^^ #{value_message} ^^^ #{key_message} puts something(binding(:other)) end RUBY end end end context 'with an empty block' do context 'when not configured to ignore empty blocks' do let(:cop_config) { { 'IgnoreEmptyBlocks' => false } } it 'registers an offense' do message = 'Unused block argument - `bar`. You can omit the ' \ "argument if you don't care about it." expect_offense(<<-RUBY.strip_indent) super { |bar| } ^^^ #{message} RUBY end end context 'when configured to ignore empty blocks' do let(:cop_config) { { 'IgnoreEmptyBlocks' => true } } it 'does not register an offense' do expect_no_offenses('super { |bar| }') end end end end context 'auto-correct' do it_behaves_like( 'auto-correction', 'fixes single', 'arr.map { |foo| stuff }', 'arr.map { |_foo| stuff }' ) it_behaves_like( 'auto-correction', 'fixes multiple', 'hash.map { |key, val| stuff }', 'hash.map { |_key, _val| stuff }' ) it_behaves_like( 'auto-correction', 'preserves whitespace', <<-SOURCE, hash.map { |key, val| stuff } SOURCE <<-CORRECTED_SOURCE hash.map { |_key, _val| stuff } CORRECTED_SOURCE ) it_behaves_like( 'auto-correction', 'preserves splat', 'obj.method { |foo, *bars, baz| stuff(foo, baz) }', 'obj.method { |foo, *_bars, baz| stuff(foo, baz) }' ) it_behaves_like( 'auto-correction', 'preserves default', 'obj.method { |foo, bar = baz| stuff(foo) }', 'obj.method { |foo, _bar = baz| stuff(foo) }' ) it 'ignores used arguments' do original_source = 'obj.method { |foo, baz| stuff(foo, baz) }' expect(autocorrect_source(original_source)).to eq(original_source) end end context 'when IgnoreEmptyBlocks config parameter is set' do let(:cop_config) { { 'IgnoreEmptyBlocks' => true } } it 'accepts an empty block with a single unused parameter' do expect_no_offenses('->(arg) { }') end it 'registers an offense for a non-empty block with an unused parameter' do message = "Unused block argument - `arg`. If it's necessary, use `_` " \ "or `_arg` as an argument name to indicate that it won't " \ 'be used. Also consider using a proc without arguments ' \ 'instead of a lambda if you want it to accept any arguments ' \ "but don't care about them." expect_offense(<<-RUBY.strip_indent) ->(arg) { 1 } ^^^ #{message} RUBY end it 'accepts an empty block with multiple unused parameters' do expect_no_offenses('->(arg1, arg2, *others) { }') end it 'registers an offense for a non-empty block with multiple unused args' do (arg1_message, arg2_message, others_message) = %w[arg1 arg2 others] .map do |arg| "Unused block argument - `#{arg}`. If it's necessary, use `_` or " \ "`_#{arg}` as an argument name to indicate that it won't be used. " \ 'Also consider using a proc without arguments instead of a lambda ' \ "if you want it to accept any arguments but don't care about them." end expect_offense(<<-RUBY.strip_indent) ->(arg1, arg2, *others) { 1 } ^^^^^^ #{others_message} ^^^^ #{arg2_message} ^^^^ #{arg1_message} RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/unused_method_argument_spec.rb000066400000000000000000000310151322072016200255010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UnusedMethodArgument, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'AllowUnusedKeywordArguments' => false, 'IgnoreEmptyMethods' => false } end describe 'inspection' do context 'when a method takes multiple arguments' do context 'and an argument is unused' do it 'registers an offense' do message = 'Unused method argument - `foo`. ' \ "If it's necessary, use `_` or `_foo` " \ "as an argument name to indicate that it won't be used." expect_offense(<<-RUBY.strip_indent) def some_method(foo, bar) ^^^ #{message} puts bar end RUBY end context 'and arguments are swap-assigned' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a, b) a, b = b, a end RUBY end end context "and one argument is assigned to another, whilst other's " \ 'value is not used' do it 'registers an offense' do message = "Unused method argument - `a`. If it's necessary, use " \ '`_` or `_a` as an argument name to indicate that ' \ "it won't be used." expect_offense(<<-RUBY.strip_indent) def foo(a, b) ^ #{message} a, b = b, 42 end RUBY end end end context 'and all the arguments are unused' do it 'registers offenses and suggests the use of `*`' do (foo_message, bar_message) = %w[foo bar].map do |arg| "Unused method argument - `#{arg}`. " \ "If it's necessary, use `_` or `_#{arg}` " \ "as an argument name to indicate that it won't be used. " \ 'You can also write as `some_method(*)` if you want the method ' \ "to accept any arguments but don't care about them." end expect_offense(<<-RUBY.strip_indent) def some_method(foo, bar) ^^^ #{bar_message} ^^^ #{foo_message} end RUBY end end end context 'when a required keyword argument is unused', ruby: 2.1 do it 'registers an offense but does not suggest underscore-prefix' do expect_offense(<<-RUBY.strip_indent) def self.some_method(foo, bar:) ^^^ Unused method argument - `bar`. puts foo end RUBY end end context 'when an optional keyword argument is unused' do it 'registers an offense but does not suggest underscore-prefix' do expect_offense(<<-RUBY.strip_indent) def self.some_method(foo, bar: 1) ^^^ Unused method argument - `bar`. puts foo end RUBY end context 'and AllowUnusedKeywordArguments set' do let(:cop_config) { { 'AllowUnusedKeywordArguments' => true } } it 'does not care' do expect_no_offenses(<<-RUBY.strip_indent) def self.some_method(foo, bar: 1) puts foo end RUBY end end end context 'when a singleton method argument is unused' do it 'registers an offense' do message = "Unused method argument - `foo`. If it's necessary, use " \ '`_` or `_foo` as an argument name to indicate that it ' \ "won't be used. You can also write as `some_method(*)` " \ 'if you want the method to accept any arguments but ' \ "don't care about them." expect_offense(<<-RUBY.strip_indent) def self.some_method(foo) ^^^ #{message} end RUBY end end context 'when an underscore-prefixed method argument is unused' do let(:source) { <<-RUBY.strip_indent } def some_method(_foo) end RUBY it 'accepts' do expect_no_offenses(source) end end context 'when a method argument is used' do let(:source) { <<-RUBY.strip_indent } def some_method(foo) puts foo end RUBY it 'accepts' do expect_no_offenses(source) end end context 'when a variable is unused' do let(:source) { <<-RUBY.strip_indent } def some_method foo = 1 end RUBY it 'does not care' do expect_no_offenses(source) end end context 'when a block argument is unused' do let(:source) { <<-RUBY.strip_indent } 1.times do |foo| end RUBY it 'does not care' do expect_no_offenses(source) end end context 'in a method calling `super` without arguments' do context 'when a method argument is not used explicitly' do it 'accepts since the arguments are guaranteed to be the same as ' \ "superclass' ones and the user has no control on them" do expect_no_offenses(<<-RUBY.strip_indent) def some_method(foo) super end RUBY end end end context 'in a method calling `super` with arguments' do context 'when a method argument is unused' do it 'registers an offense' do message = "Unused method argument - `foo`. If it's necessary, use " \ '`_` or `_foo` as an argument name to indicate that ' \ "it won't be used. You can also write as " \ '`some_method(*)` if you want the method to accept any ' \ "arguments but don't care about them." expect_offense(<<-RUBY.strip_indent) def some_method(foo) ^^^ #{message} super(:something) end RUBY end end end context 'in a method calling `binding` without arguments' do let(:source) { <<-RUBY.strip_indent } def some_method(foo, bar) do_something binding end RUBY it 'accepts all arguments' do expect_no_offenses(source) end context 'inside another method definition' do (foo_message, bar_message) = %w[foo bar].map do |arg| "Unused method argument - `#{arg}`. If it's necessary, use `_` or " \ "`_#{arg}` as an argument name to indicate that it won't be " \ 'used. You can also write as `some_method(*)` if you want the ' \ "method to accept any arguments but don't care about them." end it 'registers offenses' do expect_offense(<<-RUBY.strip_indent) def some_method(foo, bar) ^^^ #{bar_message} ^^^ #{foo_message} def other(a) puts something(binding) end end RUBY end end end context 'in a method calling `binding` with arguments' do context 'when a method argument is unused' do it 'registers an offense' do message = "Unused method argument - `foo`. If it's necessary, use " \ '`_` or `_foo` as an argument name to indicate that it ' \ "won't be used. You can also write as `some_method(*)` " \ 'if you want the method to accept any arguments but ' \ "don't care about them." expect_offense(<<-RUBY.strip_indent) def some_method(foo) ^^^ #{message} binding(:something) end RUBY end end end end describe 'auto-correction' do let(:corrected_source) { autocorrect_source(source) } context 'when multiple arguments are unused' do let(:source) { <<-RUBY } def some_method(foo, bar) end RUBY let(:expected_source) { <<-RUBY } def some_method(_foo, _bar) end RUBY it 'adds underscore-prefix to them' do expect(corrected_source).to eq(expected_source) end end context 'when only a part of arguments is unused' do let(:source) { <<-RUBY } def some_method(foo, bar) puts foo end RUBY let(:expected_source) { <<-RUBY } def some_method(foo, _bar) puts foo end RUBY it 'modifies only the unused one' do expect(corrected_source).to eq(expected_source) end end context 'when there is some whitespace around the argument' do let(:source) { <<-RUBY } def some_method(foo, bar) puts foo end RUBY let(:expected_source) { <<-RUBY } def some_method(foo, _bar) puts foo end RUBY it 'preserves the whitespace' do expect(corrected_source).to eq(expected_source) end end context 'when a splat argument is unused' do let(:source) { <<-RUBY } def some_method(foo, *bar) puts foo end RUBY let(:expected_source) { <<-RUBY } def some_method(foo, *_bar) puts foo end RUBY it 'preserves the splat' do expect(corrected_source).to eq(expected_source) end end context 'when an unused argument has default value' do let(:source) { <<-RUBY } def some_method(foo, bar = 1) puts foo end RUBY let(:expected_source) { <<-RUBY } def some_method(foo, _bar = 1) puts foo end RUBY it 'preserves the default value' do expect(corrected_source).to eq(expected_source) end end context 'when a keyword argument is unused' do let(:source) { <<-RUBY } def some_method(foo, bar: 1) puts foo end RUBY it 'ignores that since modifying the name changes the method interface' do expect(corrected_source).to eq(source) end end context 'when a trailing block argument is unused' do let(:source) { <<-RUBY } def some_method(foo, bar, &block) foo + bar end RUBY let(:expected_source) { <<-RUBY } def some_method(foo, bar) foo + bar end RUBY it 'removes the unused block arg' do expect(corrected_source).to eq(expected_source) end end end context 'when IgnoreEmptyMethods config parameter is set' do let(:cop_config) { { 'IgnoreEmptyMethods' => true } } it 'accepts an empty method with a single unused parameter' do expect_no_offenses(<<-RUBY.strip_indent) def method(arg) end RUBY end it 'accepts an empty singleton method with a single unused parameter' do expect_no_offenses(<<-RUBY.strip_indent) def self.method(unused) end RUBY end it 'registers an offense for a non-empty method with a single unused ' \ 'parameter' do message = "Unused method argument - `arg`. If it's necessary, use " \ '`_` or `_arg` as an argument name to indicate that it ' \ "won't be used. You can also write as `method(*)` if you " \ "want the method to accept any arguments but don't care " \ 'about them.' expect_offense(<<-RUBY.strip_indent) def method(arg) ^^^ #{message} 1 end RUBY end it 'accepts an empty method with multiple unused parameters' do expect_no_offenses(<<-RUBY.strip_indent) def method(a, b, *others) end RUBY end it 'registers an offense for a non-empty method with multiple unused ' \ 'parameters' do (a_message, b_message, others_message) = %w[a b others].map do |arg| "Unused method argument - `#{arg}`. If it's necessary, use `_` or " \ "`_#{arg}` as an argument name to indicate that it won't be used. " \ 'You can also write as `method(*)` if you want the method ' \ "to accept any arguments but don't care about them." end expect_offense(<<-RUBY.strip_indent) def method(a, b, *others) ^^^^^^ #{others_message} ^ #{b_message} ^ #{a_message} 1 end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/uri_escape_unescape_spec.rb000066400000000000000000000067431322072016200247500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UriEscapeUnescape do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it "registers an offense when using `URI.escape('http://example.com')`" do expect_offense(<<-RUBY.strip_indent) URI.escape('http://example.com') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `URI.escape` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. RUBY end it "registers an offense when using `URI.escape('@?@!', '!?')`" do expect_offense(<<-RUBY.strip_indent) URI.escape('@?@!', '!?') ^^^^^^^^^^^^^^^^^^^^^^^^ `URI.escape` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. RUBY end it "registers an offense when using `::URI.escape('http://example.com')`" do expect_offense(<<-RUBY.strip_indent) ::URI.escape('http://example.com') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `::URI.escape` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. RUBY end it "registers an offense when using `URI.encode('http://example.com')`" do expect_offense(<<-RUBY.strip_indent) URI.encode('http://example.com') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `URI.encode` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. RUBY end it "registers an offense when using `::URI.encode('http://example.com)`" do expect_offense(<<-RUBY.strip_indent) ::URI.encode('http://example.com') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `::URI.encode` method is obsolete and should not be used. Instead, use `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component` depending on your specific use case. RUBY end it 'registers an offense when using `URI.unescape(enc_uri)`' do expect_offense(<<-RUBY.strip_indent) URI.unescape(enc_uri) ^^^^^^^^^^^^^^^^^^^^^ `URI.unescape` method is obsolete and should not be used. Instead, use `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` depending on your specific use case. RUBY end it 'registers an offense when using `::URI.unescape(enc_uri)`' do expect_offense(<<-RUBY.strip_indent) ::URI.unescape(enc_uri) ^^^^^^^^^^^^^^^^^^^^^^^ `::URI.unescape` method is obsolete and should not be used. Instead, use `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` depending on your specific use case. RUBY end it 'registers an offense when using `URI.decode(enc_uri)`' do expect_offense(<<-RUBY.strip_indent) URI.decode(enc_uri) ^^^^^^^^^^^^^^^^^^^ `URI.decode` method is obsolete and should not be used. Instead, use `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` depending on your specific use case. RUBY end it 'registers an offense when using `::URI.decode(enc_uri)`' do expect_offense(<<-RUBY.strip_indent) ::URI.decode(enc_uri) ^^^^^^^^^^^^^^^^^^^^^ `::URI.decode` method is obsolete and should not be used. Instead, use `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component` depending on your specific use case. RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/uri_regexp_spec.rb000066400000000000000000000042651322072016200231140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UriRegexp do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `URI.regexp` with argument' do expect_offense(<<-RUBY.strip_indent) URI.regexp('http://example.com') ^^^^^^ `URI.regexp('http://example.com')` is obsolete and should not be used. Instead, use `URI::DEFAULT_PARSER.make_regexp('http://example.com')`. RUBY end it 'registers an offense when using `::URI.regexp` with argument' do expect_offense(<<-RUBY.strip_indent) ::URI.regexp('http://example.com') ^^^^^^ `::URI.regexp('http://example.com')` is obsolete and should not be used. Instead, use `::URI::DEFAULT_PARSER.make_regexp('http://example.com')`. RUBY end it 'registers an offense when using `URI.regexp` without argument' do expect_offense(<<-RUBY.strip_indent) URI.regexp ^^^^^^ `URI.regexp` is obsolete and should not be used. Instead, use `URI::DEFAULT_PARSER.make_regexp`. RUBY end it 'registers an offense when using `::URI.regexp` without argument' do expect_offense(<<-RUBY.strip_indent) ::URI.regexp ^^^^^^ `::URI.regexp` is obsolete and should not be used. Instead, use `::URI::DEFAULT_PARSER.make_regexp`. RUBY end it "autocorrects URI::DEFAULT_PARSER.make_regexp('http://example.com')" do new_source = autocorrect_source("URI.regexp('http://example.com')") expect( new_source ).to eq "URI::DEFAULT_PARSER.make_regexp('http://example.com')" end it "autocorrects ::URI::DEFAULT_PARSER.make_regexp('http://example.com')" do new_source = autocorrect_source("::URI.regexp('http://example.com')") expect( new_source ).to eq "::URI::DEFAULT_PARSER.make_regexp('http://example.com')" end it 'autocorrects URI::DEFAULT_PARSER.make_regexp' do new_source = autocorrect_source('URI.regexp') expect(new_source).to eq 'URI::DEFAULT_PARSER.make_regexp' end it 'autocorrects ::URI::DEFAULT_PARSER.make_regexp' do new_source = autocorrect_source('::URI.regexp') expect(new_source).to eq '::URI::DEFAULT_PARSER.make_regexp' end end rubocop-0.52.1/spec/rubocop/cop/lint/useless_access_modifier_spec.rb000066400000000000000000000564621322072016200256330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UselessAccessModifier do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } context 'when an access modifier has no effect' do let(:source) do <<-RUBY.strip_indent class SomeClass def some_method puts 10 end private def self.some_method puts 10 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `private` access modifier.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['private']) end end context 'when an access modifier has no methods' do let(:source) do <<-RUBY.strip_indent class SomeClass def some_method puts 10 end protected end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `protected` access modifier.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['protected']) end end context 'when an access modifier is followed by attr_*' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass protected attr_accessor :some_property public attr_reader :another_one private attr :yet_again, true protected attr_writer :just_for_good_measure end RUBY end end context 'when an access modifier is followed by a ' \ 'class method defined on constant' do let(:source) do <<-RUBY.strip_indent class SomeClass protected def SomeClass.some_method end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `protected` access modifier.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['protected']) end end context 'when there are consecutive access modifiers' do let(:source) do <<-RUBY.strip_indent class SomeClass private private def some_method puts 10 end def some_other_method puts 10 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `private` access modifier.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['private']) end end context 'when passing method as symbol' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass def some_method puts 10 end private :some_method end RUBY end end context 'when class is empty save modifier' do let(:source) do <<-RUBY.strip_indent class SomeClass private end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `private` access modifier.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['private']) end end context 'when multiple class definitions in file but only one has offense' do let(:source) do <<-RUBY.strip_indent class SomeClass private end class SomeOtherClass end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless `private` access modifier.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['private']) end end if RUBY_ENGINE == 'ruby' && RUBY_VERSION.start_with?('2.1') context 'ruby 2.1 style modifiers' do let(:source) do <<-RUBY.strip_indent class SomeClass private def some_method puts 10 end end RUBY end it 'does not register an offense' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end end context 'when only a constant or local variable is defined after the ' \ 'modifier' do %w[CONSTANT some_var].each do |binding_name| it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class SomeClass private ^^^^^^^ Useless `private` access modifier. #{binding_name} = 1 end RUBY end end end context 'when a def is an argument to a method call' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass private helper_method def some_method puts 10 end end RUBY end end context "when using ActiveSupport's `concerning` method" do let(:config) do RuboCop::Config.new( 'Lint/UselessAccessModifier' => { 'ContextCreatingMethods' => ['concerning'] } ) end it 'is aware that this creates a new scope' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass concerning :FirstThing do def foo end private def method end end concerning :SecondThing do def omg end private def method end end end RUBY end it 'still points out redundant uses within the block' do src = <<-RUBY.strip_indent class SomeClass concerning :FirstThing do def foo end private def method end end concerning :SecondThing do def omg end private def method end private def another_method end end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(17) end end context 'when using ActiveSupport behavior when Rails is not eabled' do it 'reports offenses' do src = <<-RUBY.strip_indent module SomeModule extend ActiveSupport::Concern class_methods do def some_public_class_method end private def some_private_class_method end end def some_public_instance_method end private def some_private_instance_method end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end context 'when using the class_methods method from ActiveSupport::Concern' do let(:config) do RuboCop::Config.new( 'Lint/UselessAccessModifier' => { 'ContextCreatingMethods' => ['class_methods'] } ) end it 'is aware that this creates a new scope' do expect_no_offenses(<<-RUBY.strip_indent) module SomeModule extend ActiveSupport::Concern class_methods do def some_public_class_method end private def some_private_class_method end end def some_public_instance_method end private def some_private_instance_method end end RUBY end end context 'when using a known method-creating method' do let(:config) do RuboCop::Config.new( 'Lint/UselessAccessModifier' => { 'MethodCreatingMethods' => ['delegate'] } ) end it 'is aware that this creates a new method' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass private delegate :foo, to: :bar end RUBY end it 'still points out redundant uses within the module' do src = <<-RUBY.strip_indent class SomeClass delegate :foo, to: :bar private end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(4) end end shared_examples 'at the top of the body' do |keyword| it 'registers an offense for `public`' do src = <<-RUBY.strip_indent #{keyword} A public def method end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it "doesn't register an offense for `protected`" do src = <<-RUBY.strip_indent #{keyword} A protected def method end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it "doesn't register an offense for `private`" do src = <<-RUBY.strip_indent #{keyword} A private def method end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end shared_examples 'repeated visibility modifiers' do |keyword, modifier| it "registers an offense when `#{modifier}` is repeated" do src = <<-RUBY.strip_indent #{keyword} A #{modifier == 'private' ? 'protected' : 'private'} def method1 end #{modifier} #{modifier} def method2 end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end shared_examples 'non-repeated visibility modifiers' do |keyword| it 'registers an offense even when `public` is not repeated' do src = <<-RUBY.strip_indent #{keyword} A def method1 end public def method2 end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it "doesn't register an offense when `protected` is not repeated" do src = <<-RUBY.strip_indent #{keyword} A def method1 end protected def method2 end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it "doesn't register an offense when `private` is not repeated" do src = <<-RUBY.strip_indent #{keyword} A def method1 end private def method2 end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end shared_examples 'at the end of the body' do |keyword, modifier| it "registers an offense for trailing `#{modifier}`" do src = <<-RUBY.strip_indent #{keyword} A def method1 end def method2 end #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end shared_examples 'nested in a begin..end block' do |keyword, modifier| it "still flags repeated `#{modifier}`" do src = <<-RUBY.strip_indent #{keyword} A #{modifier == 'private' ? 'protected' : 'private'} def blah end begin def method1 end #{modifier} #{modifier} def method2 end end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end unless modifier == 'public' it "doesn't flag an access modifier from surrounding scope" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} begin def method1 end end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end end shared_examples 'unused visibility modifiers' do |keyword| it 'registers an error when visibility is immediately changed ' \ 'without any intervening defs' do src = <<-RUBY.strip_indent #{keyword} A private def method1 end public # bad private def method2 end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end shared_examples 'conditionally defined method' do |keyword, modifier| %w[if unless].each do |conditional_type| it "doesn't register an offense for #{conditional_type}" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} #{conditional_type} x def method1 end end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end end shared_examples 'methods defined in an iteration' do |keyword, modifier| %w[each map].each do |iteration_method| it "doesn't register an offense for #{iteration_method}" do src = ["#{keyword} A", " #{modifier}", " [1, 2].#{iteration_method} do |i|", ' define_method("method#{i}") do', ' i', ' end', ' end', 'end'] inspect_source(src) expect(cop.offenses.empty?).to be(true) end end end shared_examples 'method defined with define_method' do |keyword, modifier| it "doesn't register an offense if a block is passed" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} define_method(:method1) do end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end %w[lambda proc ->].each do |proc_type| it "doesn't register an offense if a #{proc_type} is passed" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} define_method(:method1, #{proc_type} { }) end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end end shared_examples 'method defined on a singleton class' do |keyword, modifier| context 'inside a class' do it "doesn't register an offense if a method is defined" do src = <<-RUBY.strip_indent #{keyword} A class << self #{modifier} define_method(:method1) do end end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it "doesn't register an offense if the modifier is the same as " \ 'outside the meta-class' do src = <<-RUBY.strip_indent #{keyword} A #{modifier} def method1 end class << self #{modifier} def method2 end end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'registers an offense if no method is defined' do src = <<-RUBY.strip_indent #{keyword} A class << self #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers an offense if no method is defined after the modifier' do src = <<-RUBY.strip_indent #{keyword} A class << self def method1 end #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers an offense even if a non-singleton-class method is ' \ 'defined' do src = <<-RUBY.strip_indent #{keyword} A def method1 end class << self #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end context 'outside a class' do it "doesn't register an offense if a method is defined" do src = <<-RUBY.strip_indent class << A #{modifier} define_method(:method1) do end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'registers an offense if no method is defined' do src = <<-RUBY.strip_indent class << A #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers an offense if no method is defined after the modifier' do src = <<-RUBY.strip_indent class << A def method1 end #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end end shared_examples 'method defined using class_eval' do |modifier| it "doesn't register an offense if a method is defined" do src = <<-RUBY.strip_indent A.class_eval do #{modifier} define_method(:method1) do end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'registers an offense if no method is defined' do src = <<-RUBY.strip_indent A.class_eval do #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end context 'inside a class' do it 'registers an offense when a modifier is ouside the block and a ' \ 'method is defined only inside the block' do src = <<-RUBY.strip_indent class A #{modifier} A.class_eval do def method1 end end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers two offenses when a modifier is inside and outside the ' \ ' and no method is defined' do src = <<-RUBY.strip_indent class A #{modifier} A.class_eval do #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(2) end end end shared_examples 'def in new block' do |klass, modifier| it "doesn't register an offense if a method is defined in #{klass}.new" do src = <<-RUBY.strip_indent #{klass}.new do #{modifier} def foo end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it "registers an offense if no method is defined in #{klass}.new" do src = <<-RUBY.strip_indent #{klass}.new do #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end shared_examples 'method defined using instance_eval' do |modifier| it "doesn't register an offense if a method is defined" do src = <<-RUBY.strip_indent A.instance_eval do #{modifier} define_method(:method1) do end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'registers an offense if no method is defined' do src = <<-RUBY.strip_indent A.instance_eval do #{modifier} end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end context 'inside a class' do it 'registers an offense when a modifier is ouside the block and a ' \ 'method is defined only inside the block' do src = <<-RUBY.strip_indent class A #{modifier} self.instance_eval do def method1 end end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers two offenses when a modifier is inside and outside the ' \ ' and no method is defined' do src = <<-RUBY.strip_indent class A #{modifier} self.instance_eval do #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(2) end end end shared_examples 'nested modules' do |keyword, modifier| it "doesn't register an offense for nested #{keyword}s" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} def method1 end #{keyword} B def method2 end #{modifier} def method3 end end end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end context 'unused modifiers' do it "registers an offense with a nested #{keyword}" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} #{keyword} B #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(2) end it "registers an offense when outside a nested #{keyword}" do src = <<-RUBY.strip_indent #{keyword} A #{modifier} #{keyword} B def method1 end end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it "registers an offense when inside a nested #{keyword}" do src = <<-RUBY.strip_indent #{keyword} A #{keyword} B #{modifier} end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end end end %w[protected private].each do |modifier| it_behaves_like('method defined using class_eval', modifier) it_behaves_like('method defined using instance_eval', modifier) end %w[Class Module Struct].each do |klass| %w[protected private].each do |modifier| it_behaves_like('def in new block', klass, modifier) end end %w[module class].each do |keyword| it_behaves_like('at the top of the body', keyword) it_behaves_like('non-repeated visibility modifiers', keyword) it_behaves_like('unused visibility modifiers', keyword) %w[public protected private].each do |modifier| it_behaves_like('repeated visibility modifiers', keyword, modifier) it_behaves_like('at the end of the body', keyword, modifier) it_behaves_like('nested in a begin..end block', keyword, modifier) next if modifier == 'public' it_behaves_like('conditionally defined method', keyword, modifier) it_behaves_like('methods defined in an iteration', keyword, modifier) it_behaves_like('method defined with define_method', keyword, modifier) it_behaves_like('method defined on a singleton class', keyword, modifier) it_behaves_like('nested modules', keyword, modifier) end end end rubocop-0.52.1/spec/rubocop/cop/lint/useless_assignment_spec.rb000066400000000000000000001364451322072016200246640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UselessAssignment do subject(:cop) { described_class.new } context 'when a variable is assigned and unreferenced in a method' do let(:source) do <<-RUBY.strip_indent class SomeClass foo = 1 puts foo def some_method foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced ' \ 'in a singleton method defined with self keyword' do let(:source) do <<-RUBY.strip_indent class SomeClass foo = 1 puts foo def self.some_method foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced ' \ 'in a singleton method defined with variable name' do let(:source) do <<-RUBY.strip_indent 1.times do foo = 1 puts foo instance = Object.new def instance.some_method foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced in a class' do let(:source) do <<-RUBY.strip_indent 1.times do foo = 1 puts foo class SomeClass foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced in a class ' \ 'subclassing another class stored in local variable' do let(:source) do <<-RUBY.strip_indent 1.times do foo = 1 puts foo array_class = Array class SomeClass < array_class foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced ' \ 'in a singleton class' do let(:source) do <<-RUBY.strip_indent 1.times do foo = 1 puts foo instance = Object.new class << instance foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced in a module' do let(:source) do <<-RUBY.strip_indent 1.times do foo = 1 puts foo module SomeModule foo = 2 bar = 3 puts bar end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned and unreferenced in top level' do let(:source) do <<-RUBY.strip_indent foo = 1 bar = 2 puts bar RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned with operator assignment ' \ 'in top level' do let(:source) do 'foo ||= 1' end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Useless assignment to variable - `foo`. Use `||` instead of `||=`.' ) expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned multiple times ' \ 'but unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 bar = 2 foo = 3 puts bar end RUBY end it 'registers offenses for each assignment' do inspect_source(source) expect(cop.offenses.size).to eq(2) expect(cop.offenses[0].message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses[0].line).to eq(2) expect(cop.offenses[1].message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses[1].line).to eq(4) expect(cop.highlights).to eq(%w[foo foo]) end end context 'when a referenced variable is reassigned ' \ 'but not re-referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo foo = 3 end RUBY end it 'registers an offense for the non-re-referenced assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(4) expect(cop.highlights).to eq(['foo']) end end context 'when an unreferenced variable is reassigned ' \ 'and re-referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 foo = 3 puts foo end RUBY end it 'registers an offense for the unreferenced assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when an unreferenced variable is reassigned in a block' do let(:source) do <<-RUBY.strip_indent def const_name(node) const_names = [] const_node = node loop do namespace_node, name = *const_node const_names << name break unless namespace_node break if namespace_node.type == :cbase const_node = namespace_node end const_names.reverse.join('::') end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a referenced variable is reassigned in a block' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 puts foo 1.times do foo = 2 end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a block local variable is declared but not assigned' do let(:source) do <<-RUBY.strip_indent 1.times do |i; foo| end RUBY end include_examples 'accepts' end context 'when a block local variable is assigned and unreferenced' do let(:source) do <<-RUBY.strip_indent 1.times do |i; foo| foo = 2 end RUBY end it 'registers offenses for the assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned in loop body and unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method while true foo = 1 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned at the end of loop body ' \ 'and would be referenced in next iteration' do let(:source) do <<-RUBY.strip_indent def some_method total = 0 foo = 0 while total < 100 total += foo foo += 1 end total end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned at the end of loop body ' \ 'and would be referenced in loop condition' do let(:source) do <<-RUBY.strip_indent def some_method total = 0 foo = 0 while foo < 100 total += 1 foo += 1 end total end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a setter is invoked with operator assignment in loop body' do let(:source) do <<-RUBY.strip_indent def some_method obj = {} while obj[:count] < 100 obj[:count] += 1 end end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context "when a variable is reassigned in loop body but won't " \ 'be referenced either next iteration or loop condition' do let(:source) do <<-RUBY.strip_indent def some_method total = 0 foo = 0 while total < 100 total += 1 foo += 1 end total end RUBY end it 'registers an offense' do pending 'Requires an advanced logic that checks whether the return ' \ 'value of an operator assignment is used or not.' inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(7) expect(cop.highlights).to eq(['foo']) end end context 'when a referenced variable is reassigned ' \ 'but not re-referenced in a method defined in loop' do let(:source) do <<-RUBY.strip_indent while true def some_method foo = 1 puts foo foo = 3 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(5) expect(cop.highlights).to eq(['foo']) end end context 'when a variable that has same name as outer scope variable ' \ 'is not referenced in a method defined in loop' do let(:source) do <<-RUBY.strip_indent foo = 1 while foo < 100 foo += 1 def some_method foo = 1 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned in single branch if ' \ 'and unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method(flag) if flag foo = 1 end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a unreferenced variable is reassigned in same branch ' \ 'and referenced after the branching' do let(:source) do <<-RUBY.strip_indent def some_method(flag) if flag foo = 1 foo = 2 end foo end RUBY end it 'registers an offense for the unreferenced assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is reassigned in single branch if ' \ 'and referenced after the branching' do let(:source) do <<-RUBY.strip_indent def some_method(flag) foo = 1 if flag foo = 2 end foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned in a loop' do context 'while loop' do let(:source) do <<-RUBY.strip_indent def while(param) ret = 1 while param != 10 param += 2 ret = param + 1 end ret end RUBY end include_examples 'accepts' end context 'post while loop' do let(:source) do <<-RUBY.strip_indent def post_while(param) ret = 1 begin param += 2 ret = param + 1 end while param < 40 ret end RUBY end include_examples 'accepts' end context 'until loop' do let(:source) do <<-RUBY.strip_indent def until(param) ret = 1 until param == 10 param += 2 ret = param + 1 end ret end RUBY end include_examples 'accepts' end context 'post until loop' do let(:source) do <<-RUBY.strip_indent def post_until(param) ret = 1 begin param += 2 ret = param + 1 end until param == 10 ret end RUBY end include_examples 'accepts' end context 'for loop' do let(:source) do <<-RUBY.strip_indent def for(param) ret = 1 for x in param...10 param += x ret = param + 1 end ret end RUBY end include_examples 'accepts' end end context 'when a variable is assigned in each branch of if ' \ 'and referenced after the branching' do let(:source) do <<-RUBY.strip_indent def some_method(flag) if flag foo = 2 else foo = 3 end foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned in single branch if ' \ 'and referenced in the branch' do let(:source) do <<-RUBY.strip_indent def some_method(flag) foo = 1 if flag foo = 2 puts foo end end RUBY end it 'registers an offense for the unreferenced assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned in each branch of if ' \ 'and referenced in the else branch' do let(:source) do <<-RUBY.strip_indent def some_method(flag) if flag foo = 2 else foo = 3 puts foo end end RUBY end it 'registers an offense for the assignment in the if branch' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is reassigned and unreferenced in a if branch ' \ 'while the variable is referenced in the paired else branch ' do let(:source) do <<-RUBY.strip_indent def some_method(flag) foo = 1 if flag puts foo foo = 2 else puts foo end end RUBY end it 'registers an offense for the reassignment in the if branch' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context "when there's an unreferenced assignment in top level if branch " \ 'while the variable is referenced in the paired else branch' do let(:source) do <<-RUBY.strip_indent if flag foo = 1 else puts foo end RUBY end it 'registers an offense for the assignment in the if branch' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context "when there's an unreferenced reassignment in a if branch " \ 'while the variable is referenced in the paired elsif branch' do let(:source) do <<-RUBY.strip_indent def some_method(flag_a, flag_b) foo = 1 if flag_a puts foo foo = 2 elsif flag_b puts foo end end RUBY end it 'registers an offense for the reassignment in the if branch' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context "when there's an unreferenced reassignment in a if branch " \ 'while the variable is referenced in a case branch ' \ 'in the paired else branch' do let(:source) do <<-RUBY.strip_indent def some_method(flag_a, flag_b) foo = 1 if flag_a puts foo foo = 2 else case when flag_b puts foo end end end RUBY end it 'registers an offense for the reassignment in the if branch' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context 'when an assignment in a if branch is referenced ' \ 'in another if branch' do let(:source) do <<-RUBY.strip_indent def some_method(flag_a, flag_b) if flag_a foo = 1 end if flag_b puts foo end end RUBY end include_examples 'accepts' end context 'when a variable is assigned in branch of modifier if ' \ 'that references the variable in its conditional clause' \ 'and referenced after the branching' do let(:source) do <<-RUBY.strip_indent def some_method(flag) foo = 1 unless foo puts foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned in branch of modifier if ' \ 'that references the variable in its conditional clause' \ 'and unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method(flag) foo = 1 unless foo end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned on each side of && ' \ 'and referenced after the &&' do let(:source) do <<-RUBY.strip_indent def some_method (foo = do_something_returns_object_or_nil) && (foo = 1) foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a unreferenced variable is reassigned ' \ 'on the left side of && and referenced after the &&' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 (foo = do_something_returns_object_or_nil) && do_something foo end RUBY end it 'registers an offense for the unreferenced assignment' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when a unreferenced variable is reassigned ' \ 'on the right side of && and referenced after the &&' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 do_something_returns_object_or_nil && foo = 2 foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned ' \ 'while referencing itself in rhs and referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = [1, 2] foo = foo.map { |i| i + 1 } puts foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned ' \ 'with binary operator assignment and referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 foo += 1 foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned ' \ 'with logical operator assignment and referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = do_something_returns_object_or_nil foo ||= 1 foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned with binary operator ' \ 'assignment while assigning to itself in rhs ' \ 'then referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 foo += foo = 2 foo end RUBY end it 'registers an offense for the assignment in rhs' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned first with ||= and referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo ||= 1 foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned with ||= ' \ 'at the last expression of the scope' do let(:source) do <<-RUBY.strip_indent def some_method foo = do_something_returns_object_or_nil foo ||= 1 end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Useless assignment to variable - `foo`. Use `||` instead of `||=`.' ) expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned with ||= ' \ 'before the last expression of the scope' do let(:source) do <<-RUBY.strip_indent def some_method foo = do_something_returns_object_or_nil foo ||= 1 some_return_value end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned with multiple assignment ' \ 'and unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method foo, bar = do_something puts foo end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Useless assignment to variable - `bar`. ' \ 'Use `_` or `_bar` as a variable name ' \ "to indicate that it won't be used." ) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['bar']) end include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned with multiple assignment ' \ 'while referencing itself in rhs and referenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 foo, bar = do_something(foo) puts foo, bar end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned in loop body ' \ 'and referenced in post while condition' do let(:source) do <<-RUBY.strip_indent begin a = (a || 0) + 1 puts a end while a <= 2 RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned in loop body ' \ 'and referenced in post until condition' do let(:source) do <<-RUBY.strip_indent begin a = (a || 0) + 1 puts a end until a > 2 RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned ' \ 'in main body of begin with rescue but unreferenced' do let(:source) do <<-RUBY.strip_indent begin do_something foo = true rescue do_anything end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned in main body of begin, rescue ' \ 'and else then referenced after the begin' do let(:source) do <<-RUBY.strip_indent begin do_something foo = :in_begin rescue FirstError foo = :in_first_rescue rescue SecondError foo = :in_second_rescue else foo = :in_else end puts foo RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned multiple times ' \ 'in main body of begin then referenced after the begin' do let(:source) do <<-RUBY.strip_indent begin status = :initial connect_sometimes_fails! status = :connected fetch_sometimes_fails! status = :fetched rescue do_something end puts status RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned multiple times ' \ 'in main body of begin then referenced in rescue' do let(:source) do <<-RUBY.strip_indent begin status = :initial connect_sometimes_fails! status = :connected fetch_sometimes_fails! status = :fetched rescue puts status end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned multiple times ' \ 'in main body of begin then referenced in ensure' do let(:source) do <<-RUBY.strip_indent begin status = :initial connect_sometimes_fails! status = :connected fetch_sometimes_fails! status = :fetched ensure puts status end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is reassigned multiple times in rescue ' \ 'and referenced after the begin' do let(:source) do <<-RUBY.strip_indent foo = false begin do_something rescue foo = true foo = true end puts foo RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is reassigned multiple times ' \ 'in rescue with ensure then referenced after the begin' do let(:source) do <<-RUBY.strip_indent foo = false begin do_something rescue foo = true foo = true ensure do_anything end puts foo RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is reassigned multiple times ' \ 'in ensure with rescue then referenced after the begin' do let(:source) do <<-RUBY.strip_indent begin do_something rescue do_anything ensure foo = true foo = true end puts foo RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(6) expect(cop.highlights).to eq(['foo']) end end context 'when a variable is assigned at the end of rescue ' \ 'and would be referenced with retry' do let(:source) do <<-RUBY.strip_indent retried = false begin do_something rescue fail if retried retried = true retry end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned with operator assignment ' \ 'in rescue and would be referenced with retry' do let(:source) do <<-RUBY.strip_indent retry_count = 0 begin do_something rescue fail if (retry_count += 1) > 3 retry end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is assigned ' \ 'in main body of begin, rescue and else ' \ 'and reassigned in ensure then referenced after the begin' do let(:source) do <<-RUBY.strip_indent begin do_something foo = :in_begin rescue FirstError foo = :in_first_rescue rescue SecondError foo = :in_second_rescue else foo = :in_else ensure foo = :in_ensure end puts foo RUBY end it 'registers offenses for each assignment before ensure' do inspect_source(source) expect(cop.offenses.size).to eq(4) expect(cop.offenses[0].line).to eq(3) expect(cop.offenses[1].line).to eq(5) expect(cop.offenses[2].line).to eq(7) expect(cop.offenses[3].line).to eq(9) end end context 'when a rescued error variable is wrongly tried to be referenced ' \ 'in another rescue body' do let(:source) do <<-RUBY.strip_indent begin do_something rescue FirstError => error rescue SecondError p error # => nil end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `error`.') expect(cop.offenses.first.line).to eq(3) expect(cop.highlights).to eq(['error']) end end context 'when a method argument is reassigned ' \ 'and zero arity super is called' do let(:source) do <<-RUBY.strip_indent def some_method(foo) foo = 1 super end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a local variable is unreferenced ' \ 'and zero arity super is called' do let(:source) do <<-RUBY.strip_indent def some_method(bar) foo = 1 super end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a method argument is reassigned ' \ 'but not passed to super' do let(:source) do <<-RUBY.strip_indent def some_method(foo, bar) foo = 1 super(bar) end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end end context 'when a named capture is unreferenced in top level' do let(:source) do "/(?\w+)/ =~ 'FOO'" end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(1) end include_examples 'mimics MRI 2.1' end context 'when a named capture is unreferenced ' \ 'in other than top level' do let(:source) do <<-RUBY.strip_indent def some_method /(?\\w+)/ =~ 'FOO' end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['/(?\w+)/']) end end context 'when a named capture is referenced' do let(:source) do <<-RUBY.strip_indent def some_method /(?\w+)(?\s+)/ =~ 'FOO' puts foo puts bar end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is referenced ' \ 'in rhs of named capture expression' do let(:source) do <<-RUBY.strip_indent def some_method foo = 'some string' /(?\w+)/ =~ foo puts foo end RUBY end include_examples 'accepts' end context 'when a variable is assigned in begin ' \ 'and referenced outside' do let(:source) do <<-RUBY.strip_indent def some_method begin foo = 1 end puts foo end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a variable is shadowed by a block argument ' \ 'and unreferenced' do let(:source) do <<-RUBY.strip_indent def some_method foo = 1 1.times do |foo| puts foo end end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1', 'unused variable' end context 'when a variable is not used and the name starts with _' do let(:source) do <<-RUBY.strip_indent def some_method _foo = 1 bar = 2 puts bar end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(arg) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when an optional method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(arg = nil) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a block method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(&block) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a splat method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(*args) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a optional keyword method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(name: value) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a keyword splat method argument is used' do let(:source) do <<-RUBY.strip_indent def some_method(name: value, **rest_keywords) p rest_keywords end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a keyword splat method argument is not used' do let(:source) do <<-RUBY.strip_indent def some_method(name: value, **rest_keywords) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when an anonymous keyword splat method argument is defined' do let(:source) do <<-RUBY.strip_indent def some_method(name: value, **) end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when a block argument is not used' do let(:source) do <<-RUBY.strip_indent 1.times do |i| end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'when there is only one AST node and it is unused variable' do let(:source) do 'foo = 1' end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end context 'when a variable is assigned ' \ 'while being passed to a method taking block' do context 'and the variable is used' do let(:source) do <<-RUBY.strip_indent some_method(foo = 1) do end puts foo RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end context 'and the variable is not used' do let(:source) do <<-RUBY.strip_indent some_method(foo = 1) do end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `foo`.') expect(cop.offenses.first.line).to eq(1) expect(cop.highlights).to eq(['foo']) end include_examples 'mimics MRI 2.1' end end context 'when a variable is assigned ' \ 'and passed to a method followed by method taking block' do let(:source) do <<-RUBY.strip_indent pattern = '*.rb' Dir.glob(pattern).map do |path| end RUBY end include_examples 'accepts' include_examples 'mimics MRI 2.1' end # regression test, from problem in Locatable context 'when a variable is assigned in 2 identical if branches' do it "doesn't think 1 of the 2 assignments is useless" do expect_no_offenses(<<-RUBY.strip_indent) def foo if bar foo = 1 else foo = 1 end foo.bar.baz end RUBY end end describe 'similar name suggestion' do context "when there's a similar variable-like method invocation" do let(:source) do <<-RUBY.strip_indent def some_method enviromnent = {} another_symbol puts environment end RUBY end it 'suggests the method name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Useless assignment to variable - `enviromnent`. ' \ 'Did you mean `environment`?' ) end end context "when there's a similar variable" do let(:source) do <<-RUBY.strip_indent def some_method environment = nil another_symbol enviromnent = {} puts environment end RUBY end it 'suggests the variable name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Useless assignment to variable - `enviromnent`. ' \ 'Did you mean `environment`?' ) end end context 'when there are only less similar names' do let(:source) do <<-RUBY.strip_indent def some_method enviromnent = {} another_symbol puts envelope end RUBY end it 'does not suggest any name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `enviromnent`.') end end context "when there's a similar method invocation with explicit receiver" do let(:source) do <<-RUBY.strip_indent def some_method enviromnent = {} another_symbol puts self.environment end RUBY end it 'does not suggest any name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `enviromnent`.') end end context "when there's a similar method invocation with arguments" do let(:source) do <<-RUBY.strip_indent def some_method enviromnent = {} another_symbol puts environment(1) end RUBY end it 'does not suggest any name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `enviromnent`.') end end context "when there's a similar name but it's in inner scope" do let(:source) do <<-RUBY.strip_indent class SomeClass enviromnent = {} def some_method(environment) puts environment end end RUBY end it 'does not suggest any name' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Useless assignment to variable - `enviromnent`.') end end end end rubocop-0.52.1/spec/rubocop/cop/lint/useless_comparison_spec.rb000066400000000000000000000014301322072016200246470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UselessComparison do subject(:cop) { described_class.new } described_class::OPS.each do |op| it "registers an offense for a simple comparison with #{op}" do inspect_source(<<-RUBY.strip_indent) 5 #{op} 5 a #{op} a RUBY expect(cop.offenses.size).to eq(2) end it "registers an offense for a complex comparison with #{op}" do inspect_source(<<-RUBY.strip_indent) 5 + 10 * 30 #{op} 5 + 10 * 30 a.top(x) #{op} a.top(x) RUBY expect(cop.offenses.size).to eq(2) end end it 'works with lambda.()' do expect_offense(<<-RUBY.strip_indent) a.(x) > a.(x) ^ Comparison of something with itself detected. RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/useless_else_without_rescue_spec.rb000066400000000000000000000021511322072016200265570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UselessElseWithoutRescue do subject(:cop) { described_class.new } before do inspect_source(source) end context 'with `else` without `rescue`' do let(:source) do <<-RUBY.strip_indent begin do_something else handle_unknown_errors end RUBY end it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('`else` without `rescue` is useless.') expect(cop.highlights).to eq(['else']) end end context 'with `else` with `rescue`' do let(:source) do <<-RUBY.strip_indent begin do_something rescue ArgumentError handle_argument_error else handle_unknown_errors end RUBY end it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) begin do_something rescue ArgumentError handle_argument_error else handle_unknown_errors end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/lint/useless_setter_call_spec.rb000066400000000000000000000122571322072016200250070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::UselessSetterCall do subject(:cop) { described_class.new } context 'with method ending with setter call on local object' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def test top = Top.new top.attr = 5 ^^^ Useless setter call to local variable `top`. end RUBY end end context 'with singleton method ending with setter call on local object' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def Top.test top = Top.new top.attr = 5 ^^^ Useless setter call to local variable `top`. end RUBY end end context 'with method ending with square bracket setter on local object' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def test top = Top.new top[:attr] = 5 ^^^ Useless setter call to local variable `top`. end RUBY end end context 'with method ending with ivar assignment' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def test something @top = 5 end RUBY end end context 'with method ending with setter call on ivar' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def test something @top.attr = 5 end RUBY end end context 'with method ending with setter call on argument' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def test(some_arg) unrelated_local_variable = Top.new some_arg.attr = 5 end RUBY end end context 'when a lvar contains an object passed as argument ' \ 'at the end of the method' do it 'accepts the setter call on the lvar' do expect_no_offenses(<<-RUBY.strip_indent) def test(some_arg) @some_ivar = some_arg @some_ivar.do_something some_lvar = @some_ivar some_lvar.do_something some_lvar.attr = 5 end RUBY end end context 'when a lvar contains an object passed as argument ' \ 'by multiple-assignment at the end of the method' do it 'accepts the setter call on the lvar' do expect_no_offenses(<<-RUBY.strip_indent) def test(some_arg) _first, some_lvar, _third = 1, some_arg, 3 some_lvar.attr = 5 end RUBY end end context 'when a lvar does not contain any object passed as argument ' \ 'with multiple-assignment at the end of the method' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def test(some_arg) _first, some_lvar, _third = do_something some_lvar.attr = 5 ^^^^^^^^^ Useless setter call to local variable `some_lvar`. end RUBY end end context 'when a lvar possibly contains an object passed as argument ' \ 'by logical-operator-assignment at the end of the method' do it 'accepts the setter call on the lvar' do expect_no_offenses(<<-RUBY.strip_indent) def test(some_arg) some_lvar = nil some_lvar ||= some_arg some_lvar.attr = 5 end RUBY end end context 'when a lvar does not contain any object passed as argument ' \ 'by binary-operator-assignment at the end of the method' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def test(some_arg) some_lvar = some_arg some_lvar += some_arg some_lvar.attr = 5 ^^^^^^^^^ Useless setter call to local variable `some_lvar`. end RUBY end end context 'when a lvar declared as an argument ' \ 'is no longer the passed object at the end of the method' do it 'registers an offense for the setter call on the lvar' do expect_offense(<<-RUBY.strip_indent) def test(some_arg) some_arg = Top.new some_arg.attr = 5 ^^^^^^^^ Useless setter call to local variable `some_arg`. end RUBY end end context 'when a lvar contains a local object instantiated with literal' do it 'registers an offense for the setter call on the lvar' do expect_offense(<<-RUBY.strip_indent) def test some_arg = {} some_arg[:attr] = 1 ^^^^^^^^ Useless setter call to local variable `some_arg`. end RUBY end end context 'when a lvar contains a non-local object returned by a method' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) def test some_lvar = Foo.shared_object some_lvar[:attr] = 1 end RUBY end end it 'is not confused by operators ending with =' do expect_no_offenses(<<-RUBY.strip_indent) def test top.attr == 5 end RUBY end it 'handles exception assignments without exploding' do expect_no_offenses(<<-RUBY.strip_indent) def foo(bar) begin rescue StandardError => _ end bar[:baz] = true end RUBY end end rubocop-0.52.1/spec/rubocop/cop/lint/void_spec.rb000066400000000000000000000101071322072016200216740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Lint::Void do subject(:cop) { described_class.new } described_class::BINARY_OPERATORS.each do |op| it "registers an offense for void op #{op} if not on last line" do inspect_source(<<-RUBY.strip_indent) a #{op} b a #{op} b a #{op} b RUBY expect(cop.offenses.size).to eq(2) end end described_class::BINARY_OPERATORS.each do |op| it "accepts void op #{op} if on last line" do expect_no_offenses(<<-RUBY.strip_indent) something a #{op} b RUBY end end described_class::BINARY_OPERATORS.each do |op| it "accepts void op #{op} by itself without a begin block" do expect_no_offenses("a #{op} b") end end unary_operators = %i[+ - ~ !] unary_operators.each do |op| it "registers an offense for void op #{op} if not on last line" do inspect_source(<<-RUBY.strip_indent) #{op}b #{op}b #{op}b RUBY expect(cop.offenses.size).to eq(2) end end unary_operators.each do |op| it "accepts void op #{op} if on last line" do expect_no_offenses(<<-RUBY.strip_indent) something #{op}b RUBY end end unary_operators.each do |op| it "accepts void op #{op} by itself without a begin block" do expect_no_offenses("#{op}b") end end %w[var @var @@var VAR $var].each do |var| it "registers an offense for void var #{var} if not on last line" do inspect_source(["#{var} = 5", var, 'top']) expect(cop.offenses.size).to eq(1) end end %w(1 2.0 :test /test/ [1] {}).each do |lit| it "registers an offense for void lit #{lit} if not on last line" do inspect_source([lit, 'top']) expect(cop.offenses.size).to eq(1) end end it 'registers an offense for void `self` if not on last line' do expect_offense(<<-RUBY.strip_indent) self; top ^^^^ `self` used in void context. RUBY end it 'registers an offense for void `defined?` if not on last line' do expect_offense(<<-RUBY.strip_indent) defined?(x) ^^^^^^^^^^^ `defined?(x)` used in void context. top RUBY end it 'registers an offense for void literal in a method definition' do expect_offense(<<-RUBY.strip_indent) def something 42 ^^ Literal `42` used in void context. 42 end RUBY end it 'registers two offenses for void literals in an initialize method' do expect_offense(<<-RUBY.strip_indent) def initialize 42 ^^ Literal `42` used in void context. 42 ^^ Literal `42` used in void context. end RUBY end it 'registers two offenses for void literals in a setter method' do expect_offense(<<-RUBY.strip_indent) def foo=(rhs) 42 ^^ Literal `42` used in void context. 42 ^^ Literal `42` used in void context. end RUBY end it 'registers two offenses for void literals in a `#each` method' do expect_offense(<<-RUBY.strip_indent) array.each do |_item| 42 ^^ Literal `42` used in void context. 42 ^^ Literal `42` used in void context. end RUBY end it 'registers two offenses for void literals in a `for`' do expect_offense(<<-RUBY.strip_indent) for _item in array do 42 ^^ Literal `42` used in void context. 42 ^^ Literal `42` used in void context. end RUBY end it 'handles explicit begin blocks' do expect_offense(<<-RUBY.strip_indent) begin 1 ^ Literal `1` used in void context. 2 end RUBY end it 'accepts short call syntax' do expect_no_offenses(<<-RUBY.strip_indent) lambda.(a) top RUBY end it 'accepts backtick commands' do expect_no_offenses(<<-RUBY.strip_indent) `touch x` nil RUBY end it 'accepts percent-x commands' do expect_no_offenses(<<-RUBY.strip_indent) %x(touch x) nil RUBY end end rubocop-0.52.1/spec/rubocop/cop/message_annotator_spec.rb000066400000000000000000000104221322072016200234760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::MessageAnnotator do let(:options) { {} } let(:config) { RuboCop::Config.new({}) } let(:annotator) { described_class.new(config, config['Cop/Cop'], options) } describe '#annotate' do subject(:annotate) do annotator.annotate('message', 'Cop/Cop') end context 'with default options' do it 'returns the message' do expect(annotate).to eq('message') end end context 'with options on' do let(:options) do { extra_details: true, display_cop_names: true, display_style_guide: true } end let(:config) do RuboCop::Config.new( 'Cop/Cop' => { 'Details' => 'my cop details', 'StyleGuide' => 'http://example.org/styleguide' } ) end it 'returns an annotated message' do expect(annotate).to eq( 'Cop/Cop: message my cop details (http://example.org/styleguide)' ) end end end describe 'with style guide url' do subject(:annotate) do annotator.annotate('', 'Cop/Cop') end let(:options) do { display_style_guide: true } end context 'when StyleGuide is not set in the config' do let(:config) { RuboCop::Config.new({}) } it 'does not add style guide url' do expect(annotate).to eq('') end end context 'when StyleGuide is set in the config' do let(:config) do RuboCop::Config.new( 'Cop/Cop' => { 'StyleGuide' => 'http://example.org/styleguide' } ) end it 'adds style guide url' do expect(annotate).to include('http://example.org/styleguide') end end context 'when a base URL is specified' do let(:config) do RuboCop::Config.new( 'AllCops' => { 'StyleGuideBaseURL' => 'http://example.org/styleguide' } ) end it 'does not specify a URL if a cop does not have one' do config['Cop/Cop'] = { 'StyleGuide' => nil } expect(annotate).to eq('') end it 'combines correctly with a target-based setting' do config['Cop/Cop'] = { 'StyleGuide' => '#target_based_url' } expect(annotate).to include('http://example.org/styleguide#target_based_url') end it 'can use a path-based setting' do config['Cop/Cop'] = { 'StyleGuide' => 'cop/path/rule#target_based_url' } expect(annotate).to include('http://example.org/cop/path/rule#target_based_url') end it 'can accept relative paths if base has a full path' do config['AllCops'] = { 'StyleGuideBaseURL' => 'http://github.com/bbatsov/ruby-style-guide/' } config['Cop/Cop'] = { 'StyleGuide' => '../rails-style-guide#target_based_url' } expect(annotate).to include('http://github.com/bbatsov/rails-style-guide#target_based_url') end it 'allows absolute URLs in the cop config' do config['Cop/Cop'] = { 'StyleGuide' => 'http://other.org#absolute_url' } expect(annotate).to include('http://other.org#absolute_url') end end end describe '#urls' do let(:urls) { annotator.urls } let(:config) do RuboCop::Config.new( 'AllCops' => { 'StyleGuideBaseURL' => 'http://example.org/styleguide' } ) end it 'returns an empty array without StyleGuide URL' do expect(urls.empty?).to be(true) end it 'returns style guide url when it is specified' do config['Cop/Cop'] = { 'StyleGuide' => '#target_based_url' } expect(urls).to eq(%w[http://example.org/styleguide#target_based_url]) end it 'returns reference url when it is specified' do config['Cop/Cop'] = { 'Reference' => 'https://example.com/some_style_guide' } expect(urls).to eq(%w[https://example.com/some_style_guide]) end it 'returns style guide and reference url when they are specified' do config['Cop/Cop'] = { 'StyleGuide' => '#target_based_url', 'Reference' => 'https://example.com/some_style_guide' } expect(urls).to eq(%w[http://example.org/styleguide#target_based_url https://example.com/some_style_guide]) end end end rubocop-0.52.1/spec/rubocop/cop/metrics/000077500000000000000000000000001322072016200200755ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/metrics/abc_size_spec.rb000066400000000000000000000105401322072016200232130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::AbcSize, :config do subject(:cop) { described_class.new(config) } context 'when Max is 0' do let(:cop_config) { { 'Max' => 0 } } it 'accepts an empty method' do expect_no_offenses(<<-RUBY.strip_indent) def method_name end RUBY end it 'accepts an empty `define_method`' do expect_no_offenses(<<-RUBY.strip_indent) define_method :method_name do end RUBY end it 'registers an offense for an if modifier' do inspect_source(<<-RUBY.strip_indent) def method_name call_foo if some_condition # 0 + 2*2 + 1*1 end RUBY expect(cop.messages) .to eq(['Assignment Branch Condition size for method_name is too ' \ 'high. [2.24/0]']) expect(cop.highlights).to eq([<<-RUBY.strip_indent.chomp]) def method_name call_foo if some_condition # 0 + 2*2 + 1*1 end RUBY expect(cop.config_to_allow_offenses).to eq('Max' => 3) end it 'registers an offense for an assignment of a local variable' do inspect_source(<<-RUBY.strip_indent) def method_name x = 1 end RUBY expect(cop.messages) .to eq(['Assignment Branch Condition size for method_name is too ' \ 'high. [1/0]']) expect(cop.config_to_allow_offenses).to eq('Max' => 1) end it 'registers an offense for an assignment of an element' do inspect_source(<<-RUBY.strip_indent) def method_name x[0] = 1 end RUBY expect(cop.messages) .to eq(['Assignment Branch Condition size for method_name is too ' \ 'high. [1.41/0]']) expect(cop.config_to_allow_offenses).to eq('Max' => 2) end it 'registers an offense for complex content including A, B, and C ' \ 'scores' do inspect_source(<<-RUBY.strip_indent) def method_name my_options = Hash.new if 1 == 1 || 2 == 2 # 1, 3, 2 my_options.each do |key, value| # 0, 1, 0 p key # 0, 1, 0 p value # 0, 1, 0 end end RUBY expect(cop.messages) .to eq(['Assignment Branch Condition size for method_name is too ' \ 'high. [6.4/0]']) # sqrt(1*1 + 6*6 + 2*2) => 6.4 end it 'registers an offense for a `define_method`' do expect_offense(<<-RUBY.strip_indent) define_method :method_name do ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Assignment Branch Condition size for method_name is too high. [1/0] x = 1 end RUBY end context 'target_ruby_version >= 2.3', :ruby23 do it 'treats safe navigation method calls like regular method calls' do expect_offense(<<-RUBY.strip_indent) # sqrt(0 + 2*2 + 0) => 2 def method_name ^^^^^^^^^^^^^^^ Assignment Branch Condition size for method_name is too high. [2/0] object&.do_something end RUBY end end end context 'when Max is 2' do let(:cop_config) { { 'Max' => 2 } } it 'accepts two assignments' do expect_no_offenses(<<-RUBY.strip_indent) def method_name x = 1 y = 2 end RUBY end end context 'when Max is 1.8' do let(:cop_config) { { 'Max' => 1.8 } } it 'accepts a total score of 1.7' do expect_no_offenses(<<-RUBY.strip_indent) def method_name y = 1 if y == 1 end RUBY end end { 1.3 => '3.74/1.3', # no more than 2 decimals reported 10.3 => '37.42/10.3', 100.321 => '374.2/100.3', # 4 significant digits, so only 1 decimal here 1000.3 => '3742/1000' }.each do |max, presentation| context "when Max is #{max}" do let(:cop_config) { { 'Max' => max } } it "reports size and max as #{presentation}" do # Build an amount of code large enough to register an offense. code = [' x = Hash.new if 1 == 1 || 2 == 2'] * max inspect_source(['def method_name', *code, 'end']) expect(cop.messages) .to eq(['Assignment Branch Condition size for method_name is too ' \ "high. [#{presentation}]"]) end end end end rubocop-0.52.1/spec/rubocop/cop/metrics/block_length_spec.rb000066400000000000000000000063011322072016200240670ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::BlockLength, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 2, 'CountComments' => false } } it 'rejects a block with more than 5 lines' do inspect_source(<<-RUBY.strip_indent) something do a = 1 a = 2 a = 3 end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line).sort).to eq([1]) expect(cop.config_to_allow_offenses).to eq('Max' => 3) expect(cop.messages.first).to eq('Block has too many lines. [3/2]') end it 'reports the correct beginning and end lines' do inspect_source(<<-RUBY.strip_indent) something do a = 1 a = 2 a = 3 end RUBY offense = cop.offenses.first expect(offense.location.first_line).to eq(1) expect(offense.location.last_line).to eq(5) end it 'accepts a block with less than 3 lines' do expect_no_offenses(<<-RUBY.strip_indent) something do a = 1 a = 2 end RUBY end it 'does not count blank lines' do expect_no_offenses(<<-RUBY.strip_indent) something do a = 1 a = 4 end RUBY end it 'accepts a block with multiline receiver and less than 3 lines of body' do expect_no_offenses(<<-RUBY.strip_indent) [ :a, :b, :c, ].each do a = 1 a = 2 end RUBY end it 'accepts empty blocks' do expect_no_offenses(<<-RUBY.strip_indent) something do end RUBY end it 'rejects brace blocks too' do inspect_source(<<-RUBY.strip_indent) something { a = 1 a = 2 a = 3 } RUBY expect(cop.offenses.size).to eq(1) end it 'properly counts nested blocks' do inspect_source(<<-RUBY.strip_indent) something do something do a = 2 a = 3 a = 4 a = 5 end end RUBY expect(cop.offenses.size).to eq(2) expect(cop.offenses.map(&:line).sort).to eq([1, 2]) end it 'does not count commented lines by default' do expect_no_offenses(<<-RUBY.strip_indent) something do a = 1 #a = 2 #a = 3 a = 4 end RUBY end context 'when CountComments is enabled' do before { cop_config['CountComments'] = true } it 'also counts commented lines' do inspect_source(<<-RUBY.strip_indent) something do a = 1 #a = 2 a = 3 end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line).sort).to eq([1]) end end context 'when foo method is excluded is enabled' do before { cop_config['ExcludedMethods'] = ['foo'] } it 'still rejects other methods with long blocks' do inspect_source(<<-RUBY.strip_indent) something do a = 1 a = 2 a = 3 end RUBY expect(cop.offenses.empty?).to be(false) end it 'accepts the foo method with a long block' do expect_no_offenses(<<-RUBY.strip_indent) foo do a = 1 a = 2 a = 3 end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/metrics/block_nesting_spec.rb000066400000000000000000000107541322072016200242640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::BlockNesting, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 2 } } shared_examples 'too deep' do |source, lines, max_to_allow = 3| it "registers #{lines.length} offense(s)" do inspect_source(source) expect(cop.offenses.map(&:line)).to eq(lines) expect(cop.messages).to eq( ['Avoid more than 2 levels of block nesting.'] * lines.length ) end it 'sets `Max` value correctly' do inspect_source(source) expect(cop.config_to_allow_offenses['Max']).to eq(max_to_allow) end end it 'accepts `Max` levels of nesting' do expect_no_offenses(<<-RUBY.strip_indent) if a if b puts b end end RUBY end context '`Max + 1` levels of `if` nesting' do source = <<-RUBY.strip_indent if a if b if c puts c end end end RUBY it_behaves_like 'too deep', source, [3] end context '`Max + 2` levels of `if` nesting' do source = <<-RUBY.strip_indent if a if b if c if d puts d end end end end RUBY it_behaves_like 'too deep', source, [3], 4 end context 'Multiple nested `ifs` at same level' do source = <<-RUBY.strip_indent if a if b if c puts c end end if d if e puts e end end end RUBY it_behaves_like 'too deep', source, [3, 8] end context 'nested `case`' do source = <<-RUBY.strip_indent if a if b case c when C puts C end end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested `while`' do source = <<-RUBY.strip_indent if a if b while c puts c end end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested modifier `while`' do source = <<-RUBY.strip_indent if a if b begin puts c end while c end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested `until`' do source = <<-RUBY.strip_indent if a if b until c puts c end end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested modifier `until`' do source = <<-RUBY.strip_indent if a if b begin puts c end until c end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested `for`' do source = <<-RUBY.strip_indent if a if b for c in [1,2] do puts c end end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested `rescue`' do source = <<-RUBY.strip_indent if a if b begin puts c rescue puts x end end end RUBY it_behaves_like 'too deep', source, [5] end it 'accepts if/elsif' do expect_no_offenses(<<-RUBY.strip_indent) if a elsif b elsif c elsif d end RUBY end context 'when CountBlocks is false' do let(:cop_config) { { 'Max' => 2, 'CountBlocks' => false } } it 'accepts nested multiline blocks' do expect_no_offenses(<<-RUBY.strip_indent) if a if b [1, 2].each do |c| puts c end end end RUBY end it 'accepts nested inline blocks' do expect_no_offenses(<<-RUBY.strip_indent) if a if b [1, 2].each { |c| puts c } end end RUBY end end context 'when CountBlocks is true' do let(:cop_config) { { 'Max' => 2, 'CountBlocks' => true } } context 'nested multiline block' do source = <<-RUBY.strip_indent if a if b [1, 2].each do |c| puts c end end end RUBY it_behaves_like 'too deep', source, [3] end context 'nested inline block' do source = <<-RUBY.strip_indent if a if b [1, 2].each { |c| puts c } end end RUBY it_behaves_like 'too deep', source, [3] end end end rubocop-0.52.1/spec/rubocop/cop/metrics/class_length_spec.rb000066400000000000000000000061121322072016200241020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::ClassLength, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 5, 'CountComments' => false } } it 'rejects a class with more than 5 lines' do inspect_source(<<-RUBY.strip_indent) class Test a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Class has too many lines. [6/5]']) expect(cop.config_to_allow_offenses).to eq('Max' => 6) end it 'reports the correct beginning and end lines' do inspect_source(<<-RUBY.strip_indent) class Test a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY offense = cop.offenses.first expect(offense.location.first_line).to eq(1) expect(offense.location.last_line).to eq(8) end it 'accepts a class with 5 lines' do expect_no_offenses(<<-RUBY.strip_indent) class Test a = 1 a = 2 a = 3 a = 4 a = 5 end RUBY end it 'accepts a class with less than 5 lines' do expect_no_offenses(<<-RUBY.strip_indent) class Test a = 1 a = 2 a = 3 a = 4 end RUBY end it 'does not count blank lines' do expect_no_offenses(<<-RUBY.strip_indent) class Test a = 1 a = 2 a = 3 a = 4 a = 7 end RUBY end it 'accepts empty classes' do expect_no_offenses(<<-RUBY.strip_indent) class Test end RUBY end context 'when a class has inner classes' do it 'does not count lines of inner classes' do expect_no_offenses(<<-RUBY.strip_indent) class NamespaceClass class TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end class TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 end RUBY end it 'rejects a class with 6 lines that belong to the class directly' do inspect_source(<<-RUBY.strip_indent) class NamespaceClass class TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end class TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) end end context 'when CountComments is enabled' do before { cop_config['CountComments'] = true } it 'also counts commented lines' do inspect_source(<<-RUBY.strip_indent) class Test a = 1 #a = 2 a = 3 #a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) end end end rubocop-0.52.1/spec/rubocop/cop/metrics/cyclomatic_complexity_spec.rb000066400000000000000000000151761322072016200260520ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::CyclomaticComplexity, :config do subject(:cop) { described_class.new(config) } context 'when Max is 1' do let(:cop_config) { { 'Max' => 1 } } it 'accepts a method with no decision points' do expect_no_offenses(<<-RUBY.strip_indent) def method_name call_foo end RUBY end it 'accepts an empty method' do expect_no_offenses(<<-RUBY.strip_indent) def method_name end RUBY end it 'accepts an empty `define_method`' do expect_no_offenses(<<-RUBY.strip_indent) define_method :method_name do end RUBY end it 'accepts complex code outside of methods' do expect_no_offenses(<<-RUBY.strip_indent) def method_name call_foo end if first_condition then call_foo if second_condition && third_condition call_bar if fourth_condition || fifth_condition end RUBY end it 'registers an offense for an if modifier' do inspect_source(<<-RUBY.strip_indent) def self.method_name call_foo if some_condition end RUBY expect(cop.messages) .to eq(['Cyclomatic complexity for method_name is too high. [2/1]']) expect(cop.highlights).to eq([<<-RUBY.strip_indent.chomp]) def self.method_name call_foo if some_condition end RUBY expect(cop.config_to_allow_offenses).to eq('Max' => 2) end it 'registers an offense for an unless modifier' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo unless some_condition end RUBY end it 'registers an offense for an elsif block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [3/1] if first_condition then call_foo elsif second_condition then call_bar else call_bam end end RUBY end it 'registers an offense for a ternary operator' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] value = some_condition ? 1 : 2 end RUBY end it 'registers an offense for a while block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] while some_condition do call_foo end end RUBY end it 'registers an offense for an until block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] until some_condition do call_foo end end RUBY end it 'registers an offense for a for block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] for i in 1..2 do call_method end end RUBY end it 'registers an offense for a rescue block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] begin call_foo rescue Exception call_bar end end RUBY end it 'registers an offense for a case/when block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [3/1] case value when 1 call_foo when 2 call_bar end end RUBY end it 'registers an offense for &&' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo && call_bar end RUBY end it 'registers an offense for and' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo and call_bar end RUBY end it 'registers an offense for ||' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo || call_bar end RUBY end it 'registers an offense for or' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo or call_bar end RUBY end it 'deals with nested if blocks containing && and ||' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [6/1] if first_condition then call_foo if second_condition && third_condition call_bar if fourth_condition || fifth_condition end end RUBY end it 'counts only a single method' do expect_offense(<<-RUBY.strip_indent) def method_name_1 ^^^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name_1 is too high. [2/1] call_foo if some_condition end def method_name_2 ^^^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name_2 is too high. [2/1] call_foo if some_condition end RUBY end it 'registers an offense for a `define_method`' do expect_offense(<<-RUBY.strip_indent) define_method :method_name do ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [2/1] call_foo if some_condition end RUBY end end context 'when Max is 2' do let(:cop_config) { { 'Max' => 2 } } it 'counts stupid nested if and else blocks' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Cyclomatic complexity for method_name is too high. [5/2] if first_condition then call_foo else if second_condition then call_bar else call_bam if third_condition end call_baz if fourth_condition end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/metrics/line_length_spec.rb000066400000000000000000000267031322072016200237340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::LineLength, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 80, 'IgnoredPatterns' => nil } } it "registers an offense for a line that's 81 characters wide" do inspect_source('#' * 81) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq('Line is too long. [81/80]') expect(cop.config_to_allow_offenses).to eq('Max' => 81) end it 'highlights excessive characters' do inspect_source('#' * 80 + 'abc') expect(cop.highlights).to eq(['abc']) end it "accepts a line that's 80 characters wide" do inspect_source('#' * 80) expect(cop.offenses.empty?).to be(true) end it 'registers an offense for long line before __END__ but not after' do inspect_source(['#' * 150, '__END__', '#' * 200]) expect(cop.messages).to eq(['Line is too long. [150/80]']) end context 'when AllowURI option is enabled' do let(:cop_config) { { 'Max' => 80, 'AllowURI' => true } } context 'and all the excessive characters are part of an URL' do # This code example is allowed by AllowURI feature itself :). let(:source) { <<-RUBY } # Some documentation comment... # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c RUBY it 'accepts the line' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end context 'and the excessive characters include a complete URL' do let(:source) { <<-RUBY } # See: http://google.com/, http://gmail.com/, https://maps.google.com/, http://plus.google.com/ RUBY it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights all the excessive characters' do inspect_source(source) expect(cop.highlights).to eq(['http://plus.google.com/']) end end context 'and the excessive characters include part of an URL ' \ 'and another word' do let(:source) { <<-RUBY } # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c and # http://google.com/ RUBY it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights only the non-URL part' do inspect_source(source) expect(cop.highlights).to eq([' and']) end end context 'and an error other than URI::InvalidURIError is raised ' \ 'while validating an URI-ish string' do let(:cop_config) do { 'Max' => 80, 'AllowURI' => true, 'URISchemes' => %w[LDAP] } end let(:source) { <<-RUBY } xxxxxxxxxxxxxxxxxxxxxxxxxxxxzxxxxxxxxxxx = LDAP::DEFAULT_GROUP_UNIQUE_MEMBER_LIST_KEY RUBY it 'does not crash' do expect { inspect_source(source) }.not_to raise_error end end context 'and the URL does not have a http(s) scheme' do let(:source) { <<-RUBY } xxxxxxxxxxxxxxxxxxxxxxxxxxxxzxxxxxxxxxxx = 'otherprotocol://a.very.long.line.which.violates.LineLength/sadf' RUBY it 'rejects the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end context 'and the scheme has been configured' do let(:cop_config) do { 'Max' => 80, 'AllowURI' => true, 'URISchemes' => %w[otherprotocol] } end it 'accepts the line' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end end end context 'when IgnoredPatterns option is set' do let(:cop_config) do { 'Max' => 18, 'IgnoredPatterns' => ['^\s*test\s', /^\s*def\s+test_/] } end let(:source) do <<-RUBY.strip_indent class ExampleTest < TestCase test 'some really long test description which exceeds length' do end def test_some_other_long_test_description_which_exceeds_length end end RUBY end it 'accepts long lines matching a pattern but not other long lines' do inspect_source(source) expect(cop.highlights).to eq(['< TestCase']) end end context 'when AllowHeredoc option is enabled' do let(:cop_config) { { 'Max' => 80, 'AllowHeredoc' => true } } let(:source) { <<-RUBY } <<-SQL SELECT posts.id, posts.title, users.name FROM posts LEFT JOIN users ON posts.user_id = users.id; SQL RUBY it 'accepts long lines in heredocs' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'when the source has no AST' do let(:source) { '# this results in AST being nil' } it 'does not crash' do expect { inspect_source(source) }.not_to raise_error end end context 'and only certain heredoc delimiters are whitelisted' do let(:cop_config) do { 'Max' => 80, 'AllowHeredoc' => %w[SQL OK], 'IgnoredPatterns' => [] } end let(:source) { <<-RUBY } foo(<<-DOC, <<-SQL, <<-FOO) 1st offence: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \#{<<-OK} no offence (whitelisted): Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. OK 2nd offence: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. DOC no offence (whitelisted): Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \#{<<-XXX} no offence (nested inside whitelisted): Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. XXX no offence (whitelisted): Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. SQL 3rd offence: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \#{<<-SQL} no offence (whitelisted): Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. SQL 4th offence: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. FOO RUBY it 'rejects long lines in heredocs with not whitelisted delimiters' do inspect_source(source) expect(cop.offenses.size).to eq(4) end end end context 'when AllowURI option is disabled' do let(:cop_config) { { 'Max' => 80, 'AllowURI' => false } } context 'and all the excessive characters are part of an URL' do let(:source) { <<-RUBY } # See: https://github.com/bbatsov/rubocop/commit/3b48d8bdf5b1c2e05e35061837309890f04ab08c RUBY it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end end end context 'when IgnoreCopDirectives is disabled' do let(:cop_config) { { 'Max' => 80, 'IgnoreCopDirectives' => false } } context 'and the source is acceptable length' do let(:acceptable_source) { 'a' * 80 } context 'with a trailing Rubocop directive' do let(:cop_directive) { ' # rubcop:disable Metrics/SomeCop' } let(:source) { acceptable_source + cop_directive } it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights the excess directive' do inspect_source(source) expect(cop.highlights).to eq([cop_directive]) end end context 'with an inline comment' do let(:excess_comment) { ' ###' } let(:source) { acceptable_source + excess_comment } it 'highlights the excess comment' do inspect_source(source) expect(cop.highlights).to eq([excess_comment]) end end end context 'and the source is too long and has a trailing cop directive' do let(:excess_with_directive) { 'b # rubocop:disable Metrics/AbcSize' } let(:source) { 'a' * 80 + excess_with_directive } it 'highlights the excess source and cop directive' do inspect_source(source) expect(cop.highlights).to eq([excess_with_directive]) end end end context 'when IgnoreCopDirectives is enabled' do let(:cop_config) { { 'Max' => 80, 'IgnoreCopDirectives' => true } } context 'and the Rubocop directive is excessively long' do let(:source) { <<-RUBY } # rubocop:disable Metrics/SomeReallyLongMetricNameThatShouldBeMuchShorterAndNeedsANameChange RUBY it 'accepts the line' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end context 'and the Rubocop directive causes an excessive line length' do let(:source) { <<-RUBY } def method_definition_that_is_just_under_the_line_length_limit(foo, bar) # rubocop:disable Metrics/AbcSize # complex method end RUBY it 'accepts the line' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'and has explanatory text' do let(:source) { <<-RUBY } def method_definition_that_is_just_under_the_line_length_limit(foo) # rubocop:disable Metrics/AbcSize inherently complex! # complex end RUBY it 'accepts the line' do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end end context 'and the source is too long' do let(:source) { 'a' * 80 + 'bcd' + ' # rubocop:enable Style/ClassVars' } it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights only the non-directive part' do inspect_source(source) expect(cop.highlights).to eq(['bcd']) end context 'and the source contains non-directive # as comment' do let(:source) { <<-RUBY } aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa # bbbbbbbbbbbbbb # rubocop:enable Style/ClassVars' RUBY it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights only the non-directive part' do inspect_source(source) expect(cop.highlights).to eq(['bbbbbbb']) end end context 'and the source contains non-directive #s as non-comment' do let(:source) { <<-RUBY } LARGE_DATA_STRING_PATTERN = %r{\A([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})#([A-Za-z0-9\+\/#]*\={0,2})\z} # rubocop:disable LineLength RUBY it 'registers an offense for the line' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'highlights only the non-directive part' do inspect_source(source) expect(cop.highlights).to eq([']*={0,2})#([A-Za-z0-9+/#]*={0,2})z}']) end end end end end rubocop-0.52.1/spec/rubocop/cop/metrics/method_length_spec.rb000066400000000000000000000105221322072016200242550ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::MethodLength, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 5, 'CountComments' => false } } shared_examples 'reports violation' do |first_line, last_line| it 'rejects a method with more than 5 lines' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line)).to contain_exactly(first_line) expect(cop.config_to_allow_offenses).to eq('Max' => 6) expect(cop.messages.first).to eq('Method has too many lines. [6/5]') end it 'reports the correct beginning and end lines' do offense = cop.offenses.first expect(offense.location.first_line).to eq(first_line) expect(offense.location.last_line).to eq(last_line) end end context 'when method is an instance method' do before do inspect_source(<<-RUBY.strip_indent) def m() a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY end include_examples 'reports violation', 1, 8 end context 'when method is defined with `define_method`' do before do inspect_source(<<-RUBY.strip_indent) define_method(:m) do a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY end include_examples 'reports violation', 1, 8 end context 'when method is a class method' do before do inspect_source(<<-RUBY.strip_indent) def self.m() a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY end include_examples 'reports violation', 1, 8 end context 'when method is defined on a singleton class' do before do inspect_source(<<-RUBY.strip_indent) class K class << self def m() a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end end end RUBY end include_examples 'reports violation', 3, 10 end it 'accepts a method with less than 5 lines' do expect_no_offenses(<<-RUBY.strip_indent) def m() a = 1 a = 2 a = 3 a = 4 end RUBY end it 'accepts a method with multiline arguments ' \ 'and less than 5 lines of body' do inspect_source(<<-RUBY.strip_indent) def m(x, y, z) a = 1 a = 2 a = 3 a = 4 end RUBY expect(cop.offenses.empty?).to be(true) end it 'does not count blank lines' do expect_no_offenses(<<-RUBY.strip_indent) def m() a = 1 a = 2 a = 3 a = 4 a = 7 end RUBY end it 'accepts empty methods' do expect_no_offenses(<<-RUBY.strip_indent) def m() end RUBY end it 'is not fooled by one-liner methods, syntax #1' do expect_no_offenses(<<-RUBY.strip_indent) def one_line; 10 end def self.m() a = 1 a = 2 a = 4 a = 5 a = 6 end RUBY end it 'is not fooled by one-liner methods, syntax #2' do expect_no_offenses(<<-RUBY.strip_indent) def one_line(test) 10 end def self.m() a = 1 a = 2 a = 4 a = 5 a = 6 end RUBY end it 'properly counts lines when method ends with block' do inspect_source(<<-RUBY.strip_indent) def m() something do a = 2 a = 3 a = 4 a = 5 end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line).sort).to eq([1]) end it 'does not count commented lines by default' do expect_no_offenses(<<-RUBY.strip_indent) def m() a = 1 #a = 2 a = 3 #a = 4 a = 5 a = 6 end RUBY end context 'when CountComments is enabled' do before { cop_config['CountComments'] = true } it 'also counts commented lines' do inspect_source(<<-RUBY.strip_indent) def m() a = 1 #a = 2 a = 3 #a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.map(&:line).sort).to eq([1]) end end end rubocop-0.52.1/spec/rubocop/cop/metrics/module_length_spec.rb000066400000000000000000000103051322072016200242610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::ModuleLength, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Max' => 5, 'CountComments' => false } } it 'rejects a module with more than 5 lines' do inspect_source(<<-RUBY.strip_indent) module Test a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Module has too many lines. [6/5]']) expect(cop.config_to_allow_offenses).to eq('Max' => 6) end it 'reports the correct beginning and end lines' do inspect_source(<<-RUBY.strip_indent) module Test a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY offense = cop.offenses.first expect(offense.location.first_line).to eq(1) expect(offense.location.last_line).to eq(8) end it 'accepts a module with 5 lines' do expect_no_offenses(<<-RUBY.strip_indent) module Test a = 1 a = 2 a = 3 a = 4 a = 5 end RUBY end it 'accepts a module with less than 5 lines' do expect_no_offenses(<<-RUBY.strip_indent) module Test a = 1 a = 2 a = 3 a = 4 end RUBY end it 'does not count blank lines' do expect_no_offenses(<<-RUBY.strip_indent) module Test a = 1 a = 2 a = 3 a = 4 a = 7 end RUBY end it 'accepts empty modules' do expect_no_offenses(<<-RUBY.strip_indent) module Test end RUBY end context 'when a module has inner modules' do it 'does not count lines of inner modules' do expect_no_offenses(<<-RUBY.strip_indent) module NamespaceModule module TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end module TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 end RUBY end it 'rejects a module with 6 lines that belong to the module directly' do inspect_source(<<-RUBY.strip_indent) module NamespaceModule module TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end module TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) end end context 'when a module has inner classes' do it 'does not count lines of inner classes' do expect_no_offenses(<<-RUBY.strip_indent) module NamespaceModule class TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end class TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 end RUBY end it 'rejects a module with 6 lines that belong to the module directly' do inspect_source(<<-RUBY.strip_indent) module NamespaceModule class TestOne a = 1 a = 2 a = 3 a = 4 a = 5 end class TestTwo a = 1 a = 2 a = 3 a = 4 a = 5 end a = 1 a = 2 a = 3 a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) end end context 'when CountComments is enabled' do before { cop_config['CountComments'] = true } it 'also counts commented lines' do inspect_source(<<-RUBY.strip_indent) module Test a = 1 #a = 2 a = 3 #a = 4 a = 5 a = 6 end RUBY expect(cop.offenses.size).to eq(1) end end end rubocop-0.52.1/spec/rubocop/cop/metrics/parameter_lists_spec.rb000066400000000000000000000034631322072016200246400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::ParameterLists, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Max' => 4, 'CountKeywordArgs' => true } end it 'registers an offense for a method def with 5 parameters' do inspect_source(<<-RUBY.strip_indent) def meth(a, b, c, d, e) end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Avoid parameter lists longer than 4 parameters. [5/4]'] ) expect(cop.config_to_allow_offenses).to eq('Max' => 5) end it 'accepts a method def with 4 parameters' do expect_no_offenses(<<-RUBY.strip_indent) def meth(a, b, c, d) end RUBY end it 'accepts a proc with more than 4 parameters' do expect_no_offenses(<<-RUBY.strip_indent) proc { |a, b, c, d, e| } RUBY end it 'accepts a lambda with more than 4 parameters' do expect_no_offenses(<<-RUBY.strip_indent) ->(a, b, c, d, e) { } RUBY end context 'When CountKeywordArgs is true' do it 'counts keyword arguments as well' do expect_offense(<<-RUBY.strip_indent) def meth(a, b, c, d: 1, e: 2) ^^^^^^^^^^^^^^^^^^^^^ Avoid parameter lists longer than 4 parameters. [5/4] end RUBY end end context 'When CountKeywordArgs is false' do before { cop_config['CountKeywordArgs'] = false } it 'does not count keyword arguments' do expect_no_offenses(<<-RUBY.strip_indent) def meth(a, b, c, d: 1, e: 2) end RUBY end it 'does not count keyword arguments without default values', ruby: 2.1 do inspect_source(<<-RUBY.strip_indent) def meth(a, b, c, d:, e:) end RUBY expect(cop.offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/metrics/perceived_complexity_spec.rb000066400000000000000000000164711322072016200256700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Metrics::PerceivedComplexity, :config do subject(:cop) { described_class.new(config) } context 'when Max is 1' do let(:cop_config) { { 'Max' => 1 } } it 'accepts a method with no decision points' do expect_no_offenses(<<-RUBY.strip_indent) def method_name call_foo end RUBY end it 'accepts an empty method' do expect_no_offenses(<<-RUBY.strip_indent) def method_name end RUBY end it 'accepts an empty `define_method`' do expect_no_offenses(<<-RUBY.strip_indent) define_method :method_name do end RUBY end it 'accepts complex code outside of methods' do expect_no_offenses(<<-RUBY.strip_indent) def method_name call_foo end if first_condition then call_foo if second_condition && third_condition call_bar if fourth_condition || fifth_condition end RUBY end it 'registers an offense for an if modifier' do inspect_source(<<-RUBY.strip_indent) def self.method_name call_foo if some_condition end RUBY expect(cop.messages) .to eq(['Perceived complexity for method_name is too high. [2/1]']) expect(cop.highlights).to eq([<<-RUBY.strip_indent.chomp]) def self.method_name call_foo if some_condition end RUBY expect(cop.config_to_allow_offenses).to eq('Max' => 2) end it 'registers an offense for an unless modifier' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo unless some_condition end RUBY end it 'registers an offense for elsif and else blocks' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [4/1] if first_condition then call_foo elsif second_condition then call_bar else call_bam end end RUBY end it 'registers an offense for a ternary operator' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] value = some_condition ? 1 : 2 end RUBY end it 'registers an offense for a while block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] while some_condition do call_foo end end RUBY end it 'registers an offense for an until block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] until some_condition do call_foo end end RUBY end it 'registers an offense for a for block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] for i in 1..2 do call_method end end RUBY end it 'registers an offense for a rescue block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] begin call_foo rescue Exception call_bar end end RUBY end it 'registers an offense for a case/when block' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [3/1] case value when 1 then call_foo_1 when 2 then call_foo_2 when 3 then call_foo_3 when 4 then call_foo_4 end end RUBY end it 'registers an offense for a case/when block without an expression ' \ 'after case' do inspect_source(<<-RUBY.strip_indent) def method_name case when value == 1 call_foo when value == 2 call_bar end end RUBY # Here, the `case` node doesn't count, but each when scores one # complexity point. expect(cop.messages) .to eq(['Perceived complexity for method_name is too high. [3/1]']) end it 'registers an offense for &&' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo && call_bar end RUBY end it 'registers an offense for and' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo and call_bar end RUBY end it 'registers an offense for ||' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo || call_bar end RUBY end it 'registers an offense for or' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo or call_bar end RUBY end it 'deals with nested if blocks containing && and ||' do expect_offense(<<-RUBY.strip_indent) def method_name ^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [6/1] if first_condition then call_foo if second_condition && third_condition call_bar if fourth_condition || fifth_condition end end RUBY end it 'counts only a single method' do expect_offense(<<-RUBY.strip_indent) def method_name_1 ^^^^^^^^^^^^^^^^^ Perceived complexity for method_name_1 is too high. [2/1] call_foo if some_condition end def method_name_2 ^^^^^^^^^^^^^^^^^ Perceived complexity for method_name_2 is too high. [2/1] call_foo if some_condition end RUBY end it 'registers an offense for a `define_method`' do expect_offense(<<-RUBY.strip_indent) define_method :method_name do ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [2/1] call_foo if some_condition end RUBY end end context 'when Max is 2' do let(:cop_config) { { 'Max' => 2 } } it 'counts stupid nested if and else blocks' do expect_offense(<<-RUBY.strip_indent) def method_name # 1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Perceived complexity for method_name is too high. [7/2] if first_condition then # 2 call_foo else # 3 if second_condition then # 4 call_bar else # 5 call_bam if third_condition # 6 end call_baz if fourth_condition # 7 end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/naming/000077500000000000000000000000001322072016200177005ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/naming/accessor_method_name_spec.rb000066400000000000000000000041441322072016200254040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::AccessorMethodName do subject(:cop) { described_class.new } it 'registers an offense for method get_... with no args' do expect_offense(<<-RUBY.strip_indent) def get_attr ^^^^^^^^ Do not prefix reader method names with `get_`. # ... end RUBY end it 'registers an offense for singleton method get_... with no args' do expect_offense(<<-RUBY.strip_indent) def self.get_attr ^^^^^^^^ Do not prefix reader method names with `get_`. # ... end RUBY end it 'accepts method get_something with args' do expect_no_offenses(<<-RUBY.strip_indent) def get_something(arg) # ... end RUBY end it 'accepts singleton method get_something with args' do expect_no_offenses(<<-RUBY.strip_indent) def self.get_something(arg) # ... end RUBY end it 'registers an offense for method set_something with one arg' do expect_offense(<<-RUBY.strip_indent) def set_attr(arg) ^^^^^^^^ Do not prefix writer method names with `set_`. # ... end RUBY end it 'registers an offense for singleton method set_... with one args' do expect_offense(<<-RUBY.strip_indent) def self.set_attr(arg) ^^^^^^^^ Do not prefix writer method names with `set_`. # ... end RUBY end it 'accepts method set_something with no args' do expect_no_offenses(<<-RUBY.strip_indent) def set_something # ... end RUBY end it 'accepts singleton method set_something with no args' do expect_no_offenses(<<-RUBY.strip_indent) def self.set_something # ... end RUBY end it 'accepts method set_something with two args' do expect_no_offenses(<<-RUBY.strip_indent) def set_something(arg1, arg2) # ... end RUBY end it 'accepts singleton method set_something with two args' do expect_no_offenses(<<-RUBY.strip_indent) def self.get_something(arg1, arg2) # ... end RUBY end end rubocop-0.52.1/spec/rubocop/cop/naming/ascii_identifiers_spec.rb000066400000000000000000000016131322072016200247150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::AsciiIdentifiers do subject(:cop) { described_class.new } it 'registers an offense for a variable name with non-ascii chars' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 älg = 1 ^ Use only ascii symbols in identifiers. RUBY end it 'registers an offense for a variable name with mixed chars' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 foo∂∂bar = baz ^^ Use only ascii symbols in identifiers. RUBY end it 'accepts identifiers with only ascii chars' do expect_no_offenses('x.empty?') end it 'does not get confused by a byte order mark' do expect_no_offenses(<<-RUBY.strip_indent) # encoding: utf-8 puts 'foo' RUBY end it 'does not get confused by an empty file' do expect_no_offenses('') end end rubocop-0.52.1/spec/rubocop/cop/naming/binary_operator_parameter_name_spec.rb000066400000000000000000000036221322072016200275010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::BinaryOperatorParameterName do subject(:cop) { described_class.new } %i[+ eql? equal?].each do |op| it "registers an offense for #{op} with arg not named other" do inspect_source(<<-RUBY.strip_indent) def #{op}(another) another end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["When defining the `#{op}` operator, " \ 'name its argument `other`.']) end end it 'works properly even if the argument not surrounded with braces' do expect_offense(<<-RUBY.strip_indent) def + another ^^^^^^^ When defining the `+` operator, name its argument `other`. another end RUBY end it 'does not register an offense for arg named other' do expect_no_offenses(<<-RUBY.strip_indent) def +(other) other end RUBY end it 'does not register an offense for arg named _other' do expect_no_offenses(<<-RUBY.strip_indent) def <=>(_other) 0 end RUBY end it 'does not register an offense for []' do expect_no_offenses(<<-RUBY.strip_indent) def [](index) other end RUBY end it 'does not register an offense for []=' do expect_no_offenses(<<-RUBY.strip_indent) def []=(index, value) other end RUBY end it 'does not register an offense for <<' do expect_no_offenses(<<-RUBY.strip_indent) def <<(cop) other end RUBY end it 'does not register an offense for non binary operators' do expect_no_offenses(<<-RUBY.strip_indent) def -@; end # This + is not a unary operator. It can only be # called with dot notation. def +; end def *(a, b); end # Quite strange, but legal ruby. def `(cmd); end RUBY end end rubocop-0.52.1/spec/rubocop/cop/naming/class_and_module_camel_case_spec.rb000066400000000000000000000016231322072016200266710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::ClassAndModuleCamelCase do subject(:cop) { described_class.new } it 'registers an offense for underscore in class and module name' do expect_offense(<<-RUBY.strip_indent) class My_Class ^^^^^^^^ Use CamelCase for classes and modules. end module My_Module ^^^^^^^^^ Use CamelCase for classes and modules. end RUBY end it 'is not fooled by qualified names' do expect_offense(<<-RUBY.strip_indent) class Top::My_Class ^^^^^^^^^^^^^ Use CamelCase for classes and modules. end module My_Module::Ala ^^^^^^^^^^^^^^ Use CamelCase for classes and modules. end RUBY end it 'accepts CamelCase names' do expect_no_offenses(<<-RUBY.strip_indent) class MyClass end module Mine end RUBY end end rubocop-0.52.1/spec/rubocop/cop/naming/constant_name_spec.rb000066400000000000000000000054471322072016200241020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::ConstantName do subject(:cop) { described_class.new } it 'registers an offense for camel case in const name' do expect_offense(<<-RUBY.strip_indent) TopCase = 5 ^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'registers an offense for camel case in const name' \ 'when using frozen object assignment' do expect_offense(<<-RUBY.strip_indent) TopCase = 5.freeze ^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'registers an offense for non-POSIX upper case in const name' do expect_offense(<<-RUBY.strip_indent) Nö = 'no' ^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'registers offenses for camel case in multiple const assignment' do expect_offense(<<-RUBY.strip_indent) TopCase, Test2, TEST_3 = 5, 6, 7 ^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. ^^^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'registers an offense for snake case in const name' do expect_offense(<<-RUBY.strip_indent) TOP_test = 5 ^^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'registers 1 offense if rhs is offending const assignment' do expect_offense(<<-RUBY.strip_indent) Bar = Foo = 4 ^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end it 'allows screaming snake case in const name' do expect_no_offenses('TOP_TEST = 5') end it 'allows screaming snake case in multiple const assignment' do expect_no_offenses('TOP_TEST, TEST_2 = 5, 6') end it 'allows screaming snake case with POSIX upper case characters' do expect_no_offenses('TÖP_TEST = 5') end it 'does not check names if rhs is a method call' do expect_no_offenses('AnythingGoes = test') end it 'does not check names if rhs is a `Class.new`' do expect_no_offenses('Invalid = Class.new(StandardError)') end it 'does not check names if rhs is a `Struct.new`' do expect_no_offenses('Investigation = Struct.new(:offenses, :errors)') end it 'does not check names if rhs is a method call with block' do expect_no_offenses(<<-RUBY.strip_indent) AnythingGoes = test do do_something end RUBY end it 'does not check if rhs is another constant' do expect_no_offenses('Parser::CurrentRuby = Parser::Ruby21') end it 'does not check if rhs is a non-offensive const assignment' do expect_no_offenses(<<-RUBY.strip_indent) Bar = Foo = Qux RUBY end it 'checks qualified const names' do expect_offense(<<-RUBY.strip_indent) ::AnythingGoes = 30 ^^^^^^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. a::Bar_foo = 10 ^^^^^^^ Use SCREAMING_SNAKE_CASE for constants. RUBY end end rubocop-0.52.1/spec/rubocop/cop/naming/file_name_spec.rb000066400000000000000000000221611322072016200231600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::FileName do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( { 'AllCops' => { 'Include' => includes }, described_class.badge.to_s => cop_config }, '/some/.rubocop.yml' ) end let(:cop_config) do { 'IgnoreExecutableScripts' => true, 'ExpectMatchingDefinition' => false, 'Regex' => nil } end let(:includes) { [] } let(:source) { 'print 1' } let(:processed_source) { parse_source(source) } before do allow(processed_source.buffer) .to receive(:name).and_return(filename) _investigate(cop, processed_source) end context 'with camelCase file names ending in .rb' do let(:filename) { '/some/dir/testCase.rb' } it 'reports an offense' do expect(cop.offenses.size).to eq(1) end end context 'with camelCase file names without file extension' do let(:filename) { '/some/dir/testCase' } it 'reports an offense' do expect(cop.offenses.size).to eq(1) end end context 'with snake_case file names ending in .rb' do let(:filename) { '/some/dir/test_case.rb' } it 'reports an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with snake_case file names without file extension' do let(:filename) { '/some/dir/test_case' } it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with snake_case file names with non-rb extension' do let(:filename) { '/some/dir/some_task.rake' } it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with snake_case file names with multiple extensions' do let(:filename) { 'some/dir/some_view.html.slim_spec.rb' } it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with snake_case names which use ? and !' do let(:filename) { 'some/dir/file?!.rb' } it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with non-snake-case file names with a shebang' do let(:filename) { '/some/dir/test-case' } let(:source) { <<-RUBY.strip_indent } #!/usr/bin/env ruby print 1 RUBY it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end context 'when IgnoreExecutableScripts is disabled' do let(:cop_config) { { 'IgnoreExecutableScripts' => false } } it 'reports an offense' do expect(cop.offenses.size).to eq(1) end end end context 'when the file is specified in AllCops/Include' do let(:includes) { ['**/Gemfile'] } context 'with a non-snake_case file name' do let(:filename) { '/some/dir/Gemfile' } it 'does not report an offense' do expect(cop.offenses.empty?).to be(true) end end end context 'when ExpectMatchingDefinition is true' do let(:cop_config) do { 'IgnoreExecutableScripts' => true, 'ExpectMatchingDefinition' => true } end context 'on a file which defines no class or module at all' do %w[lib src test spec].each do |dir| context "under #{dir}" do let(:filename) { "/some/dir/#{dir}/file/test_case.rb" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['test_case.rb should define a class ' \ 'or module called `File::TestCase`.']) end end end context 'under some other random directory' do let(:filename) { '/some/other/dir/test_case.rb' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['test_case.rb should define a class ' \ 'or module called `TestCase`.']) end end end context 'on an empty file' do let(:source) { '' } let(:filename) { '/lib/rubocop/blah.rb' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['blah.rb should define a class ' \ 'or module called `Rubocop::Blah`.']) end end context 'on an empty file with a space in its filename' do let(:source) { '' } let(:filename) { 'a file.rb' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['The name of this source file (`a file.rb`) ' \ 'should use snake_case.']) end end shared_examples 'matching module or class' do %w[lib src test spec].each do |dir| context "in a matching directory under #{dir}" do let(:filename) { "/some/dir/#{dir}/a/b.rb" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context "in a non-matching directory under #{dir}" do let(:filename) { "/some/dir/#{dir}/c/b.rb" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['b.rb should define a class ' \ 'or module called `C::B`.']) end end context "in a directory with multiple instances of #{dir}" do let(:filename) { "/some/dir/#{dir}/project/#{dir}/a/b.rb" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end end context 'in a directory elsewhere which only matches the module name' do let(:filename) { '/some/dir/b.rb' } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'in a directory elsewhere which does not match the module name' do let(:filename) { '/some/dir/e.rb' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['e.rb should define a class ' \ 'or module called `E`.']) end end end context 'on a file which defines a nested module' do let(:source) { <<-RUBY.strip_indent } module A module B end end RUBY include_examples 'matching module or class' end context 'on a file which defines a nested class' do let(:source) { <<-RUBY.strip_indent } module A class B end end RUBY include_examples 'matching module or class' end context 'on a file which uses Name::Spaced::Module syntax' do let(:source) { <<-RUBY.strip_indent } begin module A::B end end RUBY include_examples 'matching module or class' end context 'on a file which defines multiple classes' do let(:source) { <<-RUBY.strip_indent } class X end module M end class A class B end end RUBY include_examples 'matching module or class' end end context 'when Regex is set' do let(:cop_config) { { 'Regex' => /\A[aeiou]\z/i } } context 'with a matching name' do let(:filename) { 'a.rb' } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with a non-matching name' do let(:filename) { 'z.rb' } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['`z.rb` should match `(?i-mx:\\A[aeiou]\\z)`.'] ) end end end context 'with acronym namespace' do let(:cop_config) do { 'IgnoreExecutableScripts' => true, 'ExpectMatchingDefinition' => true, 'AllowedAcronyms' => ['CLI'] } end let(:filename) { '/lib/my/cli/admin_user.rb' } let(:source) { <<-RUBY.strip_indent } module My module CLI class AdminUser end end end RUBY it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with acronym class name' do let(:cop_config) do { 'IgnoreExecutableScripts' => true, 'ExpectMatchingDefinition' => true, 'AllowedAcronyms' => ['CLI'] } end let(:filename) { '/lib/my/cli.rb' } let(:source) { <<-RUBY.strip_indent } module My class CLI end end RUBY it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'with include acronym name' do let(:cop_config) do { 'IgnoreExecutableScripts' => true, 'ExpectMatchingDefinition' => true, 'AllowedAcronyms' => ['HTTP'] } end let(:filename) { '/lib/my/http_server.rb' } let(:source) { <<-RUBY.strip_indent } module My class HTTPServer end end RUBY it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/naming/heredoc_delimiter_case_spec.rb000066400000000000000000000150721322072016200257060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::HeredocDelimiterCase, :config do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new(described_class.badge.to_s => cop_config) end context 'when enforced style is uppercase' do let(:cop_config) do { 'SupportedStyles' => %w[uppercase lowercase], 'EnforcedStyle' => 'uppercase' } end context 'with an interpolated heredoc' do it 'registers an offense with a lowercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-sql foo sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-Sql foo Sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'does not register an offense with an uppercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-SQL foo SQL RUBY end end context 'with a non-interpolated heredoc' do context 'when using single quoted delimiters' do it 'registers an offense with a lowercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-'sql' foo sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-'Sql' foo Sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'does not register an offense with an uppercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-'SQL' foo SQL RUBY end end context 'when using double quoted delimiters' do it 'registers an offense with a lowercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-"sql" foo sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-"Sql" foo Sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'does not register an offense with an uppercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-"SQL" foo SQL RUBY end end context 'when using back tick delimiters' do it 'registers an offense with a lowercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-`sql` foo sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-`Sql` foo Sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'does not register an offense with an uppercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-`SQL` foo SQL RUBY end end context 'when using non-word delimiters' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) <<-'+' foo + RUBY end end end context 'with a squiggly heredoc', :ruby23 do it 'registers an offense with a lowercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<~sql foo sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<~Sql foo Sql ^^^ Use uppercase heredoc delimiters. RUBY end it 'does not register an offense with an uppercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<~SQL foo SQL RUBY end end end context 'when enforced style is lowercase' do let(:cop_config) do { 'SupportedStyles' => %w[uppercase lowercase], 'EnforcedStyle' => 'lowercase' } end context 'with an interpolated heredoc' do it 'does not register an offense with a lowercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-sql foo sql RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-Sql foo Sql ^^^ Use lowercase heredoc delimiters. RUBY end it 'registers an offense with an uppercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-SQL foo SQL ^^^ Use lowercase heredoc delimiters. RUBY end end context 'with a non-interpolated heredoc' do it 'does not reguster an offense with a lowercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-'sql' foo sql RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<-'Sql' foo Sql ^^^ Use lowercase heredoc delimiters. RUBY end it 'registers an offense with an uppercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<-'SQL' foo SQL ^^^ Use lowercase heredoc delimiters. RUBY end end context 'with a squiggly heredoc', :ruby23 do it 'does not register an offense with a lowercase delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<~sql foo sql RUBY end it 'registers an offense with a camel case delimiter' do expect_offense(<<-RUBY.strip_indent) <<~Sql foo Sql ^^^ Use lowercase heredoc delimiters. RUBY end it 'registers an offense with an uppercase delimiter' do expect_offense(<<-RUBY.strip_indent) <<~SQL foo SQL ^^^ Use lowercase heredoc delimiters. RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/naming/heredoc_delimiter_naming_spec.rb000066400000000000000000000110751322072016200262430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::HeredocDelimiterNaming, :config do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new(described_class.badge.to_s => cop_config) end let(:cop_config) do { 'Blacklist' => %w[END] } end context 'with an interpolated heredoc' do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) <<-END foo END ^^^ Use meaningful heredoc delimiters. RUBY end it 'does not register an offense with a meaningful delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-SQL foo SQL RUBY end end context 'with a non-interpolated heredoc' do context 'when using single quoted delimiters' do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) <<-'END' foo END ^^^ Use meaningful heredoc delimiters. RUBY end it 'does not register an offense with a meaningful delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-'SQL' foo SQL RUBY end end context 'when using double quoted delimiters' do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) <<-"END" foo END ^^^ Use meaningful heredoc delimiters. RUBY end it 'does not register an offense with a meaningful delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-'SQL' foo SQL RUBY end end context 'when using back tick delimiters' do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) <<-`END` foo END ^^^ Use meaningful heredoc delimiters. RUBY end it 'does not register an offense with a meaningful delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<-`SQL` foo SQL RUBY end end context 'when using non-word delimiters' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) <<-'+' foo + ^ Use meaningful heredoc delimiters. RUBY end end end context 'with a squiggly heredoc', :ruby23 do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) <<~END foo END ^^^ Use meaningful heredoc delimiters. RUBY end it 'does not register an offense with a meaningful delimiter' do expect_no_offenses(<<-RUBY.strip_indent) <<~SQL foo SQL RUBY end end context 'with a naked heredoc', :ruby23 do it 'registers an offense with a non-meaningful delimiter' do expect_offense(<<-RUBY.strip_indent) < 'snake_case' } } it 'registers an offense for camel case in instance method name' do expect_offense(<<-RUBY.strip_indent) def myMethod ^^^^^^^^ Use snake_case for method names. # ... end RUBY end it 'registers an offense for opposite + correct' do expect_offense(<<-RUBY.strip_indent) def my_method end def myMethod ^^^^^^^^ Use snake_case for method names. end RUBY end it 'registers an offense for camel case in singleton method name' do expect_offense(<<-RUBY.strip_indent) def self.myMethod ^^^^^^^^ Use snake_case for method names. # ... end RUBY end it 'accepts snake case in names' do expect_no_offenses(<<-RUBY.strip_indent) def my_method end RUBY end it 'registers an offense for singleton camelCase method within class' do expect_offense(<<-RUBY.strip_indent) class Sequel def self.fooBar ^^^^^^ Use snake_case for method names. end end RUBY end include_examples 'never accepted', 'snake_case' include_examples 'always accepted', 'snake_case' end context 'when configured for camelCase' do let(:cop_config) { { 'EnforcedStyle' => 'camelCase' } } it 'accepts camel case in instance method name' do expect_no_offenses(<<-RUBY.strip_indent) def myMethod # ... end RUBY end it 'accepts camel case in singleton method name' do expect_no_offenses(<<-RUBY.strip_indent) def self.myMethod # ... end RUBY end it 'registers an offense for snake case in names' do expect_offense(<<-RUBY.strip_indent) def my_method ^^^^^^^^^ Use camelCase for method names. end RUBY end it 'registers an offense for correct + opposite' do expect_offense(<<-RUBY.strip_indent) def myMethod end def my_method ^^^^^^^^^ Use camelCase for method names. end RUBY end it 'registers an offense for singleton snake_case method within class' do expect_offense(<<-RUBY.strip_indent) class Sequel def self.foo_bar ^^^^^^^ Use camelCase for method names. end end RUBY end include_examples 'always accepted', 'camelCase' include_examples 'never accepted', 'camelCase' end end rubocop-0.52.1/spec/rubocop/cop/naming/predicate_name_spec.rb000066400000000000000000000071611322072016200242040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::PredicateName, :config do subject(:cop) { described_class.new(config) } context 'with blacklisted prefixes' do let(:cop_config) do { 'NamePrefix' => %w[has_ is_], 'NamePrefixBlacklist' => %w[has_ is_] } end %w[has is].each do |prefix| it 'registers an offense when method name starts with known prefix' do inspect_source(<<-RUBY.strip_indent) def #{prefix}_attr # ... end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(["Rename `#{prefix}_attr` to `attr?`."]) expect(cop.highlights).to eq(["#{prefix}_attr"]) end end it 'accepts method name that starts with unknown prefix' do expect_no_offenses(<<-RUBY.strip_indent) def have_attr # ... end RUBY end end context 'without blacklisted prefixes' do let(:cop_config) do { 'NamePrefix' => %w[has_ is_], 'NamePrefixBlacklist' => [] } end %w[has is].each do |prefix| it 'registers an offense when method name starts with known prefix' do inspect_source(<<-RUBY.strip_indent) def #{prefix}_attr # ... end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Rename `#{prefix}_attr` to `#{prefix}_attr?`."]) expect(cop.highlights).to eq(["#{prefix}_attr"]) end end it 'accepts method name that starts with unknown prefix' do expect_no_offenses(<<-RUBY.strip_indent) def have_attr # ... end RUBY end end context 'with whitelisted predicate names' do let(:cop_config) do { 'NamePrefix' => %w[is_], 'NamePrefixBlacklist' => %w[is_], 'NameWhitelist' => %w[is_a?] } end it 'accepts method name which is in whitelist' do expect_no_offenses(<<-RUBY.strip_indent) def is_a? # ... end RUBY end end context 'with method definition macros' do let(:cop_config) do { 'NamePrefix' => %w[is_], 'NamePrefixBlacklist' => %w[is_], 'MethodDefinitionMacros' => %w[define_method def_node_matcher] } end it 'registers an offense when using `define_method`' do expect_offense(<<-RUBY.strip_indent) define_method(:is_hello) do |method_name| ^^^^^^^^^ Rename `is_hello` to `hello?`. method_name == 'hello' end RUBY end it 'registers an offense when using an internal affair macro' do expect_offense(<<-RUBY.strip_indent) def_node_matcher :is_hello, <<-PATTERN ^^^^^^^^^ Rename `is_hello` to `hello?`. (send (send nil? :method_name) :== (str 'hello')) PATTERN RUBY end end context 'without method definition macros' do let(:cop_config) do { 'NamePrefix' => %w[is_], 'NamePrefixBlacklist' => %w[is_] } end it 'registers an offense when using `define_method`' do expect_offense(<<-RUBY.strip_indent) define_method(:is_hello) do |method_name| ^^^^^^^^^ Rename `is_hello` to `hello?`. method_name == 'hello' end RUBY end it 'does not register any offenses when using an internal affair macro' do expect_no_offenses(<<-RUBY.strip_indent) def_node_matcher :is_hello, <<-PATTERN ^^^^^^^^^ Rename `is_hello` to `hello?`. (send (send nil? :method_name) :== (str 'hello')) PATTERN RUBY end end end rubocop-0.52.1/spec/rubocop/cop/naming/variable_name_spec.rb000066400000000000000000000124051322072016200240260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::VariableName, :config do subject(:cop) { described_class.new(config) } shared_examples 'always accepted' do it 'accepts screaming snake case globals' do expect_no_offenses('$MY_GLOBAL = 0') end it 'accepts screaming snake case constants' do expect_no_offenses('MY_CONSTANT = 0') end it 'accepts assigning to camel case constant' do expect_no_offenses('Paren = Struct.new :left, :right, :kind') end it 'accepts assignment with indexing of self' do expect_no_offenses('self[:a] = b') end end context 'when configured for snake_case' do let(:cop_config) { { 'EnforcedStyle' => 'snake_case' } } it 'registers an offense for camel case in local variable name' do expect_offense(<<-RUBY.strip_indent) myLocal = 1 ^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for correct + opposite' do expect_offense(<<-RUBY.strip_indent) my_local = 1 myLocal = 1 ^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for camel case in instance variable name' do expect_offense(<<-RUBY.strip_indent) @myAttribute = 3 ^^^^^^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for camel case in class variable name' do expect_offense(<<-RUBY.strip_indent) @@myAttr = 2 ^^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for camel case local variables marked as unused' do expect_offense(<<-RUBY.strip_indent) _myLocal = 1 ^^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for method arguments' do expect_offense(<<-RUBY.strip_indent) def method(funnyArg); end ^^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for default method arguments' do expect_offense(<<-RUBY.strip_indent) def foo(optArg = 1); end ^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for rest arguments' do expect_offense(<<-RUBY.strip_indent) def foo(*restArg); end ^^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for keyword arguments' do expect_offense(<<-RUBY.strip_indent) def foo(kwArg: 1); end ^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for keyword rest arguments' do expect_offense(<<-RUBY.strip_indent) def foo(**kwRest); end ^^^^^^ Use snake_case for variable names. RUBY end it 'registers an offense for block arguments' do expect_offense(<<-RUBY.strip_indent) def foo(&blockArg); end ^^^^^^^^ Use snake_case for variable names. RUBY end include_examples 'always accepted' end context 'when configured for camelCase' do let(:cop_config) { { 'EnforcedStyle' => 'camelCase' } } it 'registers an offense for snake case in local variable name' do expect_offense(<<-RUBY.strip_indent) my_local = 1 ^^^^^^^^ Use camelCase for variable names. RUBY end it 'registers an offense for opposite + correct' do expect_offense(<<-RUBY.strip_indent) my_local = 1 ^^^^^^^^ Use camelCase for variable names. myLocal = 1 RUBY end it 'accepts camel case in local variable name' do expect_no_offenses('myLocal = 1') end it 'accepts camel case in instance variable name' do expect_no_offenses('@myAttribute = 3') end it 'accepts camel case in class variable name' do expect_no_offenses('@@myAttr = 2') end it 'registers an offense for snake case in method parameter' do expect_offense(<<-RUBY.strip_indent) def method(funny_arg); end ^^^^^^^^^ Use camelCase for variable names. RUBY end it 'accepts camel case local variables marked as unused' do expect_no_offenses('_myLocal = 1') end it 'registers an offense for default method arguments' do expect_offense(<<-RUBY.strip_indent) def foo(opt_arg = 1); end ^^^^^^^ Use camelCase for variable names. RUBY end it 'registers an offense for rest arguments' do expect_offense(<<-RUBY.strip_indent) def foo(*rest_arg); end ^^^^^^^^ Use camelCase for variable names. RUBY end it 'registers an offense for keyword arguments' do expect_offense(<<-RUBY.strip_indent) def foo(kw_arg: 1); end ^^^^^^ Use camelCase for variable names. RUBY end it 'registers an offense for keyword rest arguments' do expect_offense(<<-RUBY.strip_indent) def foo(**kw_rest); end ^^^^^^^ Use camelCase for variable names. RUBY end it 'registers an offense for block arguments' do expect_offense(<<-RUBY.strip_indent) def foo(&block_arg); end ^^^^^^^^^ Use camelCase for variable names. RUBY end include_examples 'always accepted' end end rubocop-0.52.1/spec/rubocop/cop/naming/variable_number_spec.rb000066400000000000000000000156051322072016200244030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Naming::VariableNumber, :config do subject(:cop) { described_class.new(config) } shared_examples :offense do |style, variable, style_to_allow_offenses| it "registers an offense for #{Array(variable).first} in #{style}" do inspect_source(Array(variable).map { |v| "#{v} = 1" }.join("\n")) expect(cop.messages).to eq(["Use #{style} for variable numbers."]) expect(cop.highlights).to eq(Array(variable)[0, 1]) config_to_allow_offenses = if style_to_allow_offenses { 'EnforcedStyle' => style_to_allow_offenses.to_s } else { 'Enabled' => false } end expect(cop.config_to_allow_offenses).to eq(config_to_allow_offenses) end end shared_examples :accepts do |style, variable| it "accepts #{variable} in #{style}" do inspect_source("#{variable} = 1") expect(cop.offenses.empty?).to be(true) end end context 'when configured for snake_case' do let(:cop_config) { { 'EnforcedStyle' => 'snake_case' } } it_behaves_like :offense, 'snake_case', 'local1', :normalcase it_behaves_like :offense, 'snake_case', '@local1', :normalcase it_behaves_like :offense, 'snake_case', '@@local1', :normalcase it_behaves_like :offense, 'snake_case', 'camelCase1', :normalcase it_behaves_like :offense, 'snake_case', '@camelCase1', :normalcase it_behaves_like :offense, 'snake_case', '_unused1', :normalcase it_behaves_like :offense, 'snake_case', 'aB1', :normalcase it_behaves_like :offense, 'snake_case', %w[a1 a_2], nil it_behaves_like :accepts, 'snake_case', 'local_1' it_behaves_like :accepts, 'snake_case', 'local_12' it_behaves_like :accepts, 'snake_case', 'local_123' it_behaves_like :accepts, 'snake_case', 'local_' it_behaves_like :accepts, 'snake_case', 'aB_1' it_behaves_like :accepts, 'snake_case', 'a_1_b' it_behaves_like :accepts, 'snake_case', 'a_1_b_1' it_behaves_like :accepts, 'snake_case', '_' it_behaves_like :accepts, 'snake_case', '_foo' it_behaves_like :accepts, 'snake_case', '@foo' it_behaves_like :accepts, 'snake_case', '@__foo__' it 'registers an offense for normal case numbering in method parameter' do expect_offense(<<-RUBY.strip_indent) def method(arg1); end ^^^^ Use snake_case for variable numbers. RUBY end it 'registers an offense for normal case numbering in method camel case parameter' do expect_offense(<<-RUBY.strip_indent) def method(funnyArg1); end ^^^^^^^^^ Use snake_case for variable numbers. RUBY end end context 'when configured for normal' do let(:cop_config) { { 'EnforcedStyle' => 'normalcase' } } it_behaves_like :offense, 'normalcase', 'local_1', :snake_case it_behaves_like :offense, 'normalcase', 'sha_256', :snake_case it_behaves_like :offense, 'normalcase', '@local_1', :snake_case it_behaves_like :offense, 'normalcase', '@@local_1', :snake_case it_behaves_like :offense, 'normalcase', 'myAttribute_1', :snake_case it_behaves_like :offense, 'normalcase', '@myAttribute_1', :snake_case it_behaves_like :offense, 'normalcase', '_myLocal_1', :snake_case it_behaves_like :offense, 'normalcase', 'localFOO_1', :snake_case it_behaves_like :offense, 'normalcase', 'local_FOO_1', :snake_case it_behaves_like :offense, 'normalcase', %w[a_1 a2], nil it_behaves_like :accepts, 'normalcase', 'local1' it_behaves_like :accepts, 'normalcase', 'local_' it_behaves_like :accepts, 'normalcase', 'user1_id' it_behaves_like :accepts, 'normalcase', 'sha256' it_behaves_like :accepts, 'normalcase', 'foo10_bar' it_behaves_like :accepts, 'normalcase', 'target_u2f_device' it_behaves_like :accepts, 'normalcase', 'localFOO1' it_behaves_like :accepts, 'normalcase', 'snake_case' it_behaves_like :accepts, 'normalcase', 'user_1_id' it_behaves_like :accepts, 'normalcase', '_' it_behaves_like :accepts, 'normalcase', '_foo' it_behaves_like :accepts, 'normalcase', '@foo' it_behaves_like :accepts, 'normalcase', '@__foo__' it 'registers an offense for snake case numbering in method parameter' do expect_offense(<<-RUBY.strip_indent) def method(arg_1); end ^^^^^ Use normalcase for variable numbers. RUBY end it 'registers an offense for snake case numbering in method camel case parameter' do expect_offense(<<-RUBY.strip_indent) def method(funnyArg_1); end ^^^^^^^^^^ Use normalcase for variable numbers. RUBY end end context 'when configured for non integer' do let(:cop_config) { { 'EnforcedStyle' => 'non_integer' } } it_behaves_like :offense, 'non_integer', 'local_1', :snake_case it_behaves_like :offense, 'non_integer', 'local1', :normalcase it_behaves_like :offense, 'non_integer', '@local_1', :snake_case it_behaves_like :offense, 'non_integer', '@local1', :normalcase it_behaves_like :offense, 'non_integer', 'myAttribute_1', :snake_case it_behaves_like :offense, 'non_integer', 'myAttribute1', :normalcase it_behaves_like :offense, 'non_integer', '@myAttribute_1', :snake_case it_behaves_like :offense, 'non_integer', '@myAttribute1', :normalcase it_behaves_like :offense, 'non_integer', '_myLocal_1', :snake_case it_behaves_like :offense, 'non_integer', '_myLocal1', :normalcase it_behaves_like :offense, 'non_integer', %w[a_1 aone], nil it_behaves_like :accepts, 'non_integer', 'localone' it_behaves_like :accepts, 'non_integer', 'local_one' it_behaves_like :accepts, 'non_integer', 'local_' it_behaves_like :accepts, 'non_integer', '@foo' it_behaves_like :accepts, 'non_integer', '@@foo' it_behaves_like :accepts, 'non_integer', 'fooBar' it_behaves_like :accepts, 'non_integer', '_' it_behaves_like :accepts, 'non_integer', '_foo' it_behaves_like :accepts, 'non_integer', '@__foo__' it 'registers an offense for snake case numbering in method parameter' do expect_offense(<<-RUBY.strip_indent) def method(arg_1); end ^^^^^ Use non_integer for variable numbers. RUBY end it 'registers an offense for normal case numbering in method parameter' do expect_offense(<<-RUBY.strip_indent) def method(arg1); end ^^^^ Use non_integer for variable numbers. RUBY end it 'registers an offense for snake case numbering in method camel case parameter' do expect_offense(<<-RUBY.strip_indent) def method(myArg_1); end ^^^^^^^ Use non_integer for variable numbers. RUBY end it 'registers an offense for normal case numbering in method camel case parameter' do expect_offense(<<-RUBY.strip_indent) def method(myArg1); end ^^^^^^ Use non_integer for variable numbers. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/offense_spec.rb000066400000000000000000000122441322072016200214160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Offense do subject(:offense) do described_class.new(:convention, location, 'message', 'CopName', :corrected) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end it 'has a few required attributes' do expect(offense.severity).to eq(:convention) expect(offense.line).to eq(1) expect(offense.message).to eq('message') expect(offense.cop_name).to eq('CopName') expect(offense.corrected?).to be_truthy expect(offense.highlighted_area.source).to eq('a') end it 'overrides #to_s' do expect(offense.to_s).to eq('C: 1: 1: message') end it 'does not blow up if a message contains %' do offense = described_class.new(:convention, location, 'message % test', 'CopName') expect(offense.to_s).to eq('C: 1: 1: message % test') end it 'redefines == to compare offenses based on their contents' do o1 = described_class.new(:convention, location, 'message', 'CopName') o2 = described_class.new(:convention, location, 'message', 'CopName') expect(o1 == o2).to be_truthy end it 'is frozen' do expect(offense.frozen?).to be(true) end %i[severity location message cop_name].each do |a| describe "##{a}" do it 'is frozen' do expect(offense.send(a).frozen?).to be(true) end end end context 'when unknown severity is passed' do it 'raises error' do expect do described_class.new(:foobar, location, 'message', 'CopName') end.to raise_error(ArgumentError) end end describe '#severity_level' do subject(:severity_level) do described_class.new(severity, location, 'message', 'CopName') .severity .level end context 'when severity is :refactor' do let(:severity) { :refactor } it 'is 1' do expect(severity_level).to eq(1) end end context 'when severity is :fatal' do let(:severity) { :fatal } it 'is 5' do expect(severity_level).to eq(5) end end end describe '#<=>' do def offense(hash = {}) attrs = { sev: :convention, line: 5, col: 5, mes: 'message', cop: 'CopName' }.merge(hash) described_class.new( attrs[:sev], location(attrs[:line], attrs[:col], %w[aaaaaa bbbbbb cccccc dddddd eeeeee ffffff]), attrs[:mes], attrs[:cop] ) end def location(line, column, source) source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = source.join("\n") begin_pos = source[0...(line - 1)].reduce(0) do |a, e| a + e.length + 1 end + column Parser::Source::Range.new(source_buffer, begin_pos, begin_pos + 1) end # We want a nice table layout, so we allow space inside empty hashes. # rubocop:disable Layout/SpaceInsideHashLiteralBraces, Layout/ExtraSpacing [ [{ }, { }, 0], [{ line: 6 }, { line: 5 }, 1], [{ line: 5, col: 6 }, { line: 5, col: 5 }, 1], [{ line: 6, col: 4 }, { line: 5, col: 5 }, 1], [{ cop: 'B' }, { cop: 'A' }, 1], [{ line: 6, cop: 'A' }, { line: 5, cop: 'B' }, 1], [{ col: 6, cop: 'A' }, { col: 5, cop: 'B' }, 1] ].each do |one, other, expectation| # rubocop:enable Layout/SpaceInsideHashLiteralBraces, Layout/ExtraSpacing context "when receiver has #{one} and other has #{other}" do it "returns #{expectation}" do an_offense = offense(one) other_offense = offense(other) expect(an_offense <=> other_offense).to eq(expectation) end end end end context 'offenses that span multiple lines' do subject(:offense) do described_class .new(:convention, location, 'message', 'CopName', :corrected) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = <<-RUBY.strip_indent def foo something something_else end RUBY Parser::Source::Range.new(source_buffer, 0, source_buffer.source.length) end it 'highlights the first line' do expect(offense.location.source).to eq(location.source_buffer.source) expect(offense.highlighted_area.source).to eq('def foo') end end context 'offenses that span part of a line' do subject(:offense) do described_class .new(:convention, location, 'message', 'CopName', :corrected) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = <<-RUBY.strip_indent def Foo something something_else end RUBY Parser::Source::Range.new(source_buffer, 4, 7) end it 'highlights the first line' do expect(offense.highlighted_area.source).to eq('Foo') end end end rubocop-0.52.1/spec/rubocop/cop/performance/000077500000000000000000000000001322072016200207305ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/performance/caller_spec.rb000066400000000000000000000052211322072016200235310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Caller do subject(:cop) { described_class.new } it 'accepts `caller` without argument and method chain' do expect_no_offenses('caller') end it 'accepts `caller` with arguments' do expect_no_offenses('caller(1, 1).first') end it 'accepts `caller_locations` without argument and method chain' do expect_no_offenses('caller_locations') end it 'registers an offense when :first is called on caller' do expect(caller.first).to eq(caller(1..1).first) expect_offense(<<-RUBY.strip_indent) caller.first ^^^^^^^^^^^^ Use `caller(1..1).first` instead of `caller.first`. RUBY end it 'registers an offense when :first is called on caller with 1' do expect(caller(1).first).to eq(caller(1..1).first) expect_offense(<<-RUBY.strip_indent) caller(1).first ^^^^^^^^^^^^^^^ Use `caller(1..1).first` instead of `caller.first`. RUBY end it 'registers an offense when :first is called on caller with 2' do expect(caller(2).first).to eq(caller(2..2).first) expect_offense(<<-RUBY.strip_indent) caller(2).first ^^^^^^^^^^^^^^^ Use `caller(2..2).first` instead of `caller.first`. RUBY end it 'registers an offense when :[] is called on caller' do expect(caller[1]).to eq(caller(2..2).first) expect_offense(<<-RUBY.strip_indent) caller[1] ^^^^^^^^^ Use `caller(2..2).first` instead of `caller[1]`. RUBY end it 'registers an offense when :[] is called on caller with 1' do expect(caller(1)[1]).to eq(caller(2..2).first) expect_offense(<<-RUBY.strip_indent) caller(1)[1] ^^^^^^^^^^^^ Use `caller(2..2).first` instead of `caller[1]`. RUBY end it 'registers an offense when :[] is called on caller with 2' do expect(caller(2)[1]).to eq(caller(3..3).first) expect_offense(<<-RUBY.strip_indent) caller(2)[1] ^^^^^^^^^^^^ Use `caller(3..3).first` instead of `caller[1]`. RUBY end it 'registers an offense when :first is called on caller_locations also' do expect(caller_locations.first.to_s).to eq(caller_locations(1..1).first.to_s) expect_offense(<<-RUBY.strip_indent) caller_locations.first ^^^^^^^^^^^^^^^^^^^^^^ Use `caller_locations(1..1).first` instead of `caller_locations.first`. RUBY end it 'registers an offense when :[] is called on caller_locations also' do expect(caller_locations[1].to_s).to eq(caller_locations(2..2).first.to_s) expect_offense(<<-RUBY.strip_indent) caller_locations[1] ^^^^^^^^^^^^^^^^^^^ Use `caller_locations(2..2).first` instead of `caller_locations[1]`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/case_when_splat_spec.rb000066400000000000000000000236101322072016200254300ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::CaseWhenSplat do subject(:cop) { described_class.new } let(:message) do 'Place `when` conditions with a splat at ' \ 'the end of the `when` branches.' end it 'allows case when without splat' do expect_no_offenses(<<-RUBY.strip_indent) case foo when 1 bar else baz end RUBY end it 'allows splat on a variable in the last when condition' do expect_no_offenses(<<-RUBY.strip_indent) case foo when 4 foobar when *cond bar else baz end RUBY end it 'allows multiple splat conditions on variables at the end' do expect_no_offenses(<<-RUBY.strip_indent) case foo when 4 foobar when *cond1 bar when *cond2 doo else baz end RUBY end it 'registers an offense for case when with a splat in the first condition' do expect_offense(<<-RUBY.strip_indent) case foo when *cond ^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when 4 foobar else baz end RUBY end it 'registers an offense for case when with a splat without an else' do expect_offense(<<-RUBY.strip_indent) case foo when *baz ^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when 4 foobar end RUBY end it 'registers an offense for splat conditions in when then' do expect_offense(<<-RUBY.strip_indent) case foo when *cond then bar ^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. when 4 then baz end RUBY end it 'registers an offense for a single when with splat expansion followed ' \ 'by another value' do inspect_source(<<-RUBY.strip_indent) case foo when *Foo, Bar nil end RUBY expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(['when *Foo']) end it 'registers an offense for multiple splat conditions at the beginning' do expect_offense(<<-RUBY.strip_indent) case foo when *cond1 ^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when *cond2 ^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. doo when 4 foobar else baz end RUBY end it 'registers an offense for multiple out of order splat conditions' do expect_offense(<<-RUBY.strip_indent) case foo when *cond1 ^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when 8 barfoo when *SOME_CONSTANT ^^^^^^^^^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. doo when 4 foobar else baz end RUBY end it 'registers an offense for splat condition that do not appear at the end' do expect_offense(<<-RUBY.strip_indent) case foo when *cond1 ^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when 8 barfoo when *cond2 ^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. doo when 4 foobar when *cond3 doofoo else baz end RUBY end it 'allows splat expansion on an array literal' do expect_no_offenses(<<-RUBY.strip_indent) case foo when *[1, 2] bar when *[3, 4] bar when 5 baz end RUBY end it 'allows splat expansion on array literal as the last condition' do expect_no_offenses(<<-RUBY.strip_indent) case foo when *[1, 2] bar end RUBY end it 'registers an offense for a splat on a variable that proceeds a splat ' \ 'on an array literal as the last condition' do inspect_source(<<-RUBY.strip_indent) case foo when *cond bar when *[1, 2] baz end RUBY expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(['when *cond']) end it 'registers an offense when splat is part of the condition' do expect_offense(<<-RUBY.strip_indent) case foo when cond1, *cond2 ^^^^^^^^^^^^^^^^^^ Place `when` conditions with a splat at the end of the `when` branches. bar when cond3 baz end RUBY end context 'autocorrect' do it 'corrects a single when with splat expansion followed by ' \ 'another value' do source = <<-RUBY.strip_indent case foo when *Foo, Bar, Baz nil end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when Bar, Baz, *Foo nil end RUBY end it 'corrects a when with splat expansion followed by another value ' \ 'when there are multiple whens' do source = <<-RUBY.strip_indent case foo when *Foo, Bar nil when FooBar 1 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when FooBar 1 when Bar, *Foo nil end RUBY end it 'corrects a when with multiple out of order splat expansions ' \ 'followed by other values when there are multiple whens' do source = <<-RUBY.strip_indent case foo when *Foo, Bar, *Baz, Qux nil when FooBar 1 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when FooBar 1 when Bar, Qux, *Foo, *Baz nil end RUBY end it 'moves a single splat condition to the end of the when conditions' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *cond bar when 3 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 3 baz when *cond bar end RUBY end it 'moves multiple splat condition to the end of the when conditions' do new_source = autocorrect_source_with_loop(<<-RUBY.strip_indent) case foo when *cond1 bar when *cond2 foobar when 5 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 5 baz when *cond1 bar when *cond2 foobar end RUBY end it 'moves multiple out of order splat condition to the end ' \ 'of the when conditions' do new_source = autocorrect_source_with_loop(<<-RUBY.strip_indent) case foo when *cond1 bar when 3 doo when *cond2 foobar when 6 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 3 doo when 6 baz when *cond1 bar when *cond2 foobar end RUBY end it 'corrects splat condition when using when then' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *cond then bar when 4 then baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when 4 then baz when *cond then bar end RUBY end it 'corrects nested case when statements' do new_source = autocorrect_source(<<-RUBY.strip_indent) def check case foo when *cond bar when 3 baz end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def check case foo when 3 baz when *cond bar end end RUBY end it 'corrects splat on a variable and leaves an array literal alone' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *cond bar when *[1, 2] baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when *[1, 2] baz when *cond bar end RUBY end it 'corrects a splat as part of the condition' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when cond1, *cond2 bar when cond3 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when cond3 baz when cond1, *cond2 bar end RUBY end it 'corrects an array followed by splat in the same condition' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *[cond1, cond2], *cond3 bar when cond4 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when cond4 baz when *[cond1, cond2], *cond3 bar end RUBY end it 'corrects a splat followed by array in the same condition' do new_source = autocorrect_source(<<-RUBY.strip_indent) case foo when *cond1, *[cond2, cond3] bar when cond4 baz end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) case foo when cond4 baz when *cond1, *[cond2, cond3] bar end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/performance/casecmp_spec.rb000066400000000000000000000116351322072016200237100ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Casecmp do subject(:cop) { described_class.new } shared_examples 'selectors' do |selector| it "autocorrects str.#{selector} ==" do new_source = autocorrect_source("str.#{selector} == 'string'") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects str.#{selector} == with parens around arg" do new_source = autocorrect_source("str.#{selector} == ('string')") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects str.#{selector} !=" do new_source = autocorrect_source("str.#{selector} != 'string'") expect(new_source).to eq "!str.casecmp('string').zero?" end it "autocorrects str.#{selector} != with parens around arg" do new_source = autocorrect_source("str.#{selector} != ('string')") expect(new_source).to eq "!str.casecmp('string').zero?" end it "autocorrects str.#{selector}.eql? without parens" do new_source = autocorrect_source("str.#{selector}.eql? 'string'") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects str.#{selector}.eql? with parens" do new_source = autocorrect_source("str.#{selector}.eql?('string')") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects str.#{selector}.eql? with parens and funny spacing" do new_source = autocorrect_source("str.#{selector}.eql? ( 'string' )") expect(new_source).to eq "str.casecmp( 'string' ).zero?" end it "autocorrects == str.#{selector}" do new_source = autocorrect_source("'string' == str.#{selector}") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects string with parens == str.#{selector}" do new_source = autocorrect_source("('string') == str.#{selector}") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects string != str.#{selector}" do new_source = autocorrect_source("'string' != str.#{selector}") expect(new_source).to eq "!str.casecmp('string').zero?" end it 'autocorrects string with parens and funny spacing ' \ "eql? str.#{selector}" do new_source = autocorrect_source("( 'string' ).eql? str.#{selector}") expect(new_source).to eq "str.casecmp( 'string' ).zero?" end it "autocorrects string.eql? str.#{selector} without parens " do new_source = autocorrect_source("'string'.eql? str.#{selector}") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects string.eql? str.#{selector} with parens " do new_source = autocorrect_source("'string'.eql?(str.#{selector})") expect(new_source).to eq "str.casecmp('string').zero?" end it "autocorrects obj.#{selector} == str.#{selector}" do new_source = autocorrect_source("obj.#{selector} == str.#{selector}") expect(new_source).to eq "obj.casecmp(str.#{selector}).zero?" end it "autocorrects obj.#{selector} eql? str.#{selector}" do new_source = autocorrect_source("obj.#{selector}.eql? str.#{selector}") expect(new_source).to eq "obj.casecmp(str.#{selector}).zero?" end it "formats the error message correctly for str.#{selector} ==" do inspect_source("str.#{selector} == 'string'") expect(cop.highlights).to eq(["#{selector} =="]) expect(cop.messages).to eq(["Use `casecmp` instead of `#{selector} ==`."]) end it "formats the error message correctly for == str.#{selector}" do inspect_source("'string' == str.#{selector}") expect(cop.highlights).to eq(["== str.#{selector}"]) expect(cop.messages).to eq(["Use `casecmp` instead of `== #{selector}`."]) end it 'formats the error message correctly for ' \ "obj.#{selector} == str.#{selector}" do inspect_source("obj.#{selector} == str.#{selector}") expect(cop.highlights).to eq(["obj.#{selector} == str.#{selector}"]) expect(cop.messages).to eq(["Use `casecmp` instead of `#{selector} ==`."]) end it "doesn't report an offense for variable == str.#{selector}" do inspect_source(<<-RUBY.strip_indent) var = "a" var == str.#{selector} RUBY expect(cop.offenses.empty?).to be(true) end it "doesn't report an offense for str.#{selector} == variable" do inspect_source(<<-RUBY.strip_indent) var = "a" str.#{selector} == var RUBY expect(cop.offenses.empty?).to be(true) end it "doesn't report an offense for obj.method == str.#{selector}" do inspect_source("obj.method == str.#{selector}") expect(cop.offenses.empty?).to be(true) end it "doesn't report an offense for str.#{selector} == obj.method" do inspect_source("str.#{selector} == obj.method") expect(cop.offenses.empty?).to be(true) end end it_behaves_like('selectors', 'upcase') it_behaves_like('selectors', 'downcase') end rubocop-0.52.1/spec/rubocop/cop/performance/compare_with_block_spec.rb000066400000000000000000000074751322072016200261370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::CompareWithBlock do subject(:cop) { described_class.new } shared_examples 'compare with block' do |method| it "registers an offense for #{method}" do inspect_source("array.#{method} { |a, b| a.foo <=> b.foo }") expect(cop.offenses.size).to eq(1) end it "registers an offense for #{method} with [:foo]" do inspect_source("array.#{method} { |a, b| a[:foo] <=> b[:foo] }") expect(cop.offenses.size).to eq(1) end it "registers an offense for #{method} with ['foo']" do inspect_source("array.#{method} { |a, b| a['foo'] <=> b['foo'] }") expect(cop.offenses.size).to eq(1) end it "registers an offense for #{method} with [1]" do inspect_source("array.#{method} { |a, b| a[1] <=> b[1] }") expect(cop.offenses.size).to eq(1) end it 'highlights compare method' do inspect_source("array.#{method} { |a, b| a.foo <=> b.foo }") expect(cop.highlights).to eq(["#{method} { |a, b| a.foo <=> b.foo }"]) end it "accepts valid #{method} usage" do inspect_source("array.#{method} { |a, b| b <=> a }") expect(cop.offenses.empty?).to be(true) end it "accepts #{method}_by" do inspect_source("array.#{method}_by { |a| a.baz }") end it "autocorrects array.#{method} { |a, b| a.foo <=> b.foo }" do new_source = autocorrect_source("array.#{method} { |a, b| a.foo <=> b.foo }") expect(new_source).to eq "array.#{method}_by(&:foo)" end it "autocorrects array.#{method} { |a, b| a.bar <=> b.bar }" do new_source = autocorrect_source("array.#{method} { |a, b| a.bar <=> b.bar }") expect(new_source).to eq "array.#{method}_by(&:bar)" end it "autocorrects array.#{method} { |x, y| x.foo <=> y.foo }" do new_source = autocorrect_source("array.#{method} { |x, y| x.foo <=> y.foo }") expect(new_source).to eq "array.#{method}_by(&:foo)" end it "autocorrects array.#{method} do |a, b| a.foo <=> b.foo end" do new_source = autocorrect_source(<<-RUBY.strip_indent) array.#{method} do |a, b| a.foo <=> b.foo end RUBY expect(new_source).to eq "array.#{method}_by(&:foo)\n" end it "autocorrects array.#{method} { |a, b| a[:foo] <=> b[:foo] }" do new_source = autocorrect_source( "array.#{method} { |a, b| a[:foo] <=> b[:foo] }" ) expect(new_source).to eq "array.#{method}_by { |a| a[:foo] }" end it "autocorrects array.#{method} { |a, b| a['foo'] <=> b['foo'] }" do new_source = autocorrect_source( "array.#{method} { |a, b| a['foo'] <=> b['foo'] }" ) expect(new_source).to eq "array.#{method}_by { |a| a['foo'] }" end it "autocorrects array.#{method} { |a, b| a[1] <=> b[1] }" do new_source = autocorrect_source( "array.#{method} { |a, b| a[1] <=> b[1] }" ) expect(new_source).to eq "array.#{method}_by { |a| a[1] }" end it 'formats the error message correctly for ' \ "array.#{method} { |a, b| a.foo <=> b.foo }" do inspect_source("array.#{method} { |a, b| a.foo <=> b.foo }") expect(cop.messages).to eq(["Use `#{method}_by(&:foo)` instead of " \ "`#{method} { |a, b| a.foo <=> b.foo }`."]) end it 'formats the error message correctly for ' \ "array.#{method} { |a, b| a[:foo] <=> b[:foo] }" do inspect_source("array.#{method} { |a, b| a[:foo] <=> b[:foo] }") expected = ["Use `#{method}_by { |a| a[:foo] }` instead of " \ "`#{method} { |a, b| a[:foo] <=> b[:foo] }`."] expect(cop.messages).to eq(expected) end end include_examples 'compare with block', 'sort' include_examples 'compare with block', 'max' include_examples 'compare with block', 'min' end rubocop-0.52.1/spec/rubocop/cop/performance/count_spec.rb000066400000000000000000000227241322072016200234260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Count do subject(:cop) { described_class.new } shared_examples 'selectors' do |selector| it "registers an offense for using array.#{selector}...size" do inspect_source("[1, 2, 3].#{selector} { |e| e.even? }.size") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...size`."]) expect(cop.highlights).to eq(["#{selector} { |e| e.even? }.size"]) end it "registers an offense for using hash.#{selector}...size" do inspect_source("{a: 1, b: 2, c: 3}.#{selector} { |e| e == :a }.size") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...size`."]) expect(cop.highlights).to eq(["#{selector} { |e| e == :a }.size"]) end it "registers an offense for using array.#{selector}...length" do inspect_source("[1, 2, 3].#{selector} { |e| e.even? }.length") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...length`."]) expect(cop.highlights).to eq(["#{selector} { |e| e.even? }.length"]) end it "registers an offense for using hash.#{selector}...length" do inspect_source("{a: 1, b: 2}.#{selector} { |e| e == :a }.length") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...length`."]) expect(cop.highlights).to eq(["#{selector} { |e| e == :a }.length"]) end it "registers an offense for using array.#{selector}...count" do inspect_source("[1, 2, 3].#{selector} { |e| e.even? }.count") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...count`."]) expect(cop.highlights).to eq(["#{selector} { |e| e.even? }.count"]) end it "registers an offense for using hash.#{selector}...count" do inspect_source("{a: 1, b: 2}.#{selector} { |e| e == :a }.count") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...count`."]) expect(cop.highlights).to eq(["#{selector} { |e| e == :a }.count"]) end it "allows usage of #{selector}...count with a block on an array" do inspect_source("[1, 2, 3].#{selector} { |e| e.odd? }.count { |e| e > 2 }") expect(cop.messages.empty?).to be(true) end it "allows usage of #{selector}...count with a block on a hash" do source = "{a: 1, b: 2}.#{selector} { |e| e == :a }.count { |e| e > 2 }" inspect_source(source) expect(cop.messages.empty?).to be(true) end it "registers an offense for #{selector} with params instead of a block" do inspect_source(<<-RUBY.strip_indent) Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] puts array.#{selector}(&:value).count RUBY expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...count`."]) expect(cop.highlights).to eq(["#{selector}(&:value).count"]) end it "registers an offense for #{selector}(&:something).count" do inspect_source("foo.#{selector}(&:something).count") expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...count`."]) expect(cop.highlights).to eq(["#{selector}(&:something).count"]) end it "registers an offense for #{selector}(&:something).count " \ 'when called as an instance method on its own class' do source = <<-RUBY.strip_indent class A < Array def count(&block) #{selector}(&block).count end end RUBY inspect_source(source) expect(cop.messages) .to eq(["Use `count` instead of `#{selector}...count`."]) expect(cop.highlights).to eq(["#{selector}(&block).count"]) end it "allows usage of #{selector} without getting the size" do inspect_source("[1, 2, 3].#{selector} { |e| e.even? }") expect(cop.messages.empty?).to be(true) end context 'bang methods' do it "allows usage of #{selector}!...size" do inspect_source("[1, 2, 3].#{selector}! { |e| e.odd? }.size") expect(cop.messages.empty?).to be(true) end it "allows usage of #{selector}!...count" do inspect_source("[1, 2, 3].#{selector}! { |e| e.odd? }.count") expect(cop.messages.empty?).to be(true) end it "allows usage of #{selector}!...length" do inspect_source("[1, 2, 3].#{selector}! { |e| e.odd? }.length") expect(cop.messages.empty?).to be(true) end end end it_behaves_like('selectors', 'select') it_behaves_like('selectors', 'reject') context 'ActiveRecord select' do it 'allows usage of select with a string' do expect_no_offenses("Model.select('field AS field_one').count") end it 'allows usage of select with multiple strings' do expect_no_offenses(<<-RUBY.strip_indent) Model.select('field AS field_one', 'other AS field_two').count RUBY end it 'allows usage of select with a symbol' do expect_no_offenses('Model.select(:field).count') end it 'allows usage of select with multiple symbols' do expect_no_offenses('Model.select(:field, :other_field).count') end end it 'allows usage of another method with size' do expect_no_offenses('[1, 2, 3].map { |e| e + 1 }.size') end it 'allows usage of size on an array' do expect_no_offenses('[1, 2, 3].size') end it 'allows usage of count on an array' do expect_no_offenses('[1, 2, 3].count') end it 'allows usage of count on an interstitial method called on select' do expect_no_offenses(<<-RUBY.strip_indent) Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] puts array.select(&:value).uniq.count RUBY end it 'allows usage of count on an interstitial method with blocks ' \ 'called on select' do inspect_source(<<-RUBY.strip_indent) Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] array.select(&:value).uniq { |v| v > 2 }.count RUBY expect(cop.messages.empty?).to be(true) end it 'allows usage of size called on an assigned variable' do expect_no_offenses(<<-RUBY.strip_indent) nodes = [1] nodes.size RUBY end it 'allows usage of methods called on size' do expect_no_offenses('shorter.size.to_f') end context 'properly parses non related code' do it 'will not raise an error for Bundler.setup' do expect { inspect_source('Bundler.setup(:default, :development)') } .not_to raise_error end it 'will not raise an error for RakeTask.new' do expect { inspect_source('RakeTask.new(:spec)') } .not_to raise_error end end context 'autocorrect' do context 'will correct' do it 'select..size to count' do new_source = autocorrect_source('[1, 2].select { |e| e > 2 }.size') expect(new_source).to eq('[1, 2].count { |e| e > 2 }') end it 'select..count without a block to count' do new_source = autocorrect_source('[1, 2].select { |e| e > 2 }.count') expect(new_source).to eq('[1, 2].count { |e| e > 2 }') end it 'select..length to count' do new_source = autocorrect_source('[1, 2].select { |e| e > 2 }.length') expect(new_source).to eq('[1, 2].count { |e| e > 2 }') end it 'select...size when select has parameters' do source = <<-RUBY.strip_indent Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] puts array.select(&:value).size RUBY new_source = autocorrect_source(source) expect(new_source) .to eq(<<-RUBY.strip_indent) Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] puts array.count(&:value) RUBY end end describe 'will not correct' do it 'reject...size' do new_source = autocorrect_source('[1, 2].reject { |e| e > 2 }.size') expect(new_source).to eq('[1, 2].reject { |e| e > 2 }.size') end it 'reject...count' do new_source = autocorrect_source('[1, 2].reject { |e| e > 2 }.count') expect(new_source).to eq('[1, 2].reject { |e| e > 2 }.count') end it 'reject...length' do new_source = autocorrect_source('[1, 2].reject { |e| e > 2 }.length') expect(new_source).to eq('[1, 2].reject { |e| e > 2 }.length') end it 'select...count when count has a block' do source = '[1, 2].select { |e| e > 2 }.count { |e| e.even? }' new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'reject...size when select has parameters' do source = <<-RUBY.strip_indent Data = Struct.new(:value) array = [Data.new(2), Data.new(3), Data.new(2)] puts array.reject(&:value).size RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end context 'SafeMode true' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( 'Rails' => { 'Enabled' => true }, 'Performance/Count' => { 'SafeMode' => true } ) end shared_examples 'selectors' do |selector| it "allows using array.#{selector}...size" do inspect_source("[1, 2, 3].#{selector} { |e| e.even? }.size") expect(cop.offenses.empty?).to be(true) end end it_behaves_like('selectors', 'select') it_behaves_like('selectors', 'reject') end end rubocop-0.52.1/spec/rubocop/cop/performance/detect_spec.rb000066400000000000000000000172451322072016200235500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Detect do subject(:cop) { described_class.new(config) } let(:collection_method) { nil } let(:config) do RuboCop::Config.new( 'Style/CollectionMethods' => { 'PreferredMethods' => { 'detect' => collection_method } } ) end # rspec will not let you use a variable assigned using let outside # of `it` select_methods = %i[select find_all].freeze select_methods.each do |method| it "registers an offense when first is called on #{method}" do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }.first") expect(cop.messages) .to eq(["Use `detect` instead of `#{method}.first`."]) end it "doesn't register an offense when first(n) is called on #{method}" do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }.first(n)") expect(cop.offenses.empty?).to be(true) end it "registers an offense when last is called on #{method}" do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }.last") expect(cop.messages) .to eq(["Use `reverse.detect` instead of `#{method}.last`."]) end it "doesn't register an offense when last(n) is called on #{method}" do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }.last(n)") expect(cop.offenses.empty?).to be(true) end it "registers an offense when first is called on multiline #{method}" do inspect_source(<<-RUBY.strip_indent) [1, 2, 3].#{method} do |i| i % 2 == 0 end.first RUBY expect(cop.messages).to eq(["Use `detect` instead of `#{method}.first`."]) end it "registers an offense when last is called on multiline #{method}" do inspect_source(<<-RUBY.strip_indent) [1, 2, 3].#{method} do |i| i % 2 == 0 end.last RUBY expect(cop.messages) .to eq(["Use `reverse.detect` instead of `#{method}.last`."]) end it "registers an offense when first is called on #{method} short syntax" do inspect_source("[1, 2, 3].#{method}(&:even?).first") expect(cop.messages).to eq(["Use `detect` instead of `#{method}.first`."]) end it "registers an offense when last is called on #{method} short syntax" do inspect_source("[1, 2, 3].#{method}(&:even?).last") expect(cop.messages) .to eq(["Use `reverse.detect` instead of `#{method}.last`."]) end it "registers an offense when #{method} is called" \ 'on `lazy` without receiver' do inspect_source("lazy.#{method}(&:even?).first") expect(cop.messages).to eq(["Use `detect` instead of `#{method}.first`."]) end it "does not register an offense when #{method} is used " \ 'without first or last' do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }") expect(cop.messages.empty?).to be(true) end it "does not register an offense when #{method} is called" \ 'without block or args' do inspect_source("adapter.#{method}.first") expect(cop.messages.empty?).to be(true) end it "does not register an offense when #{method} is called" \ 'with args but without ampersand syntax' do inspect_source("adapter.#{method}('something').first") expect(cop.messages.empty?).to be(true) end it "does not register an offense when #{method} is called" \ 'on lazy enumerable' do inspect_source("adapter.lazy.#{method} { 'something' }.first") expect(cop.messages.empty?).to be(true) end end it 'does not register an offense when detect is used' do expect_no_offenses('[1, 2, 3].detect { |i| i % 2 == 0 }') end context 'autocorrect' do shared_examples 'detect_autocorrect' do |preferred_method| context "with #{preferred_method}" do let(:collection_method) { preferred_method } select_methods.each do |method| it "corrects #{method}.first to #{preferred_method} (with block)" do source = "[1, 2, 3].#{method} { |i| i % 2 == 0 }.first" new_source = autocorrect_source(source) expect(new_source) .to eq("[1, 2, 3].#{preferred_method} { |i| i % 2 == 0 }") end it "corrects #{method}.last to reverse.#{preferred_method} " \ '(with block)' do source = "[1, 2, 3].#{method} { |i| i % 2 == 0 }.last" new_source = autocorrect_source(source) expect(new_source) .to eq("[1, 2, 3].reverse.#{preferred_method} { |i| i % 2 == 0 }") end it "corrects #{method}.first to #{preferred_method} (short syntax)" do source = "[1, 2, 3].#{method}(&:even?).first" new_source = autocorrect_source(source) expect(new_source).to eq("[1, 2, 3].#{preferred_method}(&:even?)") end it "corrects #{method}.last to reverse.#{preferred_method} " \ '(short syntax)' do source = "[1, 2, 3].#{method}(&:even?).last" new_source = autocorrect_source(source) expect(new_source) .to eq("[1, 2, 3].reverse.#{preferred_method}(&:even?)") end it "corrects #{method}.first to #{preferred_method} (multiline)" do source = <<-RUBY.strip_indent [1, 2, 3].#{method} do |i| i % 2 == 0 end.first RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) [1, 2, 3].#{preferred_method} do |i| i % 2 == 0 end RUBY end it "corrects #{method}.last to reverse.#{preferred_method} " \ '(multiline)' do source = <<-RUBY.strip_indent [1, 2, 3].#{method} do |i| i % 2 == 0 end.last RUBY new_source = autocorrect_source(source) expect(new_source) .to eq(<<-RUBY.strip_indent) [1, 2, 3].reverse.#{preferred_method} do |i| i % 2 == 0 end RUBY end it "corrects multiline #{method} to #{preferred_method} " \ "with 'first' on the last line" do source = <<-RUBY.strip_indent [1, 2, 3].#{method} { true } .first['x'] RUBY new_source = autocorrect_source(source) expect(new_source) .to eq("[1, 2, 3].#{preferred_method} { true }['x']\n") end it "corrects multiline #{method} to #{preferred_method} " \ "with 'first' on the last line (short syntax)" do source = <<-RUBY.strip_indent [1, 2, 3].#{method}(&:blank?) .first['x'] RUBY new_source = autocorrect_source(source) expect(new_source) .to eq("[1, 2, 3].#{preferred_method}(&:blank?)['x']\n") end end end end it_behaves_like 'detect_autocorrect', 'detect' it_behaves_like 'detect_autocorrect', 'find' end context 'SafeMode true' do let(:config) do RuboCop::Config.new( 'Rails' => { 'Enabled' => true }, 'Style/CollectionMethods' => { 'PreferredMethods' => { 'detect' => collection_method } }, 'Performance/Detect' => { 'SafeMode' => true } ) end select_methods.each do |method| it "doesn't register an offense when first is called on #{method}" do inspect_source("[1, 2, 3].#{method} { |i| i % 2 == 0 }.first") expect(cop.offenses.empty?).to be(true) end end end end rubocop-0.52.1/spec/rubocop/cop/performance/double_start_end_with_spec.rb000066400000000000000000000176101322072016200266440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::DoubleStartEndWith do subject(:cop) { described_class.new(config) } context 'IncludeActiveSupportAliases: false' do let(:config) do RuboCop::Config.new( 'Performance/DoubleStartEndWith' => { 'IncludeActiveSupportAliases' => false } ) end context 'two #start_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.start_with?(a, b) || x.start_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Use `x.start_with?(a, b, "c", D)` instead of ' \ '`x.start_with?(a, b) || x.start_with?("c", D)`.' ) expect(cop.highlights).to eq( ['x.start_with?(a, b) || x.start_with?("c", D)'] ) end it 'corrects to a single start_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.start_with?(a, b, "c", D)') end end context 'one of the parameters of the second call is not pure' do it "doesn't register an offense" do expect_no_offenses('x.start_with?(a, "b") || x.start_with?(C, d)') end end end context 'with different receivers' do it "doesn't register an offense" do expect_no_offenses('x.start_with?("a") || y.start_with?("b")') end end end context 'two #end_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.end_with?(a, b) || x.end_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Use `x.end_with?(a, b, "c", D)` instead of ' \ '`x.end_with?(a, b) || x.end_with?("c", D)`.' ) expect(cop.highlights).to eq( ['x.end_with?(a, b) || x.end_with?("c", D)'] ) end it 'corrects to a single end_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.end_with?(a, b, "c", D)') end end context 'one of the parameters of the second call is not pure' do it "doesn't register an offense" do expect_no_offenses('x.end_with?(a, "b") || x.end_with?(C, d)') end end end context 'with different receivers' do it "doesn't register an offense" do expect_no_offenses('x.end_with?("a") || y.end_with?("b")') end end end context 'a .start_with? and .end_with? call with the same receiver' do it "doesn't register an offense" do expect_no_offenses('x.start_with?("a") || x.end_with?("b")') end end context 'two #starts_with? calls' do it "doesn't register an offense" do expect_no_offenses('x.starts_with?(a, b) || x.starts_with?("c", D)') end end context 'two #ends_with? calls' do it "doesn't register an offense" do expect_no_offenses('x.ends_with?(a, b) || x.ends_with?("c", D)') end end end context 'IncludeActiveSupportAliases: true' do let(:config) do RuboCop::Config.new( 'Performance/DoubleStartEndWith' => { 'IncludeActiveSupportAliases' => true } ) end context 'two #start_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.start_with?(a, b) || x.start_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Use `x.start_with?(a, b, "c", D)` instead of ' \ '`x.start_with?(a, b) || x.start_with?("c", D)`.') expect(cop.highlights) .to eq(['x.start_with?(a, b) || x.start_with?("c", D)']) end it 'corrects to a single start_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.start_with?(a, b, "c", D)') end end end end context 'two #end_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.end_with?(a, b) || x.end_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message) .to eq('Use `x.end_with?(a, b, "c", D)` instead of ' \ '`x.end_with?(a, b) || x.end_with?("c", D)`.') expect(cop.highlights) .to eq(['x.end_with?(a, b) || x.end_with?("c", D)']) end it 'corrects to a single end_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.end_with?(a, b, "c", D)') end end end end context 'two #starts_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.starts_with?(a, b) || x.starts_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Use `x.starts_with?(a, b, "c", D)` instead of ' \ '`x.starts_with?(a, b) || x.starts_with?("c", D)`.' ) expect(cop.highlights).to eq( ['x.starts_with?(a, b) || x.starts_with?("c", D)'] ) end it 'corrects to a single starts_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.starts_with?(a, b, "c", D)') end end context 'one of the parameters of the second call is not pure' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) x.starts_with?(a, "b") || x.starts_with?(C, d) RUBY end end end context 'with different receivers' do it "doesn't register an offense" do expect_no_offenses('x.starts_with?("a") || y.starts_with?("b")') end end end context 'two #ends_with? calls' do context 'with the same receiver' do context 'all parameters of the second call are pure' do let(:source) { 'x.ends_with?(a, b) || x.ends_with?("c", D)' } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( 'Use `x.ends_with?(a, b, "c", D)` instead of ' \ '`x.ends_with?(a, b) || x.ends_with?("c", D)`.' ) expect(cop.highlights).to eq( ['x.ends_with?(a, b) || x.ends_with?("c", D)'] ) end it 'corrects to a single ends_with?' do new_source = autocorrect_source(source) expect(new_source).to eq('x.ends_with?(a, b, "c", D)') end end context 'one of the parameters of the second call is not pure' do it "doesn't register an offense" do expect_no_offenses('x.ends_with?(a, "b") || x.ends_with?(C, d)') end end end context 'with different receivers' do it "doesn't register an offense" do expect_no_offenses('x.ends_with?("a") || y.ends_with?("b")') end end end end end rubocop-0.52.1/spec/rubocop/cop/performance/end_with_spec.rb000066400000000000000000000053371322072016200241000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::EndWith do subject(:cop) { described_class.new } shared_examples 'different match methods' do |method| it "autocorrects #{method} /abc\\z/" do new_source = autocorrect_source("str#{method} /abc\\z/") expect(new_source).to eq "str.end_with?('abc')" end it "autocorrects #{method} /\\n\\z/" do new_source = autocorrect_source("str#{method} /\\n\\z/") expect(new_source).to eq 'str.end_with?("\n")' end it "autocorrects #{method} /\\t\\z/" do new_source = autocorrect_source("str#{method} /\\t\\z/") expect(new_source).to eq 'str.end_with?("\t")' end %w[. $ ^ |].each do |str| it "autocorrects #{method} /\\#{str}\\z/" do new_source = autocorrect_source("str#{method} /\\#{str}\\z/") expect(new_source).to eq "str.end_with?('#{str}')" end it "doesn't register an error for #{method} /#{str}\\z/" do inspect_source("str#{method} /#{str}\\z/") expect(cop.messages.empty?).to be(true) end end # escapes like "\n" # note that "\b" is a literal backspace char in a double-quoted string... # but in a regex, it's an anchor on a word boundary %w[a e f r t v].each do |str| it "autocorrects #{method} /\\#{str}\\z/" do new_source = autocorrect_source("str#{method} /\\#{str}\\z/") expect(new_source).to eq %{str.end_with?("\\#{str}")} end end # character classes, anchors %w[w W s S d D A Z z G b B h H R X S].each do |str| it "doesn't register an error for #{method} /\\#{str}\\z/" do inspect_source("str#{method} /\\#{str}\\z/") expect(cop.messages.empty?).to be(true) end end # characters with no special meaning whatsoever %w[i j l m o q y].each do |str| it "autocorrects #{method} /\\#{str}\\z/" do new_source = autocorrect_source("str#{method} /\\#{str}\\z/") expect(new_source).to eq "str.end_with?('#{str}')" end end it "formats the error message correctly for #{method} /abc\\z/" do inspect_source("str#{method} /abc\\z/") expect(cop.messages).to eq(['Use `String#end_with?` instead of a ' \ 'regex match anchored to the end of ' \ 'the string.']) end it "autocorrects #{method} /\\\\\\z/" do new_source = autocorrect_source("str#{method} /\\\\\\z/") expect(new_source).to eq("str.end_with?('\\\\')") end end include_examples('different match methods', ' =~') include_examples('different match methods', '.match') it 'allows match without a receiver' do expect_no_offenses('expect(subject.spin).to match(/\n\z/)') end end rubocop-0.52.1/spec/rubocop/cop/performance/fixed_size_spec.rb000066400000000000000000000154331322072016200244260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::FixedSize do subject(:cop) { described_class.new } let(:message) do 'Do not compute the size of statically sized objects.' end shared_examples :common_functionality do |method| context 'strings' do it "registers an offense when calling #{method} on a single quoted " \ 'string' do inspect_source("'a'.#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on a double quoted " \ 'string' do inspect_source("\"a\".#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on a %q string" do inspect_source("%q(a).#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on a %Q string" do inspect_source("%Q(a).#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on a % string" do inspect_source("%(a).#{method}") expect(cop.messages).to eq([message]) end it "accepts calling #{method} on a double quoted string that " \ 'contains interpolation' do inspect_source("\"\#{foo}\".#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a %Q string that contains " \ 'interpolation' do inspect_source("\%Q(\#{foo}).#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a % string that contains " \ 'interpolation' do inspect_source("\%(\#{foo}).#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a single quoted string that " \ 'is assigned to a constant' do inspect_source("CONST = 'a'.#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a double quoted string that " \ 'is assigned to a constant' do inspect_source("CONST = \"a\".#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a %q string that is assigned to " \ 'a constant' do inspect_source("CONST = %q(a).#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a variable " do inspect_source(<<-RUBY.strip_indent) foo = "abc" foo.#{method} RUBY expect(cop.messages.empty?).to be(true) end end context 'symbols' do it "registers an offense when calling #{method} on a symbol" do inspect_source(":foo.#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on a quoted symbol" do inspect_source(":'foo-bar'.#{method}") expect(cop.messages).to eq([message]) end it "accepts calling #{method} on an interpolated quoted symbol" do inspect_source(":\"foo-\#{bar}\".#{method}") expect(cop.messages.empty?).to be(true) end it "registers an offense when calling #{method} on %s" do inspect_source("%s(foo-bar).#{method}") expect(cop.messages).to eq([message]) end it "accepts calling #{method} on a symbol that is assigned " \ 'to a constant' do inspect_source("CONST = :foo.#{method}") expect(cop.messages.empty?).to be(true) end end context 'arrays' do it "registers an offense when calling #{method} on an array using []" do inspect_source("[1, 2, foo].#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on an array using %w" do inspect_source("%w(1, 2, foo).#{method}") expect(cop.messages).to eq([message]) end it "registers an offense when calling #{method} on an array using %W" do inspect_source("%W(1, 2, foo).#{method}") expect(cop.messages).to eq([message]) end it "accepts calling #{method} on an array using [] that contains " \ 'a splat' do inspect_source("[1, 2, *foo].#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on array that is set to a variable" do inspect_source(<<-RUBY.strip_indent) foo = [1, 2, 3] foo.#{method} RUBY expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on an array that is assigned " \ 'to a constant' do inspect_source("CONST = [1, 2, 3].#{method}") expect(cop.messages.empty?).to be(true) end end context 'hashes' do it "registers an offense when calling #{method} on a hash using {}" do inspect_source("{a: 1, b: 2}.#{method}") expect(cop.messages).to eq([message]) end it "accepts calling #{method} on a hash set to a variable" do inspect_source(<<-RUBY.strip_indent) foo = {a: 1, b: 2} foo.#{method} RUBY expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on a hash that contains a double splat" do inspect_source("{a: 1, **foo}.#{method}") expect(cop.messages.empty?).to be(true) end it "accepts calling #{method} on an hash that is assigned " \ 'to a constant' do inspect_source("CONST = {a: 1, b: 2}.#{method}") expect(cop.messages.empty?).to be(true) end end end it_behaves_like :common_functionality, 'size' it_behaves_like :common_functionality, 'length' it_behaves_like :common_functionality, 'count' shared_examples :count_with_arguments do |variable| it 'accepts calling count with a variable' do inspect_source("#{variable}.count(bar)") expect(cop.messages.empty?).to be(true) end it 'accepts calling count with an instance variable' do inspect_source("#{variable}.count(@bar)") expect(cop.messages.empty?).to be(true) end it 'registers an offense when calling count with a string' do inspect_source("#{variable}.count('o')") expect(cop.messages).to eq([message]) end it 'accepts calling count with a block' do inspect_source("#{variable}.count { |v| v == 'a' }") expect(cop.messages.empty?).to be(true) end it 'accepts calling count with a symbol proc' do inspect_source("#{variable}.count(&:any?) ") expect(cop.messages.empty?).to be(true) end end it_behaves_like :count_with_arguments, '"foo"' it_behaves_like :count_with_arguments, '[1, 2, 3]' it_behaves_like :count_with_arguments, '{a: 1, b: 2}' end rubocop-0.52.1/spec/rubocop/cop/performance/flat_map_spec.rb000066400000000000000000000076231322072016200240620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::FlatMap, :config do subject(:cop) { described_class.new(config) } shared_examples 'map_and_collect' do |method, flatten| it "registers an offense when calling #{method}...#{flatten}(1)" do inspect_source("[1, 2, 3, 4].#{method} { |e| [e, e] }.#{flatten}(1)") expect(cop.messages) .to eq(["Use `flat_map` instead of `#{method}...#{flatten}`."]) expect(cop.highlights).to eq(["#{method} { |e| [e, e] }.#{flatten}(1)"]) end it "does not register an offense when calling #{method}...#{flatten} " \ 'with a number greater than 1' do inspect_source("[1, 2, 3, 4].#{method} { |e| [e, e] }.#{flatten}(3)") expect(cop.messages.empty?).to be(true) end it "does not register an offense when calling #{method}!...#{flatten}" do inspect_source("[1, 2, 3, 4].#{method}! { |e| [e, e] }.#{flatten}") expect(cop.messages.empty?).to be(true) end it "corrects #{method}..#{flatten}(1) to flat_map" do source = "[1, 2].#{method} { |e| [e, e] }.#{flatten}(1)" new_source = autocorrect_source(source) expect(new_source).to eq('[1, 2].flat_map { |e| [e, e] }') end end describe 'configured to only warn when flattening one level' do let(:config) do RuboCop::Config.new('Performance/FlatMap' => { 'Enabled' => true, 'EnabledForFlattenWithoutParams' => false }) end shared_examples 'flatten_with_params_disabled' do |method, flatten| it "does not register an offense when calling #{method}...#{flatten}" do inspect_source("[1, 2, 3, 4].map { |e| [e, e] }.#{flatten}") expect(cop.messages.empty?).to be(true) end end it_behaves_like('map_and_collect', 'map', 'flatten') it_behaves_like('map_and_collect', 'map', 'flatten!') it_behaves_like('map_and_collect', 'collect', 'flatten') it_behaves_like('map_and_collect', 'collect', 'flatten!') it_behaves_like('flatten_with_params_disabled', 'map', 'flatten') it_behaves_like('flatten_with_params_disabled', 'collect', 'flatten') it_behaves_like('flatten_with_params_disabled', 'map', 'flatten!') it_behaves_like('flatten_with_params_disabled', 'collect', 'flatten!') end describe 'configured to warn when flatten is not called with parameters' do let(:config) do RuboCop::Config.new('Performance/FlatMap' => { 'Enabled' => true, 'EnabledForFlattenWithoutParams' => true }) end shared_examples 'flatten_with_params_enabled' do |method, flatten| it "registers an offense when calling #{method}...#{flatten}" do inspect_source("[1, 2, 3, 4].map { |e| [e, e] }.#{flatten}") expect(cop.messages) .to eq(["Use `flat_map` instead of `map...#{flatten}`. " \ 'Beware, `flat_map` only flattens 1 level and `flatten` ' \ 'can be used to flatten multiple levels.']) expect(cop.highlights).to eq(["map { |e| [e, e] }.#{flatten}"]) end it "will not correct #{method}..#{flatten} to flat_map" do source = "[1, 2].map { |e| [e, e] }.#{flatten}" new_source = autocorrect_source(source) expect(new_source).to eq("[1, 2].map { |e| [e, e] }.#{flatten}") end end it_behaves_like('map_and_collect', 'map', 'flatten') it_behaves_like('map_and_collect', 'map', 'flatten!') it_behaves_like('map_and_collect', 'collect', 'flatten') it_behaves_like('map_and_collect', 'collect', 'flatten!') it_behaves_like('flatten_with_params_enabled', 'map', 'flatten') it_behaves_like('flatten_with_params_enabled', 'collect', 'flatten') it_behaves_like('flatten_with_params_enabled', 'map', 'flatten!') it_behaves_like('flatten_with_params_enabled', 'collect', 'flatten!') end end rubocop-0.52.1/spec/rubocop/cop/performance/hash_each_methods_spec.rb000066400000000000000000000213571322072016200257250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::HashEachMethods do subject(:cop) { described_class.new } context 'when node matches a plain `#each` ' \ 'with unused key or value' do context 'when receiver is a send' do it 'registers an offense for foo#each with unused value' do expect_offense(<<-RUBY.strip_indent) foo.each { |k, _v| p k } ^^^^ Use `each_key` instead of `each`. RUBY end it 'does not register an offense for foo#each' \ ' if both key/value are used' do expect_no_offenses("foo.each { |k, v| p \"\#{k}_\#{v}\" }") end it 'does not register an offense when #each follows #to_a' do expect_no_offenses('foo.to_a.each { |k, _v| bar(k) }') end it 'does not register an offense when using braces around arguments' do expect_no_offenses('foo.each { |(k, _v)| bar(k) }') end it 'does not register an offense for foo#each ' \ ' if block takes only one arg' do expect_no_offenses('foo.each { |kv| p kv }') end # Regression test. See https://github.com/bbatsov/rubocop/issues/4881 it 'does not register an offense for foo#each ' \ ' without unused arg, but unused arg exists in other method' do expect_no_offenses(<<-RUBY.strip_indent) foo.each { |k, v| p [k, v] } foo.sum { |k, v| v } RUBY end it 'registers an offense for foo#each with unused key' do expect_offense(<<-RUBY.strip_indent) foo.each { |_k, v| p v } ^^^^ Use `each_value` instead of `each`. RUBY end it 'auto-corrects foo#each with unused value argument' \ ' with foo#each_key' do new_source = autocorrect_source('foo.each { |k, _v| p k }') expect(new_source).to eq('foo.each_key { |k| p k }') end # Regression test. See https://github.com/bbatsov/rubocop/pull/4883 it 'auto-corrects foo#each with unused value argument' \ ' with foo#each_key, and the used value name is not `k`' do new_source = autocorrect_source('foo.each { |key, _v| p key }') expect(new_source).to eq('foo.each_key { |key| p key }') end end context 'when receiver is a hash literal' do it 'registers an offense for {}#each with unused value' do expect_offense(<<-RUBY.strip_indent) {}.each { |k, _v| p k } ^^^^ Use `each_key` instead of `each`. RUBY end it 'registers an offense for {}#each with unused key' do expect_offense(<<-RUBY.strip_indent) {}.each { |_k, v| p v } ^^^^ Use `each_value` instead of `each`. RUBY end it 'does not register an offense for {}#each' \ ' if both key/value are used' do expect_no_offenses("{}.each { |k, v| p \"\#{k}_\#{v}\" }") end it 'does not register an offense for {}#each ' \ ' if block takes only one arg' do expect_no_offenses('{}.each { |kv| p kv }') end it 'does not register an offense when #each follows #to_a' do expect_no_offenses('{}.to_a.each { |k, _v| bar(k) }') end it 'does not register an offense when using braces around arguments' do expect_no_offenses('{}.each { |(k, _v)| bar(k) }') end it 'auto-corrects {}#each with unused value argument' \ ' with {}#each_key' do new_source = autocorrect_source('{}.each { |k, _v| p k }') expect(new_source).to eq('{}.each_key { |k| p k }') end it 'auto-corrects {}#each with unused key argument' \ ' with {}#each_value' do new_source = autocorrect_source('{}.each { |_k, v| p v }') expect(new_source).to eq('{}.each_value { |v| p v }') end end context 'when receiver is implicit' do it 'registers an offense for each with unused value' do expect_offense(<<-RUBY.strip_indent) each { |k, _v| p k } ^^^^ Use `each_key` instead of `each`. RUBY end it 'registers an offense for each with unused key' do expect_offense(<<-RUBY.strip_indent) each { |_k, v| p v } ^^^^ Use `each_value` instead of `each`. RUBY end it 'does not register an offense for each' \ ' if both key/value are used' do expect_no_offenses("each { |k, v| p \"\#{k}_\#{v}\" }") end it 'does not register an offense for each ' \ ' if block takes only one arg' do expect_no_offenses('each { |kv| p kv }') end # Regression test. See https://github.com/bbatsov/rubocop/issues/4881 it 'does not register an offense for each ' \ ' without unused arg, but unused arg exists in other method' do expect_no_offenses(<<-RUBY.strip_indent) each { |k, v| p [k, v] } sum { |k, v| v } RUBY end it 'auto-corrects each with unused value argument' \ ' with each_key' do new_source = autocorrect_source('each { |k, _v| p k }') expect(new_source).to eq('each_key { |k| p k }') end it 'auto-corrects each with unused key argument' \ ' with each_value' do new_source = autocorrect_source('each { |_k, v| p v }') expect(new_source).to eq('each_value { |v| p v }') end end end context 'when node matches a keys#each or values#each' do context 'when receiver is a send' do it 'registers an offense for foo#keys.each' do expect_offense(<<-RUBY.strip_indent) foo.keys.each { |k| p k } ^^^^^^^^^ Use `each_key` instead of `keys.each`. RUBY end it 'registers an offense for foo#values.each' do expect_offense(<<-RUBY.strip_indent) foo.values.each { |v| p v } ^^^^^^^^^^^ Use `each_value` instead of `values.each`. RUBY end it 'does not register an offense for foo#each_key' do expect_no_offenses('foo.each_key { |k| p k }') end it 'does not register an offense for Hash#each_value' do expect_no_offenses('foo.each_value { |v| p v }') end it 'auto-corrects foo#keys.each with foo#each_key' do new_source = autocorrect_source('foo.keys.each { |k| p k }') expect(new_source).to eq('foo.each_key { |k| p k }') end it 'auto-corrects foo#values.each with foo#each_value' do new_source = autocorrect_source('foo.values.each { |v| p v }') expect(new_source).to eq('foo.each_value { |v| p v }') end end context 'when receiver is a hash literal' do it 'registers an offense for {}#keys.each' do expect_offense(<<-RUBY.strip_indent) {}.keys.each { |k| p k } ^^^^^^^^^ Use `each_key` instead of `keys.each`. RUBY end it 'registers an offense for {}#values.each' do expect_offense(<<-RUBY.strip_indent) {}.values.each { |v| p v } ^^^^^^^^^^^ Use `each_value` instead of `values.each`. RUBY end it 'does not register an offense for {}#each_key' do expect_no_offenses('{}.each_key { |k| p k }') end it 'does not register an offense for {}#each_value' do expect_no_offenses('{}.each_value { |v| p v }') end it 'auto-corrects {}#keys.each with {}#each_key' do new_source = autocorrect_source('{}.keys.each { |k| p k }') expect(new_source).to eq('{}.each_key { |k| p k }') end it 'auto-corrects {}#values.each with {}#each_value' do new_source = autocorrect_source('{}.values.each { |v| p v }') expect(new_source).to eq('{}.each_value { |v| p v }') end end context 'when receiver is implicit' do it 'registers an offense for keys.each' do expect_offense(<<-RUBY.strip_indent) keys.each { |k| p k } ^^^^^^^^^ Use `each_key` instead of `keys.each`. RUBY end it 'registers an offense for values.each' do expect_offense(<<-RUBY.strip_indent) values.each { |v| p v } ^^^^^^^^^^^ Use `each_value` instead of `values.each`. RUBY end it 'does not register an offense for each_key' do expect_no_offenses('each_key { |k| p k }') end it 'does not register an offense for each_value' do expect_no_offenses('each_value { |v| p v }') end it 'auto-corrects keys.each with each_key' do new_source = autocorrect_source('keys.each { |k| p k }') expect(new_source).to eq('each_key { |k| p k }') end it 'auto-corrects values.each with each_value' do new_source = autocorrect_source('values.each { |v| p v }') expect(new_source).to eq('each_value { |v| p v }') end end end end rubocop-0.52.1/spec/rubocop/cop/performance/lstrip_rstrip_spec.rb000066400000000000000000000011761322072016200252140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::LstripRstrip do subject(:cop) { described_class.new } it 'autocorrects str.lstrip.rstrip' do new_source = autocorrect_source('str.lstrip.rstrip') expect(new_source).to eq 'str.strip' end it 'autocorrects str.rstrip.lstrip' do new_source = autocorrect_source('str.rstrip.lstrip') expect(new_source).to eq 'str.strip' end it 'formats the error message correctly for str.lstrip.rstrip' do expect_offense(<<-RUBY.strip_indent) str.lstrip.rstrip ^^^^^^^^^^^^^ Use `strip` instead of `lstrip.rstrip`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/range_include_spec.rb000066400000000000000000000017701322072016200250730ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::RangeInclude do subject(:cop) { described_class.new } it 'autocorrects (a..b).include? without parens' do new_source = autocorrect_source('(a..b).include? 1') expect(new_source).to eq '(a..b).cover? 1' end it 'autocorrects (a...b).include? without parens' do new_source = autocorrect_source('(a...b).include? 1') expect(new_source).to eq '(a...b).cover? 1' end it 'autocorrects (a..b).include? with parens' do new_source = autocorrect_source('(a..b).include?(1)') expect(new_source).to eq '(a..b).cover?(1)' end it 'autocorrects (a...b).include? with parens' do new_source = autocorrect_source('(a...b).include?(1)') expect(new_source).to eq '(a...b).cover?(1)' end it 'formats the error message correctly for (a..b).include? 1' do expect_offense(<<-RUBY.strip_indent) (a..b).include? 1 ^^^^^^^^ Use `Range#cover?` instead of `Range#include?`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/redundant_block_call_spec.rb000066400000000000000000000100171322072016200264170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::RedundantBlockCall do subject(:cop) { described_class.new } it 'autocorrects block.call without arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&block) block.call end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) yield end RUBY end it 'autocorrects block.call with empty parentheses' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&block) block.call() end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) yield end RUBY end it 'autocorrects block.call with arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&block) block.call 1, 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) yield 1, 2 end RUBY end it 'autocorrects multiple occurrences of block.call with arguments' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&block) block.call 1 block.call 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) yield 1 yield 2 end RUBY end it 'autocorrects even when block arg has a different name' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&func) func.call end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&func) yield end RUBY end it 'accepts a block that is not `call`ed' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) something.call end RUBY end it 'accepts an empty method body' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) end RUBY end it 'accepts another block being passed as the only arg' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) block.call(&some_proc) end RUBY end it 'accepts another block being passed along with other args' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) block.call(1, &some_proc) end RUBY end it 'accepts another block arg in at least one occurrence of block.call' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) block.call(1, &some_proc) block.call(2) end RUBY end it 'accepts an optional block that is defaulted' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) block ||= ->(i) { puts i } block.call(1) end RUBY end it 'accepts an optional block that is overridden' do expect_no_offenses(<<-RUBY.strip_indent) def method(&block) block = ->(i) { puts i } block.call(1) end RUBY end it 'formats the error message for func.call(1) correctly' do expect_offense(<<-RUBY.strip_indent) def method(&func) func.call(1) ^^^^^^^^^^^^ Use `yield` instead of `func.call`. end RUBY end it 'autocorrects using parentheses when block.call uses parentheses' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(&block) block.call(a, b) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) yield(a, b) end RUBY end it 'autocorrects when the result of the call is used in a scope that ' \ 'requires parentheses' do source = <<-RUBY.strip_indent def method(&block) each_with_object({}) do |(key, value), acc| acc.merge!(block.call(key) => rhs[value]) end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) def method(&block) each_with_object({}) do |(key, value), acc| acc.merge!(yield(key) => rhs[value]) end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/redundant_match_spec.rb000066400000000000000000000063101322072016200254270ustar00rootroot00000000000000# frozen_string_literal: true # do_something if str.match(/regex/) # while regex.match('str') # do_something # end # # @good # method(str.match(/regex/)) # return regex.match('str') RSpec.describe RuboCop::Cop::Performance::RedundantMatch do subject(:cop) { described_class.new } it 'autocorrects .match in if condition' do new_source = autocorrect_source('something if str.match(/regex/)') expect(new_source).to eq 'something if str =~ /regex/' end it 'autocorrects .match in unless condition' do new_source = autocorrect_source('something unless str.match(/regex/)') expect(new_source).to eq 'something unless str =~ /regex/' end it 'autocorrects .match in while condition' do new_source = autocorrect_source(<<-RUBY.strip_indent) while str.match(/regex/) do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) while str =~ /regex/ do_something end RUBY end it 'autocorrects .match in until condition' do new_source = autocorrect_source(<<-RUBY.strip_indent) until str.match(/regex/) do_something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until str =~ /regex/ do_something end RUBY end it 'autocorrects .match in method body (but not tail position)' do new_source = autocorrect_source(<<-RUBY.strip_indent) def method(str) str.match(/regex/) true end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def method(str) str =~ /regex/ true end RUBY end it 'does not autocorrect if .match has a string agrgument' do new_source = autocorrect_source('something if str.match("string")') expect(new_source).to eq 'something if str.match("string")' end it 'does not register an error when return value of .match is passed ' \ 'to another method' do inspect_source(<<-RUBY.strip_indent) def method(str) something(str.match(/regex/)) end RUBY expect(cop.messages.empty?).to be(true) end it 'does not register an error when return value of .match is stored in an ' \ 'instance variable' do inspect_source(<<-RUBY.strip_indent) def method(str) @var = str.match(/regex/) true end RUBY expect(cop.messages.empty?).to be(true) end it 'does not register an error when return value of .match is returned from' \ ' surrounding method' do inspect_source(<<-RUBY.strip_indent) def method(str) str.match(/regex/) end RUBY expect(cop.messages.empty?).to be(true) end it 'does not register an offense when match has a block' do expect_no_offenses(<<-RUBY.strip_indent) /regex/.match(str) do |m| something(m) end RUBY end it 'does not register an error when there is no receiver to the match call' do expect_no_offenses('match("bar")') end it 'formats error message correctly for something if str.match(/regex/)' do expect_offense(<<-RUBY.strip_indent) something if str.match(/regex/) ^^^^^^^^^^^^^^^^^^ Use `=~` in places where the `MatchData` returned by `#match` will not be used. RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/redundant_merge_spec.rb000066400000000000000000000157601322072016200254430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::RedundantMerge, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'MaxKeyValuePairs' => 2 } end it 'autocorrects hash.merge!(a: 1)' do new_source = autocorrect_source('hash.merge!(a: 1)') expect(new_source).to eq 'hash[:a] = 1' end it 'autocorrects hash.merge!("abc" => "value")' do new_source = autocorrect_source('hash.merge!("abc" => "value")') expect(new_source).to eq 'hash["abc"] = "value"' end context 'when receiver is a local variable' do it 'autocorrects hash.merge!(a: 1, b: 2)' do new_source = autocorrect_source(<<-RUBY.strip_indent) hash = {} hash.merge!(a: 1, b: 2) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) hash = {} hash[:a] = 1 hash[:b] = 2 RUBY end end context 'when receiver is a method call' do it "doesn't autocorrect hash.merge!(a: 1, b: 2)" do new_source = autocorrect_source('hash.merge!(a: 1, b: 2)') expect(new_source).to eq('hash.merge!(a: 1, b: 2)') end end context 'when receiver is implicit' do it "doesn't autocorrect" do new_source = autocorrect_source('merge!(foo: 1, bar: 2)') expect(new_source).to eq('merge!(foo: 1, bar: 2)') end end context 'when any argument is a double splat' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) foo.merge!(baz: qux, **bar) RUBY end end context 'when internal to each_with_object' do it 'autocorrects when the receiver is the object being built' do source = <<-RUBY.strip_indent foo.each_with_object({}) do |f, hash| hash.merge!(a: 1, b: 2) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object({}) do |f, hash| hash[:a] = 1 hash[:b] = 2 end RUBY end it 'autocorrects when the receiver is the object being built when ' \ 'merge! is the last statement' do source = <<-RUBY.strip_indent foo.each_with_object({}) do |f, hash| some_method hash.merge!(a: 1, b: 2) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object({}) do |f, hash| some_method hash[:a] = 1 hash[:b] = 2 end RUBY end it 'autocorrects when the receiver is the object being built when ' \ 'merge! is not the last statement' do source = <<-RUBY.strip_indent foo.each_with_object({}) do |f, hash| hash.merge!(a: 1, b: 2) why_are_you_doing_this? end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object({}) do |f, hash| hash[:a] = 1 hash[:b] = 2 why_are_you_doing_this? end RUBY end it 'does not register an offense when merge! is being assigned inside ' \ 'each_with_object' do source = <<-RUBY.strip_indent foo.each_with_object({}) do |f, hash| changes = hash.merge!(a: 1, b: 2) why_are_you_doing_this? end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'autocorrects when receiver uses element reference to the object ' \ 'built by each_with_object' do source = <<-RUBY.strip_indent foo.each_with_object(bar) do |f, hash| hash[:a].merge!(b: "") end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object(bar) do |f, hash| hash[:a][:b] = "" end RUBY end it 'autocorrects when receiver uses multiple element references to the ' \ 'object built by each_with_object' do source = <<-RUBY.strip_indent foo.each_with_object(bar) do |f, hash| hash[:a][:b].merge!(c: "") end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object(bar) do |f, hash| hash[:a][:b][:c] = "" end RUBY end it 'autocorrects merge! called on any method on the object built ' \ 'by each_with_object' do source = <<-RUBY.strip_indent foo.each_with_object(bar) do |f, hash| hash.bar.merge!(c: "") end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo.each_with_object(bar) do |f, hash| hash.bar[:c] = "" end RUBY end end %w[if unless while until].each do |kw| context "when there is a modifier #{kw}, and more than 1 pair" do it "autocorrects it to an #{kw} block" do new_source = autocorrect_source( <<-RUBY.strip_indent hash = {} hash.merge!(a: 1, b: 2) #{kw} condition1 && condition2 RUBY ) expect(new_source).to eq(<<-RUBY.strip_indent) hash = {} #{kw} condition1 && condition2 hash[:a] = 1 hash[:b] = 2 end RUBY end context 'when original code was indented' do it 'maintains proper indentation' do new_source = autocorrect_source( <<-RUBY.strip_indent hash = {} begin hash.merge!(a: 1, b: 2) #{kw} condition1 end RUBY ) expect(new_source).to eq(<<-RUBY.strip_indent) hash = {} begin #{kw} condition1 hash[:a] = 1 hash[:b] = 2 end end RUBY end end end end context 'when code is indented, and there is more than 1 pair' do it 'indents the autocorrected code properly' do new_source = autocorrect_source(<<-RUBY.strip_indent) hash = {} begin hash.merge!(a: 1, b: 2) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) hash = {} begin hash[:a] = 1 hash[:b] = 2 end RUBY end end it "doesn't register an error when return value is used" do expect_no_offenses(<<-RUBY.strip_indent) variable = hash.merge!(a: 1) puts variable RUBY end it 'formats the error message correctly for hash.merge!(a: 1)' do expect_offense(<<-RUBY.strip_indent) hash.merge!(a: 1) ^^^^^^^^^^^^^^^^^ Use `hash[:a] = 1` instead of `hash.merge!(a: 1)`. RUBY end context 'with MaxKeyValuePairs of 1' do let(:cop_config) do { 'MaxKeyValuePairs' => 1 } end it "doesn't register errors for multi-value hash merges" do expect_no_offenses(<<-RUBY.strip_indent) hash = {} hash.merge!(a: 1, b: 2) RUBY end end end rubocop-0.52.1/spec/rubocop/cop/performance/redundant_sort_by_spec.rb000066400000000000000000000016071322072016200260200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::RedundantSortBy do subject(:cop) { described_class.new } it 'autocorrects array.sort_by { |x| x }' do new_source = autocorrect_source('array.sort_by { |x| x }') expect(new_source).to eq 'array.sort' end it 'autocorrects array.sort_by { |y| y }' do new_source = autocorrect_source('array.sort_by { |y| y }') expect(new_source).to eq 'array.sort' end it 'autocorrects array.sort_by do |x| x end' do new_source = autocorrect_source(<<-RUBY.strip_indent) array.sort_by do |x| x end RUBY expect(new_source).to eq "array.sort\n" end it 'formats the error message correctly for array.sort_by { |x| x }' do expect_offense(<<-RUBY.strip_indent) array.sort_by { |x| x } ^^^^^^^^^^^^^^^^^ Use `sort` instead of `sort_by { |x| x }`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/regexp_match_spec.rb000066400000000000000000000171571322072016200247500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::RegexpMatch, :config do subject(:cop) { described_class.new(config) } shared_examples :accepts do |name, code| it "accepts usages of #{name}" do inspect_source(code) expect(cop.offenses.empty?).to be(true) end end shared_examples :offense do |name, code, correction| it "registers an offense for #{name}" do inspect_source(code) expect(cop.offenses.size).to eq(1) end it "corrects #{name}" do new_source = autocorrect_source(code) expect(new_source).to eq(correction) end end shared_examples :all_legacy_match_methods do |name, cond, correction| include_examples :offense, "#{name} in if condition", <<-RUBY, <<-RUBY2 if #{cond} do_something end RUBY if #{correction} do_something end RUBY2 include_examples :offense, "#{name} in unless condition", <<-RUBY, <<-RUBY2 unless #{cond} do_something end RUBY unless #{correction} do_something end RUBY2 include_examples :offense, "#{name} in elsif condition", <<-RUBY, <<-RUBY2 if cond do_something elsif #{cond} do_something2 end RUBY if cond do_something elsif #{correction} do_something2 end RUBY2 include_examples :offense, "#{name} in case condition", <<-RUBY, <<-RUBY2 case when #{cond} do_something end RUBY case when #{correction} do_something end RUBY2 include_examples :offense, "#{name} in ternary operator", <<-RUBY, <<-RUBY2 #{cond} ? do_something : do_something2 RUBY #{correction} ? do_something : do_something2 RUBY2 include_examples :offense, "#{name} in method definition", <<-RUBY, <<-RUBY2 def foo if #{cond} do_something end end RUBY def foo if #{correction} do_something end end RUBY2 %w[ $& $' $` $~ $1 $2 $100 $MATCH Regexp.last_match Regexp.last_match(1) ].each do |var| include_examples :accepts, "#{name} in method with `#{var}`", <<-RUBY def foo if #{cond} do_something(#{var}) end end RUBY include_examples :accepts, "#{name} in a class method with `#{var}`", <<-RUBY def self.foo if #{cond} do_something(#{var}) end end RUBY include_examples :accepts, "#{name} in method with `#{var}` in block", <<-RUBY def foo bar do if #{cond} do_something end end puts #{var} end RUBY include_examples :offense, "#{name} in method before `#{var}`", <<-RUBY, <<-RUBY2 def foo do_something(#{var}) if #{cond} do_something2 end end RUBY def foo do_something(#{var}) if #{correction} do_something2 end end RUBY2 include_examples :offense, "#{name} in method" \ ", `#{var}` is in other method", <<-RUBY, <<-RUBY2 def foo if #{cond} do_something2 end end def bar do_something(#{var}) end RUBY def foo if #{correction} do_something2 end end def bar do_something(#{var}) end RUBY2 include_examples :offense, "#{name} in class method" \ ", `#{var}` is in other method", <<-RUBY, <<-RUBY2 def self.foo if #{cond} do_something2 end end def self.bar do_something(#{var}) end RUBY def self.foo if #{correction} do_something2 end end def self.bar do_something(#{var}) end RUBY2 include_examples :offense, "#{name} in class" \ ", `#{var}` is in method", <<-RUBY, <<-RUBY2 class Foo if #{cond} do_something end def foo #{var} end end RUBY class Foo if #{correction} do_something end def foo #{var} end end RUBY2 include_examples :offense, "#{name} in module" \ ", `#{var}` is in method", <<-RUBY, <<-RUBY2 module Foo if #{cond} do_something end def foo #{var} end end RUBY module Foo if #{correction} do_something end def foo #{var} end end RUBY2 include_examples :offense, "#{name}, #{var} reference is overrided", <<-RUBY, <<-RUBY2 if #{cond} do_something #{cond} #{var} end RUBY if #{correction} do_something #{cond} #{var} end RUBY2 end end context 'target ruby version < 2.4', :ruby23 do [ ['match method call in if condition', <<-RUBY], if foo.match(/re/) do_something end RUBY ['match method call in elsif condition', <<-RUBY], if cond do_something elsif foo.match(/re/) do_something2 end RUBY ].each do |name, code| include_examples :accepts, name, code end end context 'target ruby version >= 2.4', :ruby24 do [ ['String#match method call', '"foo".match(re)', '"foo".match?(re)'], ['String#match method call with position', '"foo".match(re, 1)', '"foo".match?(re, 1)'], ['Regexp#match method call', '/re/.match(foo)', '/re/.match?(foo)'], ['Regexp#match method call with position', '/re/.match(foo, 1)', '/re/.match?(foo, 1)'], ['Symbol#match method call', ':foo.match(re)', ':foo.match?(re)'], ['Symbol#match method call with position', ':foo.match(re, 1)', ':foo.match?(re, 1)'], ['match method call for a variable', 'foo.match(/re/)', 'foo.match?(/re/)'], ['match method call for a variable with position', 'foo.match(/re/, 1)', 'foo.match?(/re/, 1)'], ['matching by =~`', '/re/ =~ foo', '/re/.match?(foo)'], ['matching by =~`', 'foo =~ /re/', 'foo.match?(/re/)'], ['matching by =~`', '"foo" =~ re', '"foo".match?(re)'], ['matching by =~`', ':foo =~ re', ':foo.match?(re)'], ['matching by ===`', '/re/ === foo', '/re/.match?(foo)'], ['matching by ===`', '/re/i === foo', '/re/i.match?(foo)'] ].each do |name, code, correction| include_examples :all_legacy_match_methods, name, code, correction end include_examples :accepts, '`Regexp#match?` method call', <<-RUBY if /re/.match?(str) do_something end RUBY include_examples :accepts, '`String#match?` method call', <<-RUBY if str.match?(/re/) do_something end RUBY include_examples :accepts, '`match` without arguments', <<-RUBY code if match RUBY include_examples :accepts, '`=~` with assignment', <<-RUBY if /alias_(?.*)/ =~ something do_something end RUBY end end rubocop-0.52.1/spec/rubocop/cop/performance/reverse_each_spec.rb000066400000000000000000000015441322072016200247260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::ReverseEach do subject(:cop) { described_class.new } it 'registers an offense when each is called on reverse' do expect_offense(<<-RUBY.strip_indent) [1, 2, 3].reverse.each { |e| puts e } ^^^^^^^^^^^^ Use `reverse_each` instead of `reverse.each`. RUBY end it 'does not register an offense when reverse is used without each' do expect_no_offenses('[1, 2, 3].reverse') end it 'does not register an offense when each is used without reverse' do expect_no_offenses('[1, 2, 3].each { |e| puts e }') end context 'autocorrect' do it 'corrects reverse.each to reverse_each' do new_source = autocorrect_source('[1, 2].reverse.each { |e| puts e }') expect(new_source).to eq('[1, 2].reverse_each { |e| puts e }') end end end rubocop-0.52.1/spec/rubocop/cop/performance/sample_spec.rb000066400000000000000000000056031322072016200235540ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Sample do subject(:cop) { described_class.new } shared_examples 'offense' do |wrong, right| it "when using #{wrong}" do inspect_source("[1, 2, 3].#{wrong}") expect(cop.messages).to eq(["Use `#{right}` instead of `#{wrong}`."]) end context 'corrects' do it "#{wrong} to #{right}" do new_source = autocorrect_source("[1, 2, 3].#{wrong}") expect(new_source).to eq("[1, 2, 3].#{right}") end end end shared_examples 'accepts' do |acceptable| it acceptable do inspect_source("[1, 2, 3].#{acceptable}") expect(cop.messages.empty?).to be(true) end end it_behaves_like('offense', 'shuffle.first', 'sample') it_behaves_like('offense', 'shuffle.last', 'sample') it_behaves_like('offense', 'shuffle[0]', 'sample') it_behaves_like('offense', 'shuffle[0, 3]', 'sample(3)') it_behaves_like('offense', 'shuffle[0..3]', 'sample(4)') it_behaves_like('offense', 'shuffle[0...3]', 'sample(3)') it_behaves_like('offense', 'shuffle.first(2)', 'sample(2)') it_behaves_like('offense', 'shuffle.last(3)', 'sample(3)') it_behaves_like('offense', 'shuffle.first(foo)', 'sample(foo)') it_behaves_like('offense', 'shuffle.last(bar)', 'sample(bar)') it_behaves_like('offense', 'shuffle(random: Random.new).first', 'sample(random: Random.new)') it_behaves_like('offense', 'shuffle(random: Random.new).first(2)', 'sample(2, random: Random.new)') it_behaves_like('offense', 'shuffle(random: foo).last(bar)', 'sample(bar, random: foo)') it_behaves_like('offense', 'shuffle(random: Random.new)[0..3]', 'sample(4, random: Random.new)') it_behaves_like('accepts', 'sample') it_behaves_like('accepts', 'shuffle') it_behaves_like('accepts', 'shuffle[2]') # nil if coll.size < 3 it_behaves_like('accepts', 'shuffle[3, 3]') # nil if coll.size < 3 it_behaves_like('accepts', 'shuffle[2..3]') # empty if coll.size < 3 it_behaves_like('accepts', 'shuffle[2..-3]') # can't compute range size it_behaves_like('accepts', 'shuffle[foo..3]') # can't compute range size it_behaves_like('accepts', 'shuffle[-4..-3]') # nil if coll.size < 3 it_behaves_like('accepts', 'shuffle[foo]') # foo could be a Range it_behaves_like('accepts', 'shuffle[foo, 3]') # nil if coll.size < foo it_behaves_like('accepts', 'shuffle[foo..bar]') it_behaves_like('accepts', 'shuffle[foo, bar]') it_behaves_like('accepts', 'shuffle(random: Random.new)') it_behaves_like('accepts', 'shuffle.join([5, 6, 7])') it_behaves_like('accepts', 'shuffle.map { |e| e }') it_behaves_like('accepts', 'shuffle(random: Random.new)[2]') it_behaves_like('accepts', 'shuffle(random: Random.new)[2, 3]') it_behaves_like('accepts', 'shuffle(random: Random.new).find(&:odd?)') end rubocop-0.52.1/spec/rubocop/cop/performance/size_spec.rb000066400000000000000000000101651322072016200232440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::Size do subject(:cop) { described_class.new } it 'does not register an offense when calling count ' \ 'as a stand alone method' do inspect_source('count(items)') expect(cop.messages.empty?).to be(true) end it 'does not register an offense when calling count on an object ' \ 'other than an array or a hash' do inspect_source('object.count(items)') expect(cop.messages.empty?).to be(true) end describe 'on array' do it 'registers an offense when calling count' do expect_offense(<<-RUBY.strip_indent) [1, 2, 3].count ^^^^^ Use `size` instead of `count`. RUBY end it 'registers an offense when calling count on to_a' do expect_offense(<<-RUBY.strip_indent) (1..3).to_a.count ^^^^^ Use `size` instead of `count`. RUBY end it 'registers an offense when calling count on Array[]' do expect_offense(<<-RUBY.strip_indent) Array[*1..5].count ^^^^^ Use `size` instead of `count`. RUBY end it 'does not register an offense when calling size' do expect_no_offenses('[1, 2, 3].size') end it 'does not register an offense when calling another method' do expect_no_offenses('[1, 2, 3].each') end it 'does not register an offense when calling count with a block' do expect_no_offenses('[1, 2, 3].count { |e| e > 3 }') end it 'does not register an offense when calling count with a to_proc block' do expect_no_offenses('[1, 2, 3].count(&:nil?)') end it 'does not register an offense when calling count with an argument' do expect_no_offenses('[1, 2, 3].count(1)') end it 'corrects count to size' do new_source = autocorrect_source('[1, 2, 3].count') expect(new_source).to eq('[1, 2, 3].size') end it 'corrects count to size on to_a' do new_source = autocorrect_source('(1..3).to_a.count') expect(new_source).to eq('(1..3).to_a.size') end it 'corrects count to size on Array[]' do new_source = autocorrect_source('Array[*1..5].count') expect(new_source).to eq('Array[*1..5].size') end end describe 'on hash' do it 'registers an offense when calling count' do expect_offense(<<-RUBY.strip_indent) {a: 1, b: 2, c: 3}.count ^^^^^ Use `size` instead of `count`. RUBY end it 'registers an offense when calling count on to_h' do expect_offense(<<-RUBY.strip_indent) [[:foo, :bar], [1, 2]].to_h.count ^^^^^ Use `size` instead of `count`. RUBY end it 'registers an offense when calling count on Hash[]' do expect_offense(<<-RUBY.strip_indent) Hash[*('a'..'z')].count ^^^^^ Use `size` instead of `count`. RUBY end it 'does not register an offense when calling size' do expect_no_offenses('{a: 1, b: 2, c: 3}.size') end it 'does not register an offense when calling another method' do expect_no_offenses('{a: 1, b: 2, c: 3}.each') end it 'does not register an offense when calling count with a block' do expect_no_offenses('{a: 1, b: 2, c: 3}.count { |e| e > 3 }') end it 'does not register an offense when calling count with a to_proc block' do expect_no_offenses('{a: 1, b: 2, c: 3}.count(&:nil?)') end it 'does not register an offense when calling count with an argument' do expect_no_offenses('{a: 1, b: 2, c: 3}.count(1)') end it 'corrects count to size' do new_source = autocorrect_source('{a: 1, b: 2, c: 3}.count') expect(new_source).to eq('{a: 1, b: 2, c: 3}.size') end it 'corrects count to size on to_h' do new_source = autocorrect_source('[[:foo, :bar], [1, 2]].to_h.count') expect(new_source).to eq('[[:foo, :bar], [1, 2]].to_h.size') end it 'corrects count to size on Hash[]' do new_source = autocorrect_source("Hash[*('a'..'z')].count") expect(new_source).to eq("Hash[*('a'..'z')].size") end end end rubocop-0.52.1/spec/rubocop/cop/performance/start_with_spec.rb000066400000000000000000000047011322072016200244610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::StartWith do subject(:cop) { described_class.new } shared_examples 'different match methods' do |method| it "autocorrects #{method} /\\Aabc/" do new_source = autocorrect_source("str#{method} /\\Aabc/") expect(new_source).to eq "str.start_with?('abc')" end # escapes like "\n" # note that "\b" is a literal backspace char in a double-quoted string... # but in a regex, it's an anchor on a word boundary %w[a e f r t v].each do |str| it "autocorrects #{method} /\\A\\#{str}/" do new_source = autocorrect_source("str#{method} /\\A\\#{str}/") expect(new_source).to eq %{str.start_with?("\\#{str}")} end end # regexp metacharacters %w[. * ? $ ^ |].each do |str| it "autocorrects #{method} /\\A\\#{str}/" do new_source = autocorrect_source("str#{method} /\\A\\#{str}/") expect(new_source).to eq "str.start_with?('#{str}')" end it "doesn't register an error for #{method} /\\A#{str}/" do inspect_source("str#{method} /\\A#{str}/") expect(cop.messages.empty?).to be(true) end end # character classes, anchors %w[w W s S d D A Z z G b B h H R X S].each do |str| it "doesn't register an error for #{method} /\\A\\#{str}/" do inspect_source("str#{method} /\\A\\#{str}/") expect(cop.messages.empty?).to be(true) end end # characters with no special meaning whatsoever %w[i j l m o q y].each do |str| it "autocorrects #{method} /\\A\\#{str}/" do new_source = autocorrect_source("str#{method} /\\A\\#{str}/") expect(new_source).to eq "str.start_with?('#{str}')" end end it "formats the error message correctly for #{method} /\\Aabc/" do inspect_source("str#{method} /\\Aabc/") expect(cop.messages).to eq(['Use `String#start_with?` instead of a ' \ 'regex match anchored to the beginning of ' \ 'the string.']) end it "autocorrects #{method} /\\A\\\\/" do new_source = autocorrect_source("str#{method} /\\A\\\\/") expect(new_source).to eq("str.start_with?('\\\\')") end end include_examples('different match methods', ' =~') include_examples('different match methods', '.match') it 'allows match without a receiver' do expect_no_offenses('expect(subject.spin).to match(/\A\n/)') end end rubocop-0.52.1/spec/rubocop/cop/performance/string_replacement_spec.rb000066400000000000000000000306611322072016200261620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::StringReplacement do subject(:cop) { described_class.new } it 'accepts methods other than gsub' do expect_no_offenses("'abc'.insert(2, 'a')") end shared_examples 'accepts' do |method| context 'non deterministic parameters' do it 'accepts gsub when the length of the pattern is greater than 1' do inspect_source("'abc'.#{method}('ab', 'de')") expect(cop.messages.empty?).to be(true) end it 'accepts the first param being a variable' do inspect_source(<<-RUBY.strip_indent) regex = /a/ 'abc'.#{method}(regex, '1') RUBY expect(cop.messages.empty?).to be(true) end it 'accepts the second param being a variable' do inspect_source(<<-RUBY.strip_indent) replacement = 'e' 'abc'.#{method}('abc', replacement) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts the both params being a variables' do inspect_source(<<-RUBY.strip_indent) regex = /a/ replacement = 'e' 'abc'.#{method}(regex, replacement) RUBY expect(cop.messages.empty?).to be(true) end it 'accepts gsub with only one param' do inspect_source("'abc'.#{method}('a')") expect(cop.messages.empty?).to be(true) end it 'accepts gsub with a block' do inspect_source("'abc'.#{method}('a') { |s| s.upcase } ") expect(cop.messages.empty?).to be(true) end it 'accepts a pattern with string interpolation' do inspect_source(<<-RUBY.strip_indent) foo = 'a' 'abc'.#{method}(\"\#{foo}\", '1') RUBY expect(cop.messages.empty?).to be(true) end it 'accepts a replacement with string interpolation' do inspect_source(<<-RUBY.strip_indent) foo = '1' 'abc'.#{method}('a', \"\#{foo}\") RUBY expect(cop.messages.empty?).to be(true) end it 'allows empty regex literal pattern' do inspect_source("'abc'.#{method}(//, '1')") expect(cop.messages.empty?).to be(true) end it 'allows empty regex pattern from string' do inspect_source("'abc'.#{method}(Regexp.new(''), '1')") expect(cop.messages.empty?).to be(true) end it 'allows empty regex pattern from regex' do inspect_source("'abc'.#{method}(Regexp.new(//), '1')") expect(cop.messages.empty?).to be(true) end it 'allows regex literals with options' do inspect_source("'abc'.#{method}(/a/i, '1')") expect(cop.messages.empty?).to be(true) end it 'allows regex with options' do inspect_source("'abc'.#{method}(Regexp.new(/a/i), '1')") expect(cop.messages.empty?).to be(true) end it 'allows empty string pattern' do inspect_source("'abc'.#{method}('', '1')") expect(cop.messages.empty?).to be(true) end end it 'accepts calls to gsub when the length of the pattern is shorter than ' \ 'the length of the replacement' do inspect_source("'abc'.#{method}('a', 'ab')") expect(cop.messages.empty?).to be(true) end it 'accepts calls to gsub when the length of the pattern is longer than ' \ 'the length of the replacement' do inspect_source("'abc'.#{method}('ab', 'd')") expect(cop.messages.empty?).to be(true) end end it_behaves_like('accepts', 'gsub') it_behaves_like('accepts', 'gsub!') describe 'deterministic regex' do describe 'regex literal' do it 'registers an offense when using space' do expect_offense(<<-RUBY.strip_indent) 'abc'.gsub(/ /, '') ^^^^^^^^^^^^^ Use `delete` instead of `gsub`. RUBY end %w[a b c ' " % ! = < > # & ; : ` ~ 1 2 3 - _ , \r \\\\ \y \u1234 \x65].each do |str| it "registers an offense when replacing #{str} with a literal" do inspect_source("'abc'.gsub(/#{str}/, 'a')") expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) end it "registers an offense when deleting #{str}" do inspect_source("'abc'.gsub(/#{str}/, '')") expect(cop.messages).to eq(['Use `delete` instead of `gsub`.']) end end it 'allows deterministic regex when the length of the pattern ' \ 'and the length of the replacement do not match' do inspect_source(%('abc'.gsub(/a/, 'def'))) expect(cop.messages.empty?).to be(true) end it 'registers an offense when escape characters in regex' do inspect_source(%('abc'.gsub(/\n/, ','))) expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) end it 'registers an offense when using %r notation' do expect_offense(<<-RUBY.strip_indent) '/abc'.gsub(%r{a}, 'd') ^^^^^^^^^^^^^^^^ Use `tr` instead of `gsub`. RUBY end end describe 'regex constructor' do it 'registers an offense when only using word characters' do expect_offense(<<-RUBY.strip_indent) 'abc'.gsub(Regexp.new('b'), '2') ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `tr` instead of `gsub`. RUBY end it 'registers an offense when regex is built from regex' do expect_offense(<<-RUBY.strip_indent) 'abc'.gsub(Regexp.new(/b/), '2') ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `tr` instead of `gsub`. RUBY end it 'registers an offense when using compile' do expect_offense(<<-RUBY.strip_indent) '123'.gsub(Regexp.compile('1'), 'a') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `tr` instead of `gsub`. RUBY end end end describe 'non deterministic regex' do it 'allows regex containing a +' do expect_no_offenses("'abc'.gsub(/a+/, 'def')") end it 'allows regex containing a *' do expect_no_offenses("'abc'.gsub(/a*/, 'def')") end it 'allows regex containing a ^' do expect_no_offenses("'abc'.gsub(/^/, '')") end it 'allows regex containing a $' do expect_no_offenses("'abc'.gsub(/$/, '')") end it 'allows regex containing a ?' do expect_no_offenses("'abc'.gsub(/a?/, 'def')") end it 'allows regex containing a .' do expect_no_offenses("'abc'.gsub(/./, 'a')") end it 'allows regex containing a |' do expect_no_offenses("'abc'.gsub(/a|b/, 'd')") end it 'allows regex containing ()' do expect_no_offenses("'abc'.gsub(/(ab)/, 'd')") end it 'allows regex containing escaped ()' do expect_no_offenses("'(abc)'.gsub(/(ab)/, 'd')") end it 'allows regex containing {}' do expect_no_offenses("'abc'.gsub(/a{3,}/, 'd')") end it 'allows regex containing []' do expect_no_offenses("'abc'.gsub(/[a-z]/, 'd')") end it 'allows regex containing a backslash' do expect_no_offenses('"abc".gsub(/\\s/, "d")') end it 'allows regex literal containing interpolations' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = 'a' "abc".gsub(/#{foo}/, "d") RUBY end it 'allows regex constructor containing a string with interpolations' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = 'a' "abc".gsub(Regexp.new("#{foo}"), "d") RUBY end it 'allows regex constructor containing regex with interpolations' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = 'a' "abc".gsub(Regexp.new(/#{foo}/), "d") RUBY end end it 'registers an offense when the pattern has non deterministic regex ' \ 'as a string' do inspect_source(%('a + c'.gsub('+', '-'))) expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) end it 'registers an offense when using gsub to find and replace ' \ 'a single character' do inspect_source("'abc'.gsub('a', '1')") expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) expect(cop.highlights).to eq(["gsub('a', '1')"]) end it 'registers an offense when using gsub! to find and replace ' \ 'a single character ' do inspect_source("'abc'.gsub!('a', '1')") expect(cop.messages).to eq(['Use `tr!` instead of `gsub!`.']) expect(cop.highlights).to eq(["gsub!('a', '1')"]) end it 'registers an offense for gsub! when deleting one characters' do expect_offense(<<-RUBY.strip_indent) 'abc'.gsub!('a', '') ^^^^^^^^^^^^^^ Use `delete!` instead of `gsub!`. RUBY end it 'registers an offense when using escape characters in the replacement' do inspect_source("'abc'.gsub('a', '\n')") expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) end it 'registers an offense when using escape characters in the pattern' do inspect_source("'abc'.gsub('\n', ',')") expect(cop.messages).to eq(['Use `tr` instead of `gsub`.']) end context 'auto-correct' do describe 'corrects to tr' do it 'corrects when the length of the pattern and replacement are one' do new_source = autocorrect_source("'abc'.gsub('a', 'd')") expect(new_source).to eq("'abc'.tr('a', 'd')") end it 'corrects when the pattern is a regex literal' do new_source = autocorrect_source("'abc'.gsub(/a/, '1')") expect(new_source).to eq("'abc'.tr('a', '1')") end it 'corrects when the pattern is a regex literal using %r' do new_source = autocorrect_source("'abc'.gsub(%r{a}, '1')") expect(new_source).to eq("'abc'.tr('a', '1')") end it 'corrects when the pattern uses Regexp.new' do new_source = autocorrect_source("'abc'.gsub(Regexp.new('a'), '1')") expect(new_source).to eq("'abc'.tr('a', '1')") end it 'corrects when the pattern uses Regexp.compile' do new_source = autocorrect_source("'abc'.gsub(Regexp.compile('a'), '1')") expect(new_source).to eq("'abc'.tr('a', '1')") end it 'corrects when the replacement contains a new line character' do new_source = autocorrect_source("'abc'.gsub('a', '\n')") expect(new_source).to eq("'abc'.tr('a', '\n')") end it 'corrects when the replacement contains escape backslash' do new_source = autocorrect_source("\"\".gsub('/', '\\\\')") expect(new_source).to eq("\"\".tr('/', '\\\\')") end it 'corrects when the pattern contains a new line character' do new_source = autocorrect_source("'abc'.gsub('\n', ',')") expect(new_source).to eq("'abc'.tr('\n', ',')") end it 'corrects when the pattern contains double backslash' do new_source = autocorrect_source("''.gsub('\\\\', '')") expect(new_source).to eq("''.delete('\\\\')") end it 'corrects when replacing to a single quote' do new_source = autocorrect_source('"a`b".gsub("`", "\'")') expect(new_source).to eq('"a`b".tr("`", "\'")') end it 'corrects when replacing to a double quote' do new_source = autocorrect_source('"a`b".gsub("`", "\"")') expect(new_source).to eq('"a`b".tr("`", "\"")') end end describe 'corrects to delete' do it 'corrects when deleting a single character' do new_source = autocorrect_source("'abc'.gsub!('a', '')") expect(new_source).to eq("'abc'.delete!('a')") end it 'corrects when the pattern is a regex literal' do new_source = autocorrect_source("'abc'.gsub(/a/, '')") expect(new_source).to eq("'abc'.delete('a')") end it 'corrects when deleting an escape character' do new_source = autocorrect_source("'abc'.gsub('\n', '')") expect(new_source).to eq("'abc'.delete('\n')") end it 'corrects when the pattern uses Regexp.new' do new_source = autocorrect_source("'abc'.gsub(Regexp.new('a'), '')") expect(new_source).to eq("'abc'.delete('a')") end it 'corrects when the pattern uses Regexp.compile' do new_source = autocorrect_source("'ab'.gsub(Regexp.compile('a'), '')") expect(new_source).to eq("'ab'.delete('a')") end it 'corrects when there are no brackets' do new_source = autocorrect_source("'abc'.gsub! 'a', ''") expect(new_source).to eq("'abc'.delete! 'a'") end it 'corrects when a regexp contains escapes' do new_source = autocorrect_source("'abc'.gsub(/\\n/, '')") expect(new_source).to eq(%('abc'.delete("\\n"))) end end end end rubocop-0.52.1/spec/rubocop/cop/performance/times_map_spec.rb000066400000000000000000000045541322072016200242550ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::TimesMap do subject(:cop) { described_class.new } before do inspect_source(source) end shared_examples 'map_or_collect' do |method| context ".times.#{method}" do context 'with a block' do let(:source) { "4.times.#{method} { |i| i.to_s }" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( "Use `Array.new(4)` with a block instead of `.times.#{method}`." ) expect(cop.highlights).to eq(["4.times.#{method} { |i| i.to_s }"]) end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq('Array.new(4) { |i| i.to_s }') end end context 'for non-literal receiver' do let(:source) { "n.times.#{method} { |i| i.to_s }" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( "Use `Array.new(n)` with a block instead of `.times.#{method}` " \ 'only if `n` is always 0 or more.' ) expect(cop.highlights).to eq(["n.times.#{method} { |i| i.to_s }"]) end end context 'with an explicitly passed block' do let(:source) { "4.times.#{method}(&method(:foo))" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq( "Use `Array.new(4)` with a block instead of `.times.#{method}`." ) expect(cop.highlights).to eq(["4.times.#{method}(&method(:foo))"]) end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq('Array.new(4, &method(:foo))') end end context 'without a block' do let(:source) { "4.times.#{method}" } it "doesn't register an offense" do expect(cop.offenses.empty?).to be(true) end end context 'called on nothing' do let(:source) { "times.#{method} { |i| i.to_s }" } it "doesn't register an offense" do expect(cop.offenses.empty?).to be(true) end end end end it_behaves_like 'map_or_collect', 'map' it_behaves_like 'map_or_collect', 'collect' end rubocop-0.52.1/spec/rubocop/cop/performance/unfreeze_string_spec.rb000066400000000000000000000043021322072016200254770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Performance::UnfreezeString, :config do subject(:cop) { described_class.new(config) } context 'TargetRubyVersion >= 2.3', :ruby23 do it 'registers an offense for an empty string with `.dup`' do expect_offense(<<-RUBY.strip_indent) "".dup ^^^^^^ Use unary plus to get an unfrozen string literal. RUBY end it 'registers an offense for a string with `.dup`' do expect_offense(<<-RUBY.strip_indent) "foo".dup ^^^^^^^^^ Use unary plus to get an unfrozen string literal. RUBY end it 'registers an offense for a heredoc with `.dup`' do expect_offense(<<-RUBY.strip_indent) < nil } } context 'when using action methods' do described_class::FILTER_METHODS.each do |method| it "does not register an offense for #{method}" do inspect_source_file("#{method} :name") expect(cop.offenses.size).to eq(0) end it "does not register an offense for #{method} with block" do inspect_source_file("#{method} { |controller| something }") expect(cop.offenses.size).to eq(0) end end described_class::ACTION_METHODS.each do |method| it "accepts #{method}" do inspect_source_file("#{method} :something") expect(cop.offenses.empty?).to be(true) end end it 'does not auto-correct to preferred method' do new_source = autocorrect_source_file('before_filter :test') expect(new_source).to eq('before_filter :test') end end context 'when using filter methods' do described_class::ACTION_METHODS.each do |method| it "does not register an offense for #{method}" do inspect_source_file("#{method} :name") expect(cop.offenses.size).to eq(0) end it "does not register an offense for #{method} with block" do inspect_source_file("#{method} { |controller| something }") expect(cop.offenses.size).to eq(0) end end described_class::FILTER_METHODS.each do |method| it "accepts #{method}" do inspect_source_file("#{method} :something") expect(cop.offenses.empty?).to be(true) end end it 'does not auto-correct to preferred method' do new_source = autocorrect_source_file('before_action :test') expect(new_source).to eq('before_action :test') end end end context 'Rails >= 4.0', :rails4 do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Include' => nil } } context 'when style is action' do before do cop_config['EnforcedStyle'] = 'action' end described_class::FILTER_METHODS.each do |method| it "registers an offense for #{method}" do inspect_source_file("#{method} :name") expect(cop.offenses.size).to eq(1) end it "registers an offense for #{method} with block" do inspect_source_file("#{method} { |controller| something }") expect(cop.offenses.size).to eq(1) end end described_class::ACTION_METHODS.each do |method| it "accepts #{method}" do inspect_source_file("#{method} :something") expect(cop.offenses.empty?).to be(true) end end it 'auto-corrects to preferred method' do new_source = autocorrect_source_file('before_filter :test') expect(new_source).to eq('before_action :test') end end context 'when style is filter' do before do cop_config['EnforcedStyle'] = 'filter' end described_class::ACTION_METHODS.each do |method| it "registers an offense for #{method}" do inspect_source_file("#{method} :name") expect(cop.offenses.size).to eq(1) end it "registers an offense for #{method} with block" do inspect_source_file("#{method} { |controller| something }") expect(cop.offenses.size).to eq(1) end end described_class::FILTER_METHODS.each do |method| it "accepts #{method}" do inspect_source_file("#{method} :something") expect(cop.offenses.empty?).to be(true) end end it 'auto-corrects to preferred method' do new_source = autocorrect_source_file('before_action :test') expect(new_source).to eq('before_filter :test') end end end end rubocop-0.52.1/spec/rubocop/cop/rails/active_support_aliases_spec.rb000066400000000000000000000052461322072016200256570ustar00rootroot00000000000000# frozen_string_literal: true require 'spec_helper' RSpec.describe RuboCop::Cop::Rails::ActiveSupportAliases do subject(:cop) { described_class.new } describe 'String' do describe '#starts_with?' do it 'is registered as an offence' do expect_offense(<<-RUBY.strip_indent) 'some_string'.starts_with?('prefix') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `start_with?` instead of `starts_with?`. RUBY end it 'is autocorrected' do new_source = autocorrect_source( "'some_string'.starts_with?('prefix')" ) expect(new_source).to eq "'some_string'.start_with?('prefix')" end end describe '#start_with?' do it 'is not registered as an offense' do expect_no_offenses("'some_string'.start_with?('prefix')") end end describe '#ends_with?' do it 'is registered as an offense' do expect_offense(<<-RUBY.strip_indent) 'some_string'.ends_with?('prefix') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `end_with?` instead of `ends_with?`. RUBY end it 'is autocorrected' do new_source = autocorrect_source( "'some_string'.ends_with?('prefix')" ) expect(new_source).to eq "'some_string'.end_with?('prefix')" end end describe '#end_with?' do it 'is not registered as an offense' do expect_no_offenses("'some_string'.end_with?('prefix')") end end end describe 'Array' do describe '#append' do it 'is registered as an offence' do expect_offense(<<-RUBY.strip_indent) [1, 'a', 3].append('element') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `<<` instead of `append`. RUBY end it 'is not autocorrected' do source = "[1, 'a', 3].append('element')" new_source = autocorrect_source(source) expect(new_source).to eq source end end describe '#<<' do it 'is not registered as an offense' do expect_no_offenses("[1, 'a', 3] << 'element'") end end describe '#prepend' do it 'is registered as an offence' do expect_offense(<<-RUBY.strip_indent) [1, 'a', 3].prepend('element') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `unshift` instead of `prepend`. RUBY end it 'is autocorrected' do new_source = autocorrect_source( "[1, 'a', 3].prepend('element')" ) expect(new_source).to eq "[1, 'a', 3].unshift('element')" end end describe '#unshift' do it 'is not registered as an offense' do expect_no_offenses("[1, 'a', 3].unshift('element')") end end end end rubocop-0.52.1/spec/rubocop/cop/rails/application_job_spec.rb000066400000000000000000000104521322072016200242370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::ApplicationJob do let(:msgs) { ['Jobs should subclass `ApplicationJob`.'] } context 'rails 4', :rails4, :config do subject(:cop) { described_class.new(config) } it 'allows ApplicationJob to be defined' do expect_no_offenses(<<-RUBY.strip_indent) class ApplicationJob < ActiveJob::Base end RUBY end it 'allows jobs that subclass ActiveJob::Base' do expect_no_offenses(<<-RUBY.strip_indent) class MyJob < ActiveJob::Base end RUBY end it 'allows a single-line class definitions' do expect_no_offenses('class MyJob < ActiveJob::Base; end') end it 'allows namespaced jobs that subclass ActiveJob::Base' do expect_no_offenses(<<-RUBY.strip_indent) module Nested class MyJob < ActiveJob::Base end end RUBY end it 'allows jobs defined using nested constants' do expect_no_offenses(<<-RUBY.strip_indent) class Nested::MyJob < ActiveJob::Base end RUBY end it 'allows jobs defined using Class.new' do expect_no_offenses('MyJob = Class.new(ActiveJob::Base)') end it 'allows nested jobs defined using Class.new' do expect_no_offenses('Nested::MyJob = Class.new(ActiveJob::Base)') end it 'allows anonymous jobs' do expect_no_offenses('Class.new(ActiveJob::Base) {}') end it 'allows ApplicationJob defined using Class.new' do expect_no_offenses('ApplicationJob = Class.new(ActiveJob::Base)') end end context 'rails 5', :rails5 do subject(:cop) { described_class.new } it 'allows ApplicationJob to be defined' do expect_no_offenses(<<-RUBY.strip_indent) class ApplicationJob < ActiveJob::Base end RUBY end it 'corrects jobs that subclass ActiveJob::Base' do source = "class MyJob < ActiveJob::Base\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq("class MyJob < ApplicationJob\nend") end it 'corrects single-line class definitions' do source = 'class MyJob < ActiveJob::Base; end' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq('class MyJob < ApplicationJob; end') end it 'corrects namespaced jobs that subclass ActiveJob::Base' do source = "module Nested\n class MyJob < ActiveJob::Base\n end\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq("module Nested\n class MyJob < ApplicationJob\n end\nend") end it 'corrects jobs defined using nested constants' do source = "class Nested::MyJob < ActiveJob::Base\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq("class Nested::MyJob < ApplicationJob\nend") end it 'corrects jobs defined using Class.new' do source = 'MyJob = Class.new(ActiveJob::Base)' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq('MyJob = Class.new(ApplicationJob)') end it 'corrects nested jobs defined using Class.new' do source = 'Nested::MyJob = Class.new(ActiveJob::Base)' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq('Nested::MyJob = Class.new(ApplicationJob)') end it 'corrects anonymous jobs' do source = 'Class.new(ActiveJob::Base) {}' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveJob::Base']) expect(autocorrect_source(source)) .to eq('Class.new(ApplicationJob) {}') end it 'allows ApplicationJob defined using Class.new' do expect_no_offenses('ApplicationJob = Class.new(ActiveJob::Base)') end end end rubocop-0.52.1/spec/rubocop/cop/rails/application_record_spec.rb000066400000000000000000000107621322072016200247470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::ApplicationRecord do let(:msgs) { ['Models should subclass `ApplicationRecord`.'] } context 'rails 4', :rails4, :config do subject(:cop) { described_class.new(config) } it 'allows ApplicationRecord to be defined' do expect_no_offenses(<<-RUBY.strip_indent) class ApplicationRecord < ActiveRecord::Base end RUBY end it 'allows models that subclass ActiveRecord::Base' do expect_no_offenses(<<-RUBY.strip_indent) class MyModel < ActiveRecord::Base end RUBY end it 'allows a single-line class definitions' do expect_no_offenses('class MyModel < ActiveRecord::Base; end') end it 'allows namespaced models that subclass ActiveRecord::Base' do expect_no_offenses(<<-RUBY.strip_indent) module Nested class MyModel < ActiveRecord::Base end end RUBY end it 'allows models defined using nested constants' do expect_no_offenses(<<-RUBY.strip_indent) class Nested::MyModel < ActiveRecord::Base end RUBY end it 'allows models defined using Class.new' do expect_no_offenses('MyModel = Class.new(ActiveRecord::Base)') end it 'allows nested models defined using Class.new' do expect_no_offenses('Nested::MyModel = Class.new(ActiveRecord::Base)') end it 'allows anonymous models' do expect_no_offenses('Class.new(ActiveRecord::Base) {}') end it 'allows ApplicationRecord defined using Class.new' do expect_no_offenses('ApplicationRecord = Class.new(ActiveRecord::Base)') end end context 'rails 5', :rails5 do subject(:cop) { described_class.new } it 'allows ApplicationRecord to be defined' do expect_no_offenses(<<-RUBY.strip_indent) class ApplicationRecord < ActiveRecord::Base end RUBY end it 'corrects models that subclass ActiveRecord::Base' do source = "class MyModel < ActiveRecord::Base\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq("class MyModel < ApplicationRecord\nend") end it 'corrects single-line class definitions' do source = 'class MyModel < ActiveRecord::Base; end' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq('class MyModel < ApplicationRecord; end') end it 'corrects namespaced models that subclass ActiveRecord::Base' do source = "module Nested\n class MyModel < ActiveRecord::Base\n end\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq("module Nested\n class MyModel < ApplicationRecord\n end\nend") end it 'corrects models defined using nested constants' do source = "class Nested::MyModel < ActiveRecord::Base\nend" inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq("class Nested::MyModel < ApplicationRecord\nend") end it 'corrects models defined using Class.new' do source = 'MyModel = Class.new(ActiveRecord::Base)' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq('MyModel = Class.new(ApplicationRecord)') end it 'corrects nested models defined using Class.new' do source = 'Nested::MyModel = Class.new(ActiveRecord::Base)' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq('Nested::MyModel = Class.new(ApplicationRecord)') end it 'corrects anonymous models' do source = 'Class.new(ActiveRecord::Base) {}' inspect_source(source) expect(cop.messages).to eq(msgs) expect(cop.highlights).to eq(['ActiveRecord::Base']) expect(autocorrect_source(source)) .to eq('Class.new(ApplicationRecord) {}') end it 'allows ApplicationRecord defined using Class.new' do expect_no_offenses('ApplicationRecord = Class.new(ActiveRecord::Base)') end end end rubocop-0.52.1/spec/rubocop/cop/rails/blank_spec.rb000066400000000000000000000222151322072016200221710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Blank, :config do subject(:cop) { described_class.new(config) } shared_examples :offense do |source, correction, message| it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq([message]) expect(cop.highlights).to eq([source]) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(correction) end end context 'NilOrEmpty set to true' do let(:cop_config) do { 'NilOrEmpty' => true } end it 'accepts checking nil?' do expect_no_offenses('foo.nil?') end it 'accepts checking empty?' do expect_no_offenses('foo.empty?') end it 'accepts checking nil? || empty? on different objects' do expect_no_offenses('foo.nil? || bar.empty?') end # Bug: https://github.com/bbatsov/rubocop/issues/4171 it 'does not break when RHS of `or` is a naked falsiness check' do expect_no_offenses('foo.empty? || bar') end it 'does not break when LHS of `or` is a naked falsiness check' do expect_no_offenses('bar || foo.empty?') end # Bug: https://github.com/bbatsov/rubocop/issues/4814 it 'does not break when LHS of `or` is a send node with an arugment' do expect_no_offenses('x(1) || something') end context 'nil or empty' do it_behaves_like :offense, 'foo.nil? || foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of `foo.nil? || foo.empty?`.' it_behaves_like :offense, 'nil? || empty?', 'blank?', 'Use `blank?` instead of `nil? || empty?`.' it_behaves_like :offense, 'foo == nil || foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of `foo == nil || foo.empty?`.' it_behaves_like :offense, 'nil == foo || foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of `nil == foo || foo.empty?`.' it_behaves_like :offense, '!foo || foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of `!foo || foo.empty?`.' it_behaves_like :offense, 'foo.nil? || !!foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of `foo.nil? || !!foo.empty?`.' it_behaves_like :offense, 'foo == nil || !!foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of ' \ '`foo == nil || !!foo.empty?`.' it_behaves_like :offense, 'nil == foo || !!foo.empty?', 'foo.blank?', 'Use `foo.blank?` instead of ' \ '`nil == foo || !!foo.empty?`.' end context 'checking all variable types' do it_behaves_like :offense, 'foo.bar.nil? || foo.bar.empty?', 'foo.bar.blank?', 'Use `foo.bar.blank?` instead of ' \ '`foo.bar.nil? || foo.bar.empty?`.' it_behaves_like :offense, 'FOO.nil? || FOO.empty?', 'FOO.blank?', 'Use `FOO.blank?` instead of `FOO.nil? || FOO.empty?`.' it_behaves_like :offense, 'Foo.nil? || Foo.empty?', 'Foo.blank?', 'Use `Foo.blank?` instead of `Foo.nil? || Foo.empty?`.' it_behaves_like :offense, 'Foo::Bar.nil? || Foo::Bar.empty?', 'Foo::Bar.blank?', 'Use `Foo::Bar.blank?` instead of ' \ '`Foo::Bar.nil? || Foo::Bar.empty?`.' it_behaves_like :offense, '@foo.nil? || @foo.empty?', '@foo.blank?', 'Use `@foo.blank?` instead of `@foo.nil? || @foo.empty?`.' it_behaves_like :offense, '$foo.nil? || $foo.empty?', '$foo.blank?', 'Use `$foo.blank?` instead of `$foo.nil? || $foo.empty?`.' it_behaves_like :offense, '@@foo.nil? || @@foo.empty?', '@@foo.blank?', 'Use `@@foo.blank?` instead of ' \ '`@@foo.nil? || @@foo.empty?`.' it_behaves_like :offense, 'foo[bar].nil? || foo[bar].empty?', 'foo[bar].blank?', 'Use `foo[bar].blank?` instead of ' \ '`foo[bar].nil? || foo[bar].empty?`.' it_behaves_like :offense, 'foo(bar).nil? || foo(bar).empty?', 'foo(bar).blank?', 'Use `foo(bar).blank?` instead of ' \ '`foo(bar).nil? || foo(bar).empty?`.' end end context 'NotPresent set to true' do let(:cop_config) do { 'NotPresent' => true } end it_behaves_like :offense, '!foo.present?', 'foo.blank?', 'Use `foo.blank?` instead of `!foo.present?`.' it_behaves_like :offense, 'not foo.present?', 'foo.blank?', 'Use `foo.blank?` instead of `not foo.present?`.' it_behaves_like :offense, '!present?', 'blank?', 'Use `blank?` instead of `!present?`.' end context 'UnlessPresent set to true' do let(:cop_config) do { 'UnlessPresent' => true } end it 'accepts modifier if present?' do expect_no_offenses('something if foo.present?') end it 'accepts modifier unless blank?' do expect_no_offenses('something unless foo.blank?') end it 'accepts normal if present?' do expect_no_offenses(<<-RUBY.strip_indent) if foo.present? something end RUBY end it 'accepts normal unless blank?' do expect_no_offenses(<<-RUBY.strip_indent) unless foo.blank? something end RUBY end it 'accepts elsif present?' do expect_no_offenses(<<-RUBY.strip_indent) if bar.present? something elsif bar.present? something_else end RUBY end context 'modifier unless' do context 'with a receiver' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) something unless foo.present? ^^^^^^^^^^^^^^^^^^^ Use `if foo.blank?` instead of `unless foo.present?`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('something unless foo.present?') expect(new_source).to eq('something if foo.blank?') end end context 'without a receiver' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) something unless present? ^^^^^^^^^^^^^^^ Use `if blank?` instead of `unless present?`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('something unless present?') expect(new_source).to eq('something if blank?') end end end context 'normal unless present?' do let(:source) do <<-RUBY.strip_indent unless foo.present? something end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless foo.present? ^^^^^^^^^^^^^^^^^^^ Use `if foo.blank?` instead of `unless foo.present?`. something end RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo.blank? something end RUBY end end context 'unless present? with an else' do let(:source) do <<-RUBY.strip_indent unless foo.present? something else something_else end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless foo.present? ^^^^^^^^^^^^^^^^^^^ Use `if foo.blank?` instead of `unless foo.present?`. something else something_else end RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo.blank? something else something_else end RUBY end end end context 'NilOrEmpty set to false' do let(:cop_config) do { 'NilOrEmpty' => false, 'NotPresent' => true, 'UnlessPresent' => true } end it 'accepts checking nil? || empty?' do expect_no_offenses('foo.nil? || foo.empty?') end end context 'NotPresent set to false' do let(:cop_config) do { 'NilOrEmpty' => true, 'NotPresent' => false, 'UnlessPresent' => true } end it 'accepts !present?' do expect_no_offenses('!foo.present?') end end context 'UnlessPresent set to false' do let(:cop_config) do { 'NilOrEmpty' => true, 'NotPresent' => true, 'UnlessPresent' => false } end it 'accepts unless present?' do expect_no_offenses('something unless foo.present?') end end end rubocop-0.52.1/spec/rubocop/cop/rails/create_table_with_timestamps_spec.rb000066400000000000000000000036741322072016200270250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::CreateTableWithTimestamps do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when calling `#create_table` without block' do expect_offense <<-RUBY create_table :users ^^^^^^^^^^^^^^^^^^^ Add timestamps when creating a new table. RUBY end it 'registers an offense when not including timestamps in empty block' do expect_offense <<-RUBY create_table :users do |t| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Add timestamps when creating a new table. end RUBY end it 'registers an offense when not including timestamps in one line block' do expect_offense <<-RUBY create_table :users do |t| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Add timestamps when creating a new table. t.string :name end RUBY end it 'registers an offense when not including timestamps in multiline block' do expect_offense <<-RUBY create_table :users do |t| ^^^^^^^^^^^^^^^^^^^^^^^^^^ Add timestamps when creating a new table. t.string :name t.string :email end RUBY end it 'does not register an offense when including timestamps in block' do expect_no_offenses <<-RUBY create_table :users do |t| t.string :name t.string :email t.timestamps end RUBY end it 'does not register an offense when including created_at in block' do expect_no_offenses <<-RUBY create_table :users do |t| t.string :name t.string :email t.datetime :created_at, default: -> { 'CURRENT_TIMESTAMP' } end RUBY end it 'does not register an offense when including updated_at in block' do expect_no_offenses <<-RUBY create_table :users do |t| t.string :name t.string :email t.datetime :updated_at, default: -> { 'CURRENT_TIMESTAMP' } end RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/date_spec.rb000066400000000000000000000064521322072016200220240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Date, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is "strict"' do let(:cop_config) { { 'EnforcedStyle' => 'strict' } } %w[today current yesterday tomorrow].each do |day| it "registers an offense for Date.#{day}" do inspect_source("Date.#{day}") expect(cop.offenses.size).to eq(1) end it "registers an offense for ::Date.#{day}" do inspect_source("::Date.#{day}") expect(cop.offenses.size).to eq(1) end it "accepts Some::Date.#{day}" do inspect_source("Some::Date.#{day}") expect(cop.offenses.empty?).to be(true) end end %w[to_time to_time_in_current_zone].each do |method| it "registers an offense for ##{method}" do inspect_source("date.#{method}") expect(cop.offenses.size).to eq(1) end it "accepts variable named #{method}" do inspect_source("#{method} = 1") expect(cop.offenses.empty?).to be(true) end it "accepts variable #{method} as range end" do inspect_source("from_time..#{method}") expect(cop.offenses.empty?).to be(true) end end context 'when a zone is provided' do it 'does not register an offense' do expect_no_offenses('date.to_time(:utc)') end end context 'when a string literal with timezone' do it 'does not register an offense' do expect_no_offenses('"2016-07-12 14:36:31 +0100".to_time(:utc)') end end context 'when a string literal without timezone' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) "2016-07-12 14:36:31".to_time(:utc) ^^^^^^^ Do not use `to_time` on Date objects, because they know nothing about the time zone in use. RUBY end end context 'when a string literal with "Z"-style UTC timezone' do it 'does not register an offense' do expect_no_offenses('"2017-09-22T22:46:06.497Z".to_time(:utc)') end end it 'does not blow up in the presence of a single constant to inspect' do expect_no_offenses('A') end RuboCop::Cop::Rails::TimeZone::ACCEPTED_METHODS.each do |a_method| it "registers an offense for val.to_time.#{a_method}" do inspect_source("val.to_time.#{a_method}") expect(cop.offenses.size).to eq(1) end end end context 'when EnforcedStyle is "flexible"' do let(:cop_config) { { 'EnforcedStyle' => 'flexible' } } %w[current yesterday tomorrow].each do |day| it "accepts Date.#{day}" do inspect_source("Date.#{day}") expect(cop.offenses.empty?).to be(true) end end it 'registers an offense for Date.today' do expect_offense(<<-RUBY.strip_indent) Date.today ^^^^^ Do not use `Date.today` without zone. Use `Time.zone.today` instead. RUBY end RuboCop::Cop::Rails::TimeZone::ACCEPTED_METHODS.each do |a_method| it "accepts val.to_time.#{a_method}" do inspect_source("val.to_time.#{a_method}") expect(cop.offenses.empty?).to be(true) end end it 'accepts #to_time_in_current_zone' do expect_no_offenses('date.to_time_in_current_zone') end end end rubocop-0.52.1/spec/rubocop/cop/rails/delegate_allow_blank_spec.rb000066400000000000000000000015251322072016200252220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::DelegateAllowBlank do subject(:cop) { described_class.new } it 'registers an offense when using allow_blank' do inspect_source('delegate :foo, to: :bar, allow_blank: true') msg = '`allow_blank` is not a valid option, use `allow_nil`.' expect(cop.messages).to eq([msg]) end it 'does not register an offense when using allow_nil' do expect_no_offenses('delegate :foo, to: :bar, allow_nil: true') end it 'does not register an offense when no extra options given' do expect_no_offenses('delegate :foo, to: :bar') end it 'autocorrects allow_blank to allow_nil' do source = 'delegate :foo, to: :bar, allow_blank: true' new_source = autocorrect_source(source) expect(new_source).to eq('delegate :foo, to: :bar, allow_nil: true') end end rubocop-0.52.1/spec/rubocop/cop/rails/delegate_spec.rb000066400000000000000000000111221322072016200226470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Delegate do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforceForPrefixed' => true } } let(:config) do merged = RuboCop::ConfigLoader .default_configuration['Rails/Delegate'].merge(cop_config) RuboCop::Config.new('Rails/Delegate' => merged) end it 'finds trivial delegate' do expect_offense(<<-RUBY.strip_indent) def foo ^^^ Use `delegate` to define delegations. bar.foo end RUBY end it 'finds trivial delegate with arguments' do expect_offense(<<-RUBY.strip_indent) def foo(baz) ^^^ Use `delegate` to define delegations. bar.foo(baz) end RUBY end it 'finds trivial delegate with prefix' do expect_offense(<<-RUBY.strip_indent) def bar_foo ^^^ Use `delegate` to define delegations. bar.foo end RUBY end it 'ignores class methods' do expect_no_offenses(<<-RUBY.strip_indent) def self.fox new.fox end RUBY end it 'ignores non trivial delegate' do expect_no_offenses(<<-RUBY.strip_indent) def fox bar.foo.fox end RUBY end it 'ignores trivial delegate with mismatched arguments' do expect_no_offenses(<<-RUBY.strip_indent) def fox(baz) bar.fox(foo) end RUBY end it 'ignores trivial delegate with optional argument with a default value' do expect_no_offenses(<<-RUBY.strip_indent) def fox(foo = nil) bar.fox(foo || 5) end RUBY end it 'ignores trivial delegate with mismatched number of arguments' do expect_no_offenses(<<-RUBY.strip_indent) def fox(a, baz) bar.fox(a) end RUBY end it 'ignores trivial delegate with other prefix' do expect_no_offenses(<<-RUBY.strip_indent) def fox_foo bar.foo end RUBY end it 'ignores methods with arguments' do expect_no_offenses(<<-RUBY.strip_indent) def fox(bar) bar.fox end RUBY end it 'ignores private delegations' do expect_no_offenses(<<-RUBY.strip_indent) private def fox # leading spaces are on purpose bar.fox end private def fox bar.fox end RUBY end it 'ignores protected delegations' do expect_no_offenses(<<-RUBY.strip_indent) protected def fox # leading spaces are on purpose bar.fox end protected def fox bar.fox end RUBY end it 'ignores delegation with assignment' do expect_no_offenses(<<-RUBY.strip_indent) def new @bar = Foo.new end RUBY end it 'ignores delegation to constant' do expect_no_offenses(<<-RUBY.strip_indent) FOO = [] def size FOO.size end RUBY end it 'ignores code with no receiver' do expect_no_offenses(<<-RUBY.strip_indent) def change add_column :images, :size, :integer end RUBY end context 'with EnforceForPrefixed: false' do let(:cop_config) do { 'EnforceForPrefixed' => false } end it 'ignores trivial delegate with prefix' do expect_no_offenses(<<-RUBY.strip_indent) def bar_foo bar.foo end RUBY end end context 'Ruby 2.3', :ruby23 do it 'ignores trivial delegate with safe navigation' do expect_no_offenses(<<-RUBY.strip_indent) def foo bar&.foo end RUBY end end describe '#autocorrect' do context 'trivial delegation' do let(:source) do <<-RUBY.strip_indent def bar foo.bar end RUBY end let(:corrected_source) do <<-RUBY.strip_indent delegate :bar, to: :foo RUBY end it 'autocorrects' do expect(autocorrect_source(source)).to eq(corrected_source) end end context 'trivial delegation with prefix' do let(:source) do <<-RUBY.strip_indent def foo_bar foo.bar end RUBY end let(:corrected_source) do <<-RUBY.strip_indent delegate :bar, to: :foo, prefix: true RUBY end it 'autocorrects' do expect(autocorrect_source(source)).to eq(corrected_source) end context 'with EnforceForPrefixed: false' do let(:cop_config) do { 'EnforceForPrefixed' => false } end it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) end end end end end rubocop-0.52.1/spec/rubocop/cop/rails/dynamic_find_by_spec.rb000066400000000000000000000074071322072016200242260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::DynamicFindBy, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Whitelist' => %w[find_by_sql] } end shared_examples 'register an offense and auto correct' do |message, corrected| it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq([message]) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(corrected) end end context 'with dynamic find_by_*' do let(:source) { 'User.find_by_name(name)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name`.', 'User.find_by(name: name)' ) end context 'with dynamic find_by_*_and_*' do let(:source) { 'User.find_by_name_and_email(name, email)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name_and_email`.', 'User.find_by(name: name, email: email)' ) end context 'with dynamic find_by_*!' do let(:source) { 'User.find_by_name!(name)' } include_examples( 'register an offense and auto correct', 'Use `find_by!` instead of dynamic `find_by_name!`.', 'User.find_by!(name: name)' ) end context 'with dynamic find_by_*_and_*_and_*' do let(:source) { 'User.find_by_name_and_email_and_token(name, email, token)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name_and_email_and_token`.', 'User.find_by(name: name, email: email, token: token)' ) end context 'with dynamic find_by_*_and_*_and_*!' do let(:source) do 'User.find_by_name_and_email_and_token!(name, email, token)' end include_examples( 'register an offense and auto correct', 'Use `find_by!` instead of dynamic `find_by_name_and_email_and_token!`.', 'User.find_by!(name: name, email: email, token: token)' ) end context 'with dynamic find_by_*_and_*_and_* with newline' do let(:source) do <<-RUBY.strip_indent User.find_by_name_and_email_and_token( name, email, token ) RUBY end include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name_and_email_and_token`.', <<-RUBY.strip_indent User.find_by( name: name, email: email, token: token ) RUBY ) end context 'with column includes undersoce' do let(:source) { 'User.find_by_first_name(name)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_first_name`.', 'User.find_by(first_name: name)' ) end context 'with too much arguments' do let(:source) { 'User.find_by_name_and_email(name, email, token)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name_and_email`.', # Do not correct 'User.find_by_name_and_email(name, email, token)' ) end context 'with too few arguments' do let(:source) { 'User.find_by_name_and_email(name)' } include_examples( 'register an offense and auto correct', 'Use `find_by` instead of dynamic `find_by_name_and_email`.', # Do not correct 'User.find_by_name_and_email(name)' ) end it 'accepts' do expect_no_offenses('User.find_by(name: name)') end it 'accepts method in whitelist' do expect_no_offenses(<<-RUBY.strip_indent) User.find_by_sql(["select * from users where name = ?", name]) RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/enum_uniqueness_spec.rb000066400000000000000000000056251322072016200243330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::EnumUniqueness, :config do subject(:cop) { described_class.new } context 'when array syntax is used' do context 'with a single duplicated enum value' do it 'registers an offense' do inspect_source('enum status: [:active, :archived, :active]') msg = 'Duplicate value `:active` found in `status` enum declaration.' expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([msg]) end end context 'with several duplicated enum values' do it 'registers two offenses' do expect_offense(<<-RUBY.strip_indent) enum status: [:active, :archived, :active, :active] ^^^^^^^ Duplicate value `:active` found in `status` enum declaration. ^^^^^^^ Duplicate value `:active` found in `status` enum declaration. RUBY end end context 'with no duplicated enum values' do it 'does not register an offense for unique enum values' do expect_no_offenses('enum status: [:active, :archived]') end end end context 'when hash syntax is used' do context 'with a single duplicated enum value' do it 'registers an offense' do inspect_source('enum status: { active: 0, archived: 0 }') msg = 'Duplicate value `0` found in `status` enum declaration.' expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([msg]) end end context 'with several duplicated enum values' do it 'registers two offenses' do expect_offense(<<-RUBY.strip_indent) enum status: { active: 0, pending: 0, archived: 0 } ^ Duplicate value `0` found in `status` enum declaration. ^ Duplicate value `0` found in `status` enum declaration. RUBY end end context 'with no duplicated enum values' do it 'does not register an offense' do expect_no_offenses('enum status: { active: 0, pending: 1 }') end end end context 'when receiving a variable' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) var = { status: { active: 0, archived: 1 } } enum var RUBY end end context 'when receiving a hash without literal values' do context 'when value is a variable' do it 'does not register an offense' do expect_no_offenses('enum status: statuses') end end context 'when value is a method chain' do it 'does not register an offense' do expect_no_offenses('enum status: User.statuses.keys') end end context 'when value is a constant' do it 'does not register an offense' do expect_no_offenses('enum status: STATUSES') end end end end rubocop-0.52.1/spec/rubocop/cop/rails/environment_comparison_spec.rb000066400000000000000000000022561322072016200257030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::EnvironmentComparison do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `Rails.env == production`' do expect_offense(<<-RUBY.strip_indent) Rails.env == 'production' ^^^^^^^^^^^^^^^^^^^^^^^^^ Favor `Rails.env.production?` over `Rails.env == 'production'`. Rails.env == :development ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not compare `Rails.env` with a symbol, it will always evaluate to `false`. RUBY end it 'autocorrects a string' do new_source = autocorrect_source(<<-RUBY.strip_indent) Rails.env == 'development' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) Rails.env.development? RUBY end it 'autocorrects a symbol' do new_source = autocorrect_source(<<-RUBY.strip_indent) Rails.env == :test RUBY expect(new_source).to eq(<<-RUBY.strip_indent) Rails.env.test? RUBY end it 'does not register an offense when using `#good_method`' do expect_no_offenses(<<-RUBY.strip_indent) Rails.env.production? Rails.env.test? RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/exit_spec.rb000066400000000000000000000034561322072016200220610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Exit, :config do subject(:cop) { described_class.new } it 'registers an offense for an exit call with no receiver' do expect_offense(<<-RUBY.strip_indent) exit ^^^^ Do not use `exit` in Rails applications. RUBY end it 'registers an offense for an exit! call with no receiver' do expect_offense(<<-RUBY.strip_indent) exit! ^^^^^ Do not use `exit` in Rails applications. RUBY end context 'exit calls on objects' do it 'does not register an offense for an explicit exit call on an object' do expect_no_offenses('Object.new.exit') end it 'does not register an offense for an explicit exit call '\ 'with an argument on an object' do inspect_source('Object.new.exit(0)') expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for an explicit exit! call on an object' do expect_no_offenses('Object.new.exit!(0)') end end context 'with arguments' do it 'registers an offense for an exit(0) call with no receiver' do expect_offense(<<-RUBY.strip_indent) exit(0) ^^^^ Do not use `exit` in Rails applications. RUBY end it 'ignores exit calls with unexpected number of parameters' do expect_no_offenses('exit(1, 2)') end end context 'explicit calls' do it 'does register an offense for explicit Kernel.exit calls' do expect_offense(<<-RUBY.strip_indent) Kernel.exit ^^^^ Do not use `exit` in Rails applications. RUBY end it 'does register an offense for explicit Process.exit calls' do expect_offense(<<-RUBY.strip_indent) Process.exit ^^^^ Do not use `exit` in Rails applications. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/file_path_spec.rb000066400000000000000000000040771322072016200230430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::FilePath do subject(:cop) { described_class.new } context 'when using Rails.root.join with some path strings' do it 'does not registers an offense' do expect_no_offenses("Rails.root.join('app', 'models', 'user.rb')") end end context 'when using File.join with Rails.root' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) File.join(Rails.root, 'app', 'models') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please use `Rails.root.join('path', 'to')` instead. RUBY end end context 'when using Rails.root.join with slash separated path string' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) Rails.root.join('app/models/goober') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please use `Rails.root.join('path', 'to')` instead. RUBY end end context 'when using Rails.root called by double quoted string' do it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) "#{Rails.root}/app/models/goober" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please use `Rails.root.join('path', 'to')` instead. RUBY end end context 'Rails.root is used as a method argument' do it 'registers an offense once' do expect_offense(<<-RUBY.strip_indent) foo(bar(File.join(Rails.root, "app", "models"))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please use `Rails.root.join('path', 'to')` instead. RUBY end end context 'Rails.root.join used as an argument' do it 'registers an offense once' do expect_offense(<<-RUBY.strip_indent) foo(Rails.root.join('app/models')) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Please use `Rails.root.join('path', 'to')` instead. RUBY end end context 'Rails.root.join with a non-string argument including "/"' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) Rails.root.join("tmp", "data", index/3, "data.csv") RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/find_by_spec.rb000066400000000000000000000016311322072016200225130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::FindBy do subject(:cop) { described_class.new } shared_examples 'registers_offense' do |selector| it "when using where.#{selector}" do inspect_source("User.where(id: x).#{selector}") expect(cop.messages) .to eq(["Use `find_by` instead of `where.#{selector}`."]) end end it_behaves_like('registers_offense', 'first') it_behaves_like('registers_offense', 'take') it 'does not register an offense when using find_by' do expect_no_offenses('User.find_by(id: x)') end it 'autocorrects where.take to find_by' do new_source = autocorrect_source('User.where(id: x).take') expect(new_source).to eq('User.find_by(id: x)') end it 'does not autocorrect where.first' do new_source = autocorrect_source('User.where(id: x).first') expect(new_source).to eq('User.where(id: x).first') end end rubocop-0.52.1/spec/rubocop/cop/rails/find_each_spec.rb000066400000000000000000000027501322072016200230040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::FindEach do subject(:cop) { described_class.new } shared_examples 'register_offense' do |scope| it "registers an offense when using #{scope}.each" do inspect_source("User.#{scope}.each { |u| u.something }") expect(cop.messages).to eq(['Use `find_each` instead of `each`.']) end it "does not register an offense when using #{scope}.order(...).each" do inspect_source("User.#{scope}.order(:name).each { |u| u.something }") expect(cop.offenses.empty?).to be(true) end it "does not register an offense when using #{scope}.limit(...).each" do inspect_source("User.#{scope}.limit(10).each { |u| u.something }") expect(cop.offenses.empty?).to be(true) end it "does not register an offense when using #{scope}.select(...).each" do inspect_source("User.#{scope}.select(:name, :age).each " \ '{ |u| u.something }') expect(cop.offenses.empty?).to be(true) end end it_behaves_like('register_offense', 'where(name: name)') it_behaves_like('register_offense', 'all') it_behaves_like('register_offense', 'where.not(name: name)') it 'does not register an offense when using find_by' do expect_no_offenses('User.all.find_each { |u| u.x }') end it 'auto-corrects each to find_each' do new_source = autocorrect_source('User.all.each { |u| u.x }') expect(new_source).to eq('User.all.find_each { |u| u.x }') end end rubocop-0.52.1/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb000066400000000000000000000005671322072016200257440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::HasAndBelongsToMany do subject(:cop) { described_class.new } it 'registers an offense for has_and_belongs_to_many' do expect_offense(<<-RUBY.strip_indent) has_and_belongs_to_many :groups ^^^^^^^^^^^^^^^^^^^^^^^ Prefer `has_many :through` to `has_and_belongs_to_many`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/has_many_or_has_one_dependent_spec.rb000066400000000000000000000100521322072016200271170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::HasManyOrHasOneDependent do subject(:cop) { described_class.new } context 'has_one' do it 'registers an offense when not specifying any options' do expect_offense(<<-RUBY.strip_indent) class Person has_one :foo ^^^^^^^ Specify a `:dependent` option. end RUBY end it 'registers an offense when missing an explicit `:dependent` strategy' do expect_offense(<<-RUBY.strip_indent) class Person has_one :foo, class_name: 'bar' ^^^^^^^ Specify a `:dependent` option. end RUBY end it 'does not register an offense when specifying `:dependent` strategy' do expect_no_offenses(<<-RUBY.strip_indent) class Person has_one :foo, dependent: :destroy end RUBY end context 'with :through option' do it 'does not register an offense for non-nil value' do expect_no_offenses(<<-RUBY.strip_indent) class Person has_one :foo, through: :bar end RUBY end it 'registers an offense for nil value' do expect_offense(<<-RUBY.strip_indent) class Person has_one :foo, through: nil ^^^^^^^ Specify a `:dependent` option. end RUBY end end context 'with_options dependent: :destroy' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options dependent: :destroy do has_one :foo end end RUBY end it 'does not register an offense for using `class_name` option' do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options dependent: :destroy do has_one :foo, class_name: 'Foo' end end RUBY end end end context 'has_many' do it 'registers an offense when not specifying any options' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo ^^^^^^^^ Specify a `:dependent` option. end RUBY end it 'registers an offense when missing an explicit `:dependent` strategy' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo, class_name: 'bar' ^^^^^^^^ Specify a `:dependent` option. end RUBY end it 'does not register an offense when specifying `:dependent` strategy' do expect_no_offenses('has_many :foo, dependent: :bar') end context 'with :through option' do it 'does not register an offense for non-nil value' do expect_no_offenses('has_many :foo, through: :bars') end it 'registers an offense for nil value' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo, through: nil ^^^^^^^^ Specify a `:dependent` option. end RUBY end end context 'Surrounded `with_options` block' do it 'registers an offense when `dependent: :destroy` is not present' do expect_offense(<<-RUBY.strip_indent) class Person with_options through: nil do has_many :foo ^^^^^^^^ Specify a `:dependent` option. end end RUBY end it "doesn't register an offense for `with_options dependent: :destroy`" do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options dependent: :destroy do has_many :foo end end RUBY end context 'Multiple associations' do it "doesn't register an offense for " \ '`with_options dependent: :destroy`' do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options dependent: :destroy do has_many :foo has_many :bar end end RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/rails/http_positional_arguments_spec.rb000066400000000000000000000413221322072016200264070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::HttpPositionalArguments do context 'rails 4', :rails4, :config do subject(:cop) { described_class.new(config) } it 'does not register an offense for post method' do expect_no_offenses('post :create, user_id: @user.id') end it 'does not register an offense for patch method' do expect_no_offenses('patch :update, user_id: @user.id') end it 'does not register an offense for delete method' do expect_no_offenses('delete :destroy, id: @user.id') end it 'accepts for not HTTP method' do expect_no_offenses('puts :create, user_id: @user.id') end describe 'when using process' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) process :new, method: :get, params: { user_id: @user.id } RUBY end end [ 'params: { user_id: @user.id }', 'xhr: true', 'session: { foo: \'bar\' }', 'format: :json' ].each do |keyword_args| describe "when using keyword args #{keyword_args}" do let(:source) do "get :new, #{keyword_args}" end it 'does not register an offense' do inspect_source(source) expect(cop.messages.empty?).to be(true) end end end describe '.get' do let(:source) do 'get :new, user_id: @user.id' end it 'does not register an offense' do expect_no_offenses('get :new, user_id: @user.id') end it 'does not auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end describe 'no params' do it 'does not register an offense' do expect_no_offenses('get :new') end end end describe '.patch' do let(:source) do <<-RUBY.strip_indent patch :update, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) patch :update, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'does not auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end describe '.post' do let(:source) do <<-RUBY.strip_indent post :create, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) post :create, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'does not auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end %w[post get patch put delete].each do |keyword| it 'does not register an offense when keyword' do source = "@user.#{keyword}.id = ''" inspect_source(source) expect(cop.offenses.size).to eq(0) end end it 'does not auto-correct http action when method' do source = 'post user_attrs, id: 1' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct http action when symbol' do source = 'post :user_attrs, id: 1' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct' do source = 'post(:user_attrs, id: 1)' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not register when post is found' do expect_no_offenses(<<-RUBY.strip_indent) if post.stint_title.present? true end RUBY end it 'does not remove quotes when single quoted' do source = "get '/auth/linkedin/callback'" new_source = autocorrect_source(source) expect(new_source).to eq("get '/auth/linkedin/callback'") end it 'does not remove quotes when double quoted' do source = 'get "/auth/linkedin/callback"' new_source = autocorrect_source(source) expect(new_source).to eq('get "/auth/linkedin/callback"') end it 'does not add headers keyword when env or headers are used' do source = 'get some_path(profile.id), {},' source += " 'HTTP_REFERER' => p_url(p.id).to_s" new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not duplicate brackets when hash is already supplied' do source = 'get some_path(profile.id), ' source += '{ user_id: @user.id, profile_id: p.id },' source += " 'HTTP_REFERER' => p_url(p.id).to_s" new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct http action when params is a method call' do source = 'post :create, confirmation_data' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct http action when params and action names ' \ 'are method calls' do source = 'post user_attrs, params' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end # rubocop:disable LineLength it 'does not auto-correct http action when parameter matches keyword name' do source = 'post :create, id: 7, comment: { body: "hei" }' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct http action when format keyword included ' \ 'but not alone' do source = 'post :create, id: 7, format: :rss' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct when params is a lvar' do source = <<-RUBY.strip_indent params = { id: 1 } post user_attrs, params RUBY inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not auto-correct http action when params is a method call ' \ 'with chain' do source = 'post user_attrs, params.merge(foo: bar)' inspect_source(source) expect(cop.offenses.size).to eq(0) new_source = autocorrect_source(source) expect(new_source).to eq(source) end end context 'rails 5 and above', :rails5 do subject(:cop) { described_class.new } it 'registers an offense for post method' do source = 'post :create, user_id: @user.id' inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'registers an offense for patch method' do source = 'patch :update, user_id: @user.id' inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'registers an offense for delete method' do source = 'delete :destroy, id: @user.id' inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'accepts for not HTTP method' do expect_no_offenses('puts :create, user_id: @user.id') end describe 'when using process' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) process :new, method: :get, params: { user_id: @user.id } RUBY end end [ 'params: { user_id: @user.id }', 'xhr: true', 'session: { foo: \'bar\' }', 'format: :json' ].each do |keyword_args| describe "when using keyword args #{keyword_args}" do let(:source) do "get :new, #{keyword_args}" end it 'does not register an offense' do inspect_source(source) expect(cop.messages.empty?).to be(true) end end end describe '.get' do let(:source) do 'get :new, user_id: @user.id' end let(:corrected_result) do 'get :new, params: { user_id: @user.id }' end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) get :new, user_id: @user.id ^^^ Use keyword arguments instead of positional arguments for http call: `get`. RUBY end it 'autocorrects offense' do new_source = autocorrect_source(source) expect(new_source).to eq(corrected_result) end describe 'no params' do it 'does not register an offense' do expect_no_offenses('get :new') end end end describe '.patch' do let(:source) do <<-RUBY.strip_indent patch :update, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end let(:corrected_result) do <<-RUBY.strip_indent patch :update, params: { id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } } RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) patch :update, ^^^^^ Use keyword arguments instead of positional arguments for http call: `patch`. id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'autocorrects offense' do new_source = autocorrect_source(source) expect(new_source).to eq(corrected_result) end end describe '.post' do let(:source) do <<-RUBY.strip_indent post :create, id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end let(:corrected_result) do <<-RUBY.strip_indent post :create, params: { id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } } RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) post :create, ^^^^ Use keyword arguments instead of positional arguments for http call: `post`. id: @user.id, ac: { article_id: @article1.id, profile_id: @profile1.id, content: 'Some Text' } RUBY end it 'autocorrects offense' do new_source = autocorrect_source(source) expect(new_source).to eq(corrected_result) end end %w[post get patch put delete].each do |keyword| it 'does not register an offense when keyword' do source = "@user.#{keyword}.id = ''" inspect_source(source) expect(cop.offenses.size).to eq(0) end end it 'auto-corrects http action when method' do source = 'post user_attrs, id: 1' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expected = 'post user_attrs, params: { id: 1 }' expect(new_source).to eq(expected) end it 'auto-corrects http action when symbol' do source = 'post :user_attrs, id: 1' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expected = 'post :user_attrs, params: { id: 1 }' expect(new_source).to eq(expected) end it 'maintains parentheses in auto-correcting' do source = 'post(:user_attrs, id: 1)' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expected = 'post(:user_attrs, params: { id: 1 })' expect(new_source).to eq(expected) end it 'does not register when post is found' do expect_no_offenses(<<-RUBY.strip_indent) if post.stint_title.present? true end RUBY end it 'does not remove quotes when single quoted' do source = "get '/auth/linkedin/callback'" new_source = autocorrect_source(source) expect(new_source).to eq("get '/auth/linkedin/callback'") end it 'does not remove quotes when double quoted' do source = 'get "/auth/linkedin/callback"' new_source = autocorrect_source(source) expect(new_source).to eq('get "/auth/linkedin/callback"') end it 'does add headers keyword when env or headers are used' do source = 'get some_path(profile.id), {},' source += " 'HTTP_REFERER' => p_url(p.id).to_s" new_source = autocorrect_source(source) output = 'get some_path(profile.id),' output += " headers: { 'HTTP_REFERER' => p_url(p.id).to_s }" expect(new_source).to eq(output) end it 'does not duplicate brackets when hash is already supplied' do source = 'get some_path(profile.id), ' source += '{ user_id: @user.id, profile_id: p.id },' source += " 'HTTP_REFERER' => p_url(p.id).to_s" new_source = autocorrect_source(source) output = 'get some_path(profile.id), params:' output += ' { user_id: @user.id, profile_id: p.id },' output += " headers: { 'HTTP_REFERER' => p_url(p.id).to_s }" expect(new_source).to eq(output) end it 'auto-corrects http action when params is a method call' do source = 'post :create, confirmation_data' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) output = 'post :create, params: confirmation_data' expect(new_source).to eq(output) end it 'auto-corrects http action when parameter matches special keyword name' do source = 'post :create, id: 7, comment: { body: "hei" }' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) output = 'post :create, params: { id: 7, comment: { body: "hei" } }' expect(new_source).to eq(output) end it 'auto-corrects http action when format keyword included but not alone' do source = 'post :create, id: 7, format: :rss' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) output = 'post :create, params: { id: 7, format: :rss }' expect(new_source).to eq(output) end it 'auto-corrects http action when params is a lvar' do source = <<-RUBY.strip_indent params = { id: 1 } post user_attrs, params RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) params = { id: 1 } post user_attrs, params: params RUBY end it 'auto-corrects http action when params and action name are method calls' do source = 'post user_attrs, params' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expected = 'post user_attrs, params: params' expect(new_source).to eq(expected) end it 'auto-corrects http action when params is a method call with chain' do source = 'post user_attrs, params.merge(foo: bar)' inspect_source(source) expect(cop.offenses.size).to eq(1) new_source = autocorrect_source(source) expected = 'post user_attrs, params: params.merge(foo: bar)' expect(new_source).to eq(expected) end end end # rubocop:enable LineLength rubocop-0.52.1/spec/rubocop/cop/rails/inverse_of_spec.rb000066400000000000000000000152121322072016200232400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::InverseOf do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } context 'with scope' do it 'registers an offense when not specifying `:inverse_of`' do expect_offense(<<-RUBY.strip_indent) class Person has_one :foo, -> () { where(bar: true) } ^^^^^^^ Specify an `:inverse_of` option. end RUBY end it 'does not register an offense when specifying `:inverse_of`' do expect_no_offenses( 'has_many :foo, -> () { where(bar: true) }, inverse_of: false' ) end end context 'with option preventing automatic inverse' do it 'registers an offense when not specifying `:inverse_of`' do expect_offense(<<-RUBY.strip_indent) class Person belongs_to :foo, foreign_key: 'foo_id' ^^^^^^^^^^ Specify an `:inverse_of` option. end RUBY end it 'does not register an offense when specifying `:inverse_of`' do expect_no_offenses( "has_one :foo, foreign_key: 'foo_id', inverse_of: :bar" ) end it 'does not register an offense with `:inverse_of` as first option' do expect_no_offenses( "has_one :foo, inverse_of: :bar, foreign_key: 'foo_id'" ) end it 'registers an offense with other option and `:inverse_of` unset' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo, dependent: :destroy, foreign_key: 'foo_id' ^^^^^^^^ Specify an `:inverse_of` option. end RUBY end it 'registers an offense when including `class_name` option' do expect_offense(<<-RUBY.strip_indent) class Book < ApplicationRecord belongs_to :author, class_name: "Patron" ^^^^^^^^^^ Specify an `:inverse_of` option. end RUBY end it 'registers an offense when including `conditions` option' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo, conditions: -> { where(bar: true) } ^^^^^^^^ Specify an `:inverse_of` option. end RUBY end end context 'with scope and options' do it 'registers an offense when not specifying `:inverse_of`' do expect_offense(<<-RUBY.strip_indent) class Person has_many :foo, -> { group 'x' }, dependent: :destroy ^^^^^^^^ Specify an `:inverse_of` option. end RUBY end it 'does not register an offense when specifying `:inverse_of`' do expect_no_offenses( "has_many :foo, -> { group 'x' }, dependent: :destroy, inverse_of: :baz" ) end end context '`:as` option' do context 'Rails < 5.2', :rails5 do it 'registers an offense when not specifying `:inverse_of`' do expect_offense(<<-RUBY.strip_indent) class Person has_many :pictures, as: :imageable ^^^^^^^^ Specify an `:inverse_of` option. end RUBY end end context 'Rails >= 5.2', :config do let(:rails_version) { 5.2 } it 'does not register an offense when not specifying `:inverse_of`' do expect_no_offenses( 'has_many :pictures, as: :imageable' ) end end end context 'with no options' do it 'does not register an offense' do expect_no_offenses('has_one :foo') end end context 'with other options' do it 'does not register an offense' do expect_no_offenses('has_one :foo, dependent: :nullify') end end context 'with option ignoring `:inverse_of`' do it 'does not register an offense when including `through` option' do expect_no_offenses(<<-RUBY.strip_indent) class Physician < ApplicationRecord has_many :appointments has_many :patients, -> () { where(bar: true) }, through: :appointments end RUBY end it 'does not register an offense when including `polymorphic` option' do expect_no_offenses(<<-RUBY.strip_indent) class Picture < ApplicationRecord belongs_to :imageable, -> () { where(bar: true) }, polymorphic: true end RUBY end end context 'with valid options in `with_options`' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options inverse_of: false do has_one :foo, -> () { where(bar: true) } end end RUBY end it 'does not register an offense when using the explicit receiver' do expect_no_offenses(<<-RUBY.strip_indent) class Person with_options inverse_of: :bar do |assoc| assoc.belongs_to :foo, foreign_key: 'foo_id' end end RUBY end it 'registers an offense when using the invalid explicit receiver' do expect_offense(<<-RUBY.strip_indent) class Person with_options inverse_of: :bar do |_assoc| belongs_to :foo, foreign_key: 'foo_id' ^^^^^^^^^^ Specify an `:inverse_of` option. end end RUBY end it 'does not register an offense when using multiple blocks' do expect_no_offenses(<<-RUBY.strip_indent) class Book < ApplicationRecord with_options inverse_of: :book do with_helper do |helper| helper.define_assoc with_options class_name: "Patron" do belongs_to :author end end end end RUBY end end context 'with invalid options in `with_options`' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) class Person with_options class_name: "hoge" do has_one :foo ^^^^^^^ Specify an `:inverse_of` option. end end RUBY end it 'registers an offense when using the explicit receiver' do expect_offense(<<-RUBY.strip_indent) class Person with_options class_name: "baz" do |assoc| assoc.belongs_to :foo, foreign_key: 'foo_id' ^^^^^^^^^^ Specify an `:inverse_of` option. end end RUBY end it 'registers an offense when using multiple blocks' do expect_offense(<<-RUBY.strip_indent) class Book < ApplicationRecord with_options class_name: "Patron" do with_helper do |helper| helper.define_assoc with_options foreign_key: "patron_id" do belongs_to :author ^^^^^^^^^^ Specify an `:inverse_of` option. end end end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/lexically_scoped_action_filter_spec.rb000066400000000000000000000057221322072016200273330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::LexicallyScopedActionFilter do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when string node method is not defined' do expect_offense <<-RUBY class LoginController < ApplicationController before_action :require_login, except: 'health_check' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `health_check` is not explicitly defined on the controller. def index end end RUBY end it 'registers an offense when symbol node method is not defined' do expect_offense <<-RUBY class LoginController < ApplicationController skip_before_action :require_login, only: :health_check ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `health_check` is not explicitly defined on the controller. def index end end RUBY end it 'registers an offense when array string node methods are not defined' do expect_offense <<-RUBY class LoginController < ApplicationController before_action :require_login, only: %w[index settings] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `settings` is not explicitly defined on the controller. def index end end RUBY end it 'registers an offense when array symbol node methods are not defined' do expect_offense <<-RUBY class LoginController < ApplicationController before_action :require_login, only: %i[index settings logout] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `settings`, `logout` are not explicitly defined on the controller. def index end end RUBY end it "doesn't register an offense when string node method is defined" do expect_no_offenses <<-RUBY class LoginController < ApplicationController before_action :require_login, except: 'health_check' def health_check end end RUBY end it "doesn't register an offense when symbol node method is defined" do expect_no_offenses <<-RUBY class LoginController < ApplicationController skip_before_action :require_login, only: :health_check def health_check end end RUBY end it "doesn't register an offense when array string node methods are defined" do expect_no_offenses <<-RUBY class LoginController < ApplicationController before_action :require_login, only: %w[index settings] def index end def settings end end RUBY end it "doesn't register an offense when array symbol node methods are defined" do expect_no_offenses <<-RUBY class LoginController < ApplicationController before_action :require_login, only: %i[index settings logout] def index end def settings end def logout end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/not_null_column_spec.rb000066400000000000000000000052271322072016200243150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::NotNullColumn, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Include' => nil } } context 'with add_column call' do context 'with null: false' do it 'reports an offense' do expect_offense(<<-RUBY.strip_indent) add_column :users, :name, :string, null: false ^^^^^^^^^^^ Do not add a NOT NULL column without a default value. RUBY end end context 'with null: false and default' do let(:source) do 'add_column :users, :name, :string, null: false, default: ""' end include_examples 'accepts' end context 'with null: false and default: nil' do it 'reports an offense' do expect_offense(<<-RUBY.strip_indent) add_column :users, :name, :string, null: false, default: nil ^^^^^^^^^^^ Do not add a NOT NULL column without a default value. RUBY end end context 'with null: true' do let(:source) { 'add_column :users, :name, :string, null: true' } include_examples 'accepts' end context 'without any options' do let(:source) { 'add_column :users, :name, :string' } include_examples 'accepts' end end context 'with change_column call' do let(:source) do <<-RUBY.strip_indent add_column :users, :name, :string User.update_all(name: "dummy") change_column :users, :name, :string, null: false RUBY end include_examples 'accepts' end context 'with create_table call' do let(:source) do <<-RUBY.strip_indent class CreateUsersTable < ActiveRecord::Migration def change create_table :users do |t| t.string :name, null: false t.timestamps null: false end end end RUBY end include_examples 'accepts' end context 'with add_reference call' do context 'with null: false' do it 'reports an offense' do expect_offense(<<-RUBY.strip_indent) add_reference :products, :category, null: false ^^^^^^^^^^^ Do not add a NOT NULL column without a default value. RUBY end end context 'with default option' do let(:source) do 'add_reference :products, :category, null: false, default: 1' end include_examples 'accepts' end context 'without any options' do let(:source) { 'add_reference :products, :category' } include_examples 'accepts' end end end rubocop-0.52.1/spec/rubocop/cop/rails/output_safety_spec.rb000066400000000000000000000100161322072016200240110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::OutputSafety do subject(:cop) { described_class.new } context 'when using `#safe_concat`' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo.safe_concat('bar') ^^^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end it 'registers an offense when wrapped inside `#safe_join`' do expect_offense(<<-RUBY.strip_indent) safe_join([i18n_text.safe_concat(i18n_text)]) ^^^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end context 'when using safe navigation operator', :ruby23 do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo&.safe_concat('bar') ^^^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end end end context 'when using `#html_safe`' do it 'registers an offense for literal receiver and no argument' do expect_offense(<<-RUBY.strip_indent) "foo".html_safe ^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end it 'registers an offense for variable receiver and no argument' do expect_offense(<<-RUBY.strip_indent) foo.html_safe ^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end it 'does not register an offense for variable receiver and arguments' do expect_no_offenses(<<-RUBY.strip_indent) foo.html_safe(one) RUBY end it 'does not register an offense without a receiver' do expect_no_offenses('html_safe') end it 'registers an offense when used inside `#safe_join`' do expect_offense(<<-RUBY.strip_indent) safe_join([i18n_text.html_safe, "foo"]) ^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end it 'registers an offense when used inside `#safe_join` in other method' do expect_offense(<<-RUBY.strip_indent) foo(safe_join([i18n_text.html_safe, "bar"])) ^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end context 'when using safe navigation operator', :ruby23 do it 'registers an offense for variable receiver and no argument' do expect_offense(<<-RUBY.strip_indent) foo&.html_safe ^^^^^^^^^ Tagging a string as html safe may be a security risk. RUBY end end end context 'when using `#raw`' do it 'registers an offense with no receiver and a variable argument' do expect_offense(<<-RUBY) raw(foo) ^^^ Tagging a string as html safe may be a security risk. RUBY end it 'registers an offense with no receiver and a literal argument' do expect_offense(<<-RUBY) raw("foo") ^^^ Tagging a string as html safe may be a security risk. RUBY end it 'does not register an offense with a receiver' do expect_no_offenses(<<-RUBY.strip_indent) foo.raw(foo) RUBY end it 'does not register an offense without arguments' do expect_no_offenses('raw') end it 'does not reguster an offense with more than one argument' do expect_no_offenses('raw(one, two)') end it 'does not ergister an offense for comments' do expect_no_offenses(<<-RUBY.strip_indent) # foo.html_safe # raw foo RUBY end it 'registers an offense when used inside `#safe_join`' do expect_offense(<<-RUBY.strip_indent) safe_join([raw(i18n_text), "foo"]) ^^^ Tagging a string as html safe may be a security risk. RUBY end it 'registers an offense when used inside `#safe_join` in other method' do expect_offense(<<-RUBY.strip_indent) foo(safe_join([raw(i18n_text), "bar"])) ^^^ Tagging a string as html safe may be a security risk. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/output_spec.rb000066400000000000000000000015461322072016200224460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Output do subject(:cop) { described_class.new } it 'records an offense for methods without a receiver' do source = <<-RUBY.strip_indent p "edmond dantes" puts "sinbad" print "abbe busoni" pp "monte cristo" RUBY inspect_source(source) expect(cop.offenses.size).to eq(4) end it 'does not record an offense for methods with a receiver' do expect_no_offenses(<<-RUBY.strip_indent) obj.print something.p nothing.pp RUBY end it 'does not record an offense for methods without arguments' do expect_no_offenses(<<-RUBY.strip_indent) print pp puts RUBY end it 'does not record an offense for comments' do expect_no_offenses(<<-RUBY.strip_indent) # print "test" # p RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/pluralization_grammar_spec.rb000066400000000000000000000064541322072016200255140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::PluralizationGrammar do subject(:cop) { described_class.new } before do inspect_source(source) end shared_examples 'enforces pluralization grammar' do |method_name| context "When #{method_name} is called on an unknown variable" do context "when using the plural form ##{method_name}s" do let(:source) { "some_variable.#{method_name}s" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context "when using the singular form ##{method_name}" do let(:source) { "some_method.#{method_name}" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end end [-1, -1.0, 1, 1.0].each do |singular_literal| context "when mis-pluralizing #{method_name} with #{singular_literal}" do let(:source) { "#{singular_literal}.#{method_name}s.ago" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(["#{singular_literal}.#{method_name}s"]) expect(cop.messages).to eq( ["Prefer `#{singular_literal}.#{method_name}`."] ) end it 'autocorrects to be grammatically correct' do new_source = autocorrect_source(source) expect(new_source).to eq("#{singular_literal}.#{method_name}.ago") end end context "when using the singular form ##{method_name}" do let(:source) { "#{singular_literal}.#{method_name}" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end end context "when #{method_name} is called on any other literal number" do [-rand(2..1000), -rand(0...1.0), 0, rand(0...1.0), rand(2..1000)].each do |plural_number| context "when using the plural form ##{method_name}s" do let(:source) { "#{plural_number}.#{method_name}s" } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context "when using the singular form ##{method_name}" do let(:source) { "#{plural_number}.#{method_name}.from_now" } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(["#{plural_number}.#{method_name}"]) expect(cop.messages).to eq( ["Prefer `#{plural_number}.#{method_name}s`."] ) end it 'autocorrects to be grammatically correct' do new_source = autocorrect_source(source) expect(new_source) .to eq("#{plural_number}.#{method_name}s.from_now") end end end end end it_behaves_like 'enforces pluralization grammar', 'second' it_behaves_like 'enforces pluralization grammar', 'minute' it_behaves_like 'enforces pluralization grammar', 'hour' it_behaves_like 'enforces pluralization grammar', 'day' it_behaves_like 'enforces pluralization grammar', 'week' it_behaves_like 'enforces pluralization grammar', 'fortnight' it_behaves_like 'enforces pluralization grammar', 'month' it_behaves_like 'enforces pluralization grammar', 'year' end rubocop-0.52.1/spec/rubocop/cop/rails/presence_spec.rb000066400000000000000000000104071322072016200227060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Presence do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } shared_examples :offense do |source, correction, first_line, end_line| it 'registers an offense' do inspect_source(source) expect(cop.offenses.count).to eq 1 expect(cop.offenses).to all( have_attributes( first_line: first_line, last_line: end_line ) ) expect(cop.offenses).to all( have_attributes( message: "Use `#{correction}` instead of `#{source}`." ) ) end it 'auto correct' do expect(autocorrect_source(source)).to eq(correction) end end it_behaves_like :offense, 'a.present? ? a : nil', 'a.presence', 1, 1 it_behaves_like :offense, '!a.present? ? nil: a', 'a.presence', 1, 1 it_behaves_like :offense, 'a.blank? ? nil : a', 'a.presence', 1, 1 it_behaves_like :offense, '!a.blank? ? a : nil', 'a.presence', 1, 1 it_behaves_like :offense, 'a.present? ? a : b', 'a.presence || b', 1, 1 it_behaves_like :offense, '!a.present? ? b : a', 'a.presence || b', 1, 1 it_behaves_like :offense, 'a.blank? ? b : a', 'a.presence || b', 1, 1 it_behaves_like :offense, '!a.blank? ? a : b', 'a.presence || b', 1, 1 it_behaves_like :offense, 'a(:bar).map(&:baz).present? ? a(:bar).map(&:baz) : nil', 'a(:bar).map(&:baz).presence', 1, 1 it_behaves_like :offense, <<-RUBY.strip_indent.chomp, 'a.presence', 1, 5 if a.present? a else nil end RUBY it_behaves_like :offense, 'a if a.present?', 'a.presence', 1, 1 it_behaves_like :offense, 'a unless a.blank?', 'a.presence', 1, 1 it_behaves_like :offense, <<-RUBY.strip_indent.chomp, <<-FIXED.strip_indent.chomp, 1, 7 ## rubocop:disable Metrics/LineLength if [1, 2, 3].map { |num| num + 1 } .map { |num| num + 2 } .present? [1, 2, 3].map { |num| num + 1 }.map { |num| num + 2 } else b end RUBY [1, 2, 3].map { |num| num + 1 } .map { |num| num + 2 }.presence || b FIXED it 'does not register an offense when using `#presence`' do expect_no_offenses(<<-RUBY.strip_indent) a.presence RUBY end it 'does not register an offense when the expression does not return the receiver of `#present?`' do # rubocop:disable Metrics/LineLength expect_no_offenses(<<-RUBY.strip_indent) a.present? ? b : nil RUBY end it 'does not register an offense when the expression does not return the receiver of `#blank?`' do # rubocop:disable Metrics/LineLength expect_no_offenses(<<-RUBY.strip_indent) a.blank? ? nil : b RUBY end it 'does not register an offense when if or unless modifier is used ' do [ 'a if a.blank?', 'a unless a.present?' ].each { |source| expect_no_offenses(source) } end it 'does not register an offense when the else block is multiline' do expect_no_offenses(<<-RUBY.strip_indent) if a.present? a else something something something end RUBY end it 'does not register an offense when the else block has multiple statements' do # rubocop:disable Metrics/LineLength expect_no_offenses(<<-RUBY.strip_indent) if a.present? a else something; something; something end RUBY end it 'does not register an offense when including the elsif block' do expect_no_offenses(<<-RUBY.strip_indent) if a.present? a elsif b b end RUBY end it 'does not register an offense when the else block has `if` node' do expect_no_offenses(<<-RUBY.strip_indent) if a.present? a else b if c end RUBY end it 'does not register an offense when the else block has `rescue` node' do expect_no_offenses(<<-RUBY.strip_indent) if something_method.present? something_method else invalid_method rescue StandardError end RUBY end it 'does not register an offense when the else block has `while` node' do expect_no_offenses(<<-RUBY.strip_indent) if a.present? a else fetch_state while waiting? end RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/present_spec.rb000066400000000000000000000213451322072016200225650ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Present, :config do subject(:cop) { described_class.new(config) } shared_examples :offense do |source, correction, message| it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq([message]) expect(cop.highlights).to eq([source]) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(correction) end end context 'NotNilAndNotEmpty set to true' do let(:cop_config) do { 'NotNilAndNotEmpty' => true, 'NotBlank' => false, 'UnlessBlank' => false } end it 'accepts checking nil?' do expect_no_offenses('foo.nil?') end it 'accepts checking empty?' do expect_no_offenses('foo.empty?') end it 'accepts checking nil? || empty? on different objects' do expect_no_offenses('foo.nil? || bar.empty?') end it 'accepts checking existence && not empty? on different objects' do expect_no_offenses('foo && !bar.empty?') end it_behaves_like :offense, 'foo && !foo.empty?', 'foo.present?', 'Use `foo.present?` instead of `foo && !foo.empty?`.' it_behaves_like :offense, '!foo.nil? && !foo.empty?', 'foo.present?', 'Use `foo.present?` instead of `!foo.nil? && !foo.empty?`.' it_behaves_like :offense, '!nil? && !empty?', 'present?', 'Use `present?` instead of `!nil? && !empty?`.' it_behaves_like :offense, 'foo != nil && !foo.empty?', 'foo.present?', 'Use `foo.present?` instead of `foo != nil && !foo.empty?`.' it_behaves_like :offense, '!!foo && !foo.empty?', 'foo.present?', 'Use `foo.present?` instead of `!!foo && !foo.empty?`.' context 'checking all variable types' do it_behaves_like :offense, '!foo.nil? && !foo.empty?', 'foo.present?', 'Use `foo.present?` instead of ' \ '`!foo.nil? && !foo.empty?`.' it_behaves_like :offense, '!foo.bar.nil? && !foo.bar.empty?', 'foo.bar.present?', 'Use `foo.bar.present?` instead of ' \ '`!foo.bar.nil? && !foo.bar.empty?`.' it_behaves_like :offense, '!FOO.nil? && !FOO.empty?', 'FOO.present?', 'Use `FOO.present?` instead of ' \ '`!FOO.nil? && !FOO.empty?`.' it_behaves_like :offense, '!Foo.nil? && !Foo.empty?', 'Foo.present?', 'Use `Foo.present?` instead of ' \ '`!Foo.nil? && !Foo.empty?`.' it_behaves_like :offense, '!@foo.nil? && !@foo.empty?', '@foo.present?', 'Use `@foo.present?` instead of ' \ '`!@foo.nil? && !@foo.empty?`.' it_behaves_like :offense, '!$foo.nil? && !$foo.empty?', '$foo.present?', 'Use `$foo.present?` instead of ' \ '`!$foo.nil? && !$foo.empty?`.' it_behaves_like :offense, '!@@foo.nil? && !@@foo.empty?', '@@foo.present?', 'Use `@@foo.present?` instead of ' \ '`!@@foo.nil? && !@@foo.empty?`.' it_behaves_like :offense, '!foo[bar].nil? && !foo[bar].empty?', 'foo[bar].present?', 'Use `foo[bar].present?` instead of ' \ '`!foo[bar].nil? && !foo[bar].empty?`.' it_behaves_like :offense, '!Foo::Bar.nil? && !Foo::Bar.empty?', 'Foo::Bar.present?', 'Use `Foo::Bar.present?` instead of ' \ '`!Foo::Bar.nil? && !Foo::Bar.empty?`.' it_behaves_like :offense, '!foo(bar).nil? && !foo(bar).empty?', 'foo(bar).present?', 'Use `foo(bar).present?` instead of ' \ '`!foo(bar).nil? && !foo(bar).empty?`.' end end context 'NotBlank set to true' do let(:cop_config) do { 'NotNilAndNotEmpty' => false, 'NotBlank' => true, 'UnlessBlank' => false } end it_behaves_like :offense, '!foo.blank?', 'foo.present?', 'Use `foo.present?` instead of `!foo.blank?`.' it_behaves_like :offense, 'not foo.blank?', 'foo.present?', 'Use `foo.present?` instead of `not foo.blank?`.' it_behaves_like :offense, '!blank?', 'present?', 'Use `present?` instead of `!blank?`.' end context 'UnlessBlank set to true' do let(:cop_config) do { 'NotNilAndNotEmpty' => false, 'NotBlank' => false, 'UnlessBlank' => true } end it 'accepts modifier if blank?' do expect_no_offenses('something if foo.blank?') end it 'accepts modifier unless present?' do expect_no_offenses('something unless foo.present?') end it 'accepts normal if blank?' do expect_no_offenses(<<-RUBY.strip_indent) if foo.blank? something end RUBY end it 'accepts normal unless present?' do expect_no_offenses(<<-RUBY.strip_indent) unless foo.present? something end RUBY end context 'unless blank?' do context 'modifier unless' do context 'with a receiver' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) something unless foo.blank? ^^^^^^^^^^^^^^^^^ Use `if foo.present?` instead of `unless foo.blank?`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('something unless foo.blank?') expect(new_source).to eq('something if foo.present?') end end context 'without a receiver' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) something unless blank? ^^^^^^^^^^^^^ Use `if present?` instead of `unless blank?`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('something unless blank?') expect(new_source).to eq('something if present?') end end end context 'normal unless blank?' do let(:source) do <<-RUBY.strip_indent unless foo.blank? something end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless foo.blank? ^^^^^^^^^^^^^^^^^ Use `if foo.present?` instead of `unless foo.blank?`. something end RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo.present? something end RUBY end end context 'unless blank? with an else' do let(:source) do <<-RUBY.strip_indent unless foo.blank? something else something_else end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless foo.blank? ^^^^^^^^^^^^^^^^^ Use `if foo.present?` instead of `unless foo.blank?`. something else something_else end RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo.present? something else something_else end RUBY end end end end context 'NotNilAndNotEmpty set to false' do let(:cop_config) do { 'NotNilAndNotEmpty' => false, 'NotBlank' => true, 'UnlessBlank' => true } end it 'accepts checking nil? || empty?' do expect_no_offenses('foo.nil? || foo.empty?') end end context 'NotBlank set to false' do let(:cop_config) do { 'NotNilAndNotEmpty' => true, 'NotBlank' => false, 'UnlessBlank' => true } end it 'accepts !...blank?' do expect_no_offenses('!foo.blank?') end end context 'UnlessBlank set to false' do let(:cop_config) do { 'NotNilAndNotEmpty' => true, 'NotBlank' => true, 'UnlessBlank' => false } end it 'accepts unless blank?' do expect_no_offenses('something unless foo.blank?') end end end rubocop-0.52.1/spec/rubocop/cop/rails/read_write_attribute_spec.rb000066400000000000000000000070151322072016200253130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::ReadWriteAttribute do subject(:cop) { described_class.new } context 'read_attribute' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) res = read_attribute(:test) ^^^^^^^^^^^^^^ Prefer `self[:attr]` over `read_attribute(:attr)`. RUBY end it 'registers no offense with explicit receiver' do expect_no_offenses('res = object.read_attribute(:test)') end end context 'write_attribute' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) write_attribute(:test, val) ^^^^^^^^^^^^^^^ Prefer `self[:attr] = val` over `write_attribute(:attr, val)`. RUBY end it 'registers no offense with explicit receiver' do expect_no_offenses('object.write_attribute(:test, val)') end end describe '#autocorrect' do context 'write_attribute' do it 'autocorrects symbol' do source = 'write_attribute(:attr, var)' corrected_source = 'self[:attr] = var' expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects string' do source = "write_attribute('attr', 'test')" corrected_source = "self['attr'] = 'test'" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects without parentheses' do source = "write_attribute 'attr', 'test'" corrected_source = "self['attr'] = 'test'" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects expression' do source = "write_attribute(:attr, 'test_' + postfix)" corrected_source = "self[:attr] = 'test_' + postfix" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects multiline' do source = [ 'write_attribute(', ':attr, ', '(', "'test_' + postfix", ').to_sym', ')', '' ] corrected_source = <<-RUBY.strip_indent self[:attr] = ( 'test_' + postfix ).to_sym RUBY expect(autocorrect_source(source)).to eq(corrected_source) end end context 'read_attribute' do it 'autocorrects symbol' do source = 'res = read_attribute(:test)' corrected_source = 'res = self[:test]' expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects string' do source = "res = read_attribute('test')" corrected_source = "res = self['test']" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects without parentheses' do source = "res = read_attribute 'test'" corrected_source = "res = self['test']" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects expression' do source = "res = read_attribute('test_' + postfix)" corrected_source = "res = self['test_' + postfix]" expect(autocorrect_source(source)).to eq(corrected_source) end it 'autocorrects multiline' do source = <<-RUBY.strip_indent res = read_attribute( ( 'test_' + postfix ).to_sym ) RUBY corrected_source = <<-RUBY.strip_indent res = self[( 'test_' + postfix ).to_sym] RUBY expect(autocorrect_source(source)).to eq(corrected_source) end end end end rubocop-0.52.1/spec/rubocop/cop/rails/redundant_receiver_in_with_options_spec.rb000066400000000000000000000075721322072016200302570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::RedundantReceiverInWithOptions, :config do subject(:cop) { described_class.new(config) } context 'rails >= 4.2' do let(:rails_version) { 4.2 } it 'registers an offense when using explicit receiver in `with_options`' do expect_offense(<<-RUBY.strip_indent) class Account < ApplicationRecord with_options dependent: :destroy do |assoc| assoc.has_many :customers ^^^^^ Redundant receiver in `with_options`. assoc.has_many :products ^^^^^ Redundant receiver in `with_options`. assoc.has_many :invoices ^^^^^ Redundant receiver in `with_options`. assoc.has_many :expenses ^^^^^ Redundant receiver in `with_options`. end end RUBY end it 'does not register an offense when using inplicit receiver ' \ 'in `with_options`' do expect_no_offenses(<<-RUBY.strip_indent) class Account < ApplicationRecord with_options dependent: :destroy do has_many :customers has_many :products has_many :invoices has_many :expenses end end RUBY end it 'registers an offense when including multiple redendant receivers ' \ 'in single line' do expect_offense(<<-RUBY.strip_indent) with_options options: false do |merger| merger.invoke(merger.something) ^^^^^^ Redundant receiver in `with_options`. ^^^^^^ Redundant receiver in `with_options`. end RUBY end it 'does not register an offense when including method invocations ' \ 'to different receivers' do expect_no_offenses(<<-RUBY.strip_indent) client = ApplicationClient.new with_options options: false do |merger| client.invoke(merger.something, something) end RUBY end it 'autocorrects to implicit receiver in `with_options`' do new_source = autocorrect_source(<<-RUBY.strip_indent) class Account < ApplicationRecord with_options dependent: :destroy do |assoc| assoc.has_many :customers assoc.has_many :products assoc.has_many :invoices assoc.has_many :expenses end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class Account < ApplicationRecord with_options dependent: :destroy do has_many :customers has_many :products has_many :invoices has_many :expenses end end RUBY end it 'autocorrects to implicit receiver when including multiple receivers' do new_source = autocorrect_source(<<-RUBY.strip_indent) with_options options: false do |merger| merger.invoke(merger.something) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) with_options options: false do invoke(something) end RUBY end it 'does not register an offense when including block node' \ 'in `with_options`' do expect_no_offenses(<<-RUBY.strip_indent) with_options options: false do |merger| merger.invoke with_another_method do |another_receiver| merger.invoke(another_receiver) end end RUBY end end context 'rails <= 4.1' do let(:rails_version) { 4.1 } it 'registers an offense when using explicit receiver in `with_options`' do expect_no_offenses(<<-RUBY.strip_indent) class Account < ApplicationRecord with_options dependent: :destroy do |assoc| assoc.has_many :customers assoc.has_many :products assoc.has_many :invoices assoc.has_many :expenses end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/relative_date_constant_spec.rb000066400000000000000000000046741322072016200256340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::RelativeDateConstant do subject(:cop) { described_class.new } it 'registers an offense for ActiveSupport::Duration.since' do expect_offense(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT = 1.week.since ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not assign since to constants as it will be evaluated only once. end RUBY end it 'accepts a method with arguments' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT = 1.week.since(base) end RUBY end it 'accepts a lambda' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT = -> { 1.year.ago } end RUBY end it 'accepts a proc' do expect_no_offenses(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT = Proc.new { 1.year.ago } end RUBY end it 'registers an offense for relative date in ||=' do expect_offense(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT ||= 1.week.since ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not assign since to constants as it will be evaluated only once. end RUBY end it 'registers an offense for relative date in multiple assignment' do expect_offense(<<-RUBY.strip_indent) class SomeClass START, A, x = 2.weeks.ago, 1.week.since, 5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not assign ago to constants as it will be evaluated only once. end RUBY end it 'registers an offense for exclusive end range' do expect_offense(<<-RUBY.strip_indent) class SomeClass TRIAL_PERIOD = DateTime.current..1.day.since ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not assign since to constants as it will be evaluated only once. end RUBY end it 'registers an offense for inclusive end range' do expect_offense(<<-RUBY.strip_indent) class SomeClass TRIAL_PERIOD = DateTime.current...1.day.since ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not assign since to constants as it will be evaluated only once. end RUBY end it 'autocorrects' do new_source = autocorrect_source(<<-RUBY.strip_indent) class SomeClass EXPIRED_AT = 1.week.since end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class SomeClass def self.expired_at 1.week.since end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/request_referer_spec.rb000066400000000000000000000027711322072016200243110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::RequestReferer, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is referer' do before { inspect_source('puts request.referrer') } let(:cop_config) { { 'EnforcedStyle' => 'referer' } } it 'registers an offense for request.referrer' do expect(cop.offenses.size).to eq(1) end it 'highlights the offence' do expect(cop.highlights).to eq(['request.referrer']) end it 'sends a message to the user' do expect(cop.messages) .to eq(['Use `request.referer` instead of `request.referrer`.']) end it 'autocorrects referrer with referer' do corrected = autocorrect_source(['puts request.referrer']) expect(corrected).to eq 'puts request.referer' end end context 'when EnforcedStyle is referrer' do before { inspect_source('puts request.referer') } let(:cop_config) { { 'EnforcedStyle' => 'referrer' } } it 'registers an offense for request.referer' do expect(cop.offenses.size).to eq(1) end it 'highlights the offence' do expect(cop.highlights).to eq(['request.referer']) end it 'sends a message to the user' do expect(cop.messages) .to eq(['Use `request.referrer` instead of `request.referer`.']) end it 'autocorrects referer with referrer' do corrected = autocorrect_source(['puts request.referer']) expect(corrected).to eq 'puts request.referrer' end end end rubocop-0.52.1/spec/rubocop/cop/rails/reversible_migration_spec.rb000066400000000000000000000113701322072016200253150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::ReversibleMigration, :config do subject(:cop) { described_class.new(config) } let(:source) do <<-RUBY class ExampleMigration < ActiveRecord::Migration def change #{code} end end RUBY end shared_examples :accepts do |name, code| let(:code) { code } it "accepts usages of #{name}" do inspect_source(source) expect(cop.offenses.empty?).to be(true) end end shared_examples :offense do |name, code| let(:code) { code } it "registers an offense for #{name}" do inspect_source(source) expect(cop.messages).to eq(["#{name} is not reversible."]) end end it_behaves_like :accepts, 'create_table', <<-RUBY create_table :users do |t| t.string :name end RUBY it_behaves_like :offense, 'execute', <<-RUBY execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)" RUBY context 'within block' do it_behaves_like :accepts, 'create_table', <<-RUBY [:users, :articles].each do |table| create_table table do |t| t.string :name end end RUBY it_behaves_like :offense, 'execute', <<-RUBY [:pages_linked_pages, :pages_unlinked_pages].each do |table| execute "ALTER TABLE `table` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)" end RUBY end context 'within #reversible' do it_behaves_like :accepts, 'execute', <<-RUBY reversible do |dir| dir.up do execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)" end dir.down do execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`" end end RUBY end context 'drop_table' do it_behaves_like :accepts, 'drop_table(with block)', <<-RUBY drop_table :users do |t| t.string :name end RUBY it_behaves_like :offense, 'drop_table(without block)', <<-RUBY drop_table :users RUBY end context 'change_column_default' do it_behaves_like :accepts, 'change_column_default(with :from and :to)', <<-RUBY change_column_default(:posts, :state, from: nil, to: "draft") RUBY it_behaves_like :offense, 'change_column_default(without :from and :to)', <<-RUBY change_column_default(:suppliers, :qualification, 'new') RUBY end context 'remove_column' do it_behaves_like :accepts, 'remove_column(with type)', <<-RUBY remove_column(:suppliers, :qualification, :string) RUBY it_behaves_like :accepts, 'remove_column(with type and options)', <<-RUBY remove_column(:suppliers, :qualification, :string, null: false) RUBY it_behaves_like :offense, 'remove_column(without type)', <<-RUBY remove_column(:suppliers, :qualification) RUBY end context 'remove_foreign_key' do it_behaves_like :accepts, 'remove_foreign_key(with table)', <<-RUBY remove_foreign_key :accounts, :branches RUBY it_behaves_like :offense, 'remove_foreign_key(without table)', <<-RUBY remove_foreign_key :accounts, column: :owner_id RUBY end context 'change_table' do context 'Rails < 4.0', :rails3 do it_behaves_like :offense, 'change_table', <<-RUBY change_table :users do |t| t.column :name, :string t.text :description t.boolean :authorized end RUBY it_behaves_like :offense, 'change_table', <<-RUBY change_table :users do |t| t.change :description, :text end RUBY it_behaves_like :offense, 'change_table', <<-RUBY change_table :users do |t| t.change_default :authorized, 1 end RUBY it_behaves_like :offense, 'change_table', <<-RUBY change_table :users do |t| t.remove :qualification end RUBY end context 'Rails >= 4.0', :rails4 do it_behaves_like :accepts, 'change_table(with reversible calls)', <<-RUBY change_table :users do |t| t.column :name, :string t.text :description t.boolean :authorized end RUBY it_behaves_like :offense, 'change_table(with change)', <<-RUBY change_table :users do |t| t.change :description, :text end RUBY it_behaves_like :offense, 'change_table(with change_default)', <<-RUBY change_table :users do |t| t.change_default :authorized, 1 end RUBY it_behaves_like :offense, 'change_table(with remove)', <<-RUBY change_table :users do |t| t.remove :qualification end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/safe_navigation_spec.rb000066400000000000000000000221401322072016200242340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::SafeNavigation, :config do subject(:cop) { described_class.new(config) } shared_examples :accepts do |name, code| it "accepts usages of #{name}" do inspect_source("[1, 2].#{code}") expect(cop.offenses.empty?).to be(true) end end shared_examples :offense do |name, method, params| it "registers an offense for #{name}" do inspect_source("[1, 2].#{method}#{params}") expect(cop.messages) .to eq([format('Use safe navigation (`&.`) instead of `%s`.', method)]) end end shared_examples :autocorrect do |name, source, correction| it "corrects #{name}" do new_source = autocorrect_source(source) expect(new_source).to eq(correction) end end context 'only convert try!' do let(:cop_config) { { 'ConvertTry' => false } } it_behaves_like :accepts, 'non try! method calls', 'join' context 'target_ruby_version < 2.3', :ruby22 do it_behaves_like :accepts, 'try! with a single parameter', 'try!(:join)' it_behaves_like :accepts, 'try! with a multiple parameters', 'try!(:join, ",")' it_behaves_like :accepts, 'try! with a block', 'try!(:map) { |e| e.some_method }' it_behaves_like :accepts, 'try! with params and a block', ['try!(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end context 'target_ruby_version > 2.3', :ruby23 do context 'try!' do it_behaves_like :offense, 'try! with a single parameter', 'try!', '(:join)' it_behaves_like :offense, 'try! with a multiple parameters', 'try!', '(:join, ",")' it_behaves_like :offense, 'try! with a block', 'try!', '(:map) { |e| e.some_method }' it_behaves_like :offense, 'try! with params and a block', 'try!', ['(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") it_behaves_like :offense, 'try! with a question method', 'try!', '(:something?)' it_behaves_like :offense, 'try! with a bang method', 'try!', '(:something!)' it_behaves_like :accepts, 'try! used to call an enumerable accessor', 'foo.try!(:[], :bar)' it_behaves_like :accepts, 'try! with ==', 'foo.try!(:==, bar)' it_behaves_like :accepts, 'try! with an operator', 'foo.try!(:+, bar)' it_behaves_like :accepts, 'try! with a method stored as a variable', ['bar = :==', 'foo.try!(baz, bar)'].join("\n") it 'accepts usages of try! without receiver' do expect_no_offenses('try!(:something)') end end context 'try' do it_behaves_like :accepts, 'try with a single parameter', 'try(:join)' it_behaves_like :accepts, 'try with a multiple parameters', 'try(:join, ",")' it_behaves_like :accepts, 'try with a block', 'try(:map) { |e| e.some_method }' it_behaves_like :accepts, 'try with params and a block', ['try(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end it_behaves_like :autocorrect, 'try! a single parameter', 'foo.try!(:thing=, bar)', 'foo&.thing = bar' it_behaves_like :autocorrect, 'try! a single parameter', '[1, 2].try!(:join)', '[1, 2]&.join' it_behaves_like :autocorrect, 'try! with 2 parameters', '[1, 2].try!(:join, ",")', '[1, 2]&.join(",")' it_behaves_like :autocorrect, 'try! with multiple parameters', '[1, 2].try!(:join, bar, baz)', '[1, 2]&.join(bar, baz)' it_behaves_like :autocorrect, 'try! with a block', ['[foo, bar].try!(:map) do |e|', ' e.some_method', 'end'].join("\n"), ['[foo, bar]&.map do |e|', ' e.some_method', 'end'].join("\n") it_behaves_like :autocorrect, 'try! with params and a block', ['[foo, bar].try!(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n"), ['[foo, bar]&.each_with_object([]) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end end context 'convert try and try!' do let(:cop_config) { { 'ConvertTry' => true } } context 'target_ruby_version < 2.3', :ruby22 do it_behaves_like :accepts, 'try! with a single parameter', 'try!(:join)' it_behaves_like :accepts, 'try! with a multiple parameters', 'try!(:join, ",")' it_behaves_like :accepts, 'try! with a block', 'try!(:map) { |e| e.some_method }' it_behaves_like :accepts, 'try! with params and a block', ['try!(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end context 'target_ruby_version > 2.3', :ruby23 do context 'try!' do it_behaves_like :offense, 'try! with a single parameter', 'try!', '(:join)' it_behaves_like :offense, 'try! with a multiple parameters', 'try!', '(:join, ",")' it_behaves_like :offense, 'try! with a block', 'try!', '(:map) { |e| e.some_method }' it_behaves_like :offense, 'try! with params and a block', 'try!', ['(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") it_behaves_like :accepts, 'try! used to call an enumerable accessor', 'foo.try!(:[], :bar)' it_behaves_like :autocorrect, 'try! a single parameter', '[1, 2].try!(:join)', '[1, 2]&.join' it_behaves_like :autocorrect, 'try! with 2 parameters', '[1, 2].try!(:join, ",")', '[1, 2]&.join(",")' it_behaves_like :autocorrect, 'try! with multiple parameters', '[1, 2].try!(:join, bar, baz)', '[1, 2]&.join(bar, baz)' it_behaves_like :autocorrect, 'try! with a block', ['[foo, bar].try!(:map) do |e|', ' e.some_method', 'end'].join("\n"), ['[foo, bar]&.map do |e|', ' e.some_method', 'end'].join("\n") it_behaves_like :autocorrect, 'try! with params and a block', ['[foo, bar].try!(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n"), ['[foo, bar]&.each_with_object([]) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end context 'try' do it_behaves_like :offense, 'try with a single parameter', 'try', '(:join)' it_behaves_like :offense, 'try with a multiple parameters', 'try', '(:join, ",")' it_behaves_like :offense, 'try with a block', 'try', '(:map) { |e| e.some_method }' it_behaves_like :offense, 'try with params and a block', 'try', ['(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") it_behaves_like :accepts, 'try! used to call an enumerable accessor', 'foo.try!(:[], :bar)' it_behaves_like :autocorrect, 'try a single parameter', '[1, 2].try(:join)', '[1, 2]&.join' it_behaves_like :autocorrect, 'try with 2 parameters', '[1, 2].try(:join, ",")', '[1, 2]&.join(",")' it_behaves_like :autocorrect, 'try with multiple parameters', '[1, 2].try(:join, bar, baz)', '[1, 2]&.join(bar, baz)' it_behaves_like :autocorrect, 'try with a block', ['[foo, bar].try(:map) do |e|', ' e.some_method', 'end'].join("\n"), ['[foo, bar]&.map do |e|', ' e.some_method', 'end'].join("\n") it_behaves_like :autocorrect, 'try with params and a block', ['[foo, bar].try(:each_with_object, []) do |e, acc|', ' acc << e.some_method', 'end'].join("\n"), ['[foo, bar]&.each_with_object([]) do |e, acc|', ' acc << e.some_method', 'end'].join("\n") end end end end rubocop-0.52.1/spec/rubocop/cop/rails/save_bang_spec.rb000066400000000000000000000156331322072016200230350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::SaveBang do subject(:cop) { described_class.new } shared_examples 'checks_common_offense' do |method| it "when using #{method} with arguments" do inspect_source("object.#{method}(name: 'Tom', age: 20)") if method == :destroy expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["Use `#{method}!` instead of `#{method}` " \ 'if the return value is not checked.']) end end it "when using #{method} without arguments" do inspect_source(method.to_s) expect(cop.messages) .to eq(["Use `#{method}!` instead of `#{method}` " \ 'if the return value is not checked.']) end it "when using #{method}!" do inspect_source("object.#{method}!") expect(cop.messages.empty?).to be(true) end it "when using #{method} with 2 arguments" do inspect_source("Model.#{method}(1, name: 'Tom')") expect(cop.messages.empty?).to be(true) end it "when using #{method} with wrong argument" do inspect_source("object.#{method}('Tom')") expect(cop.messages.empty?).to be(true) end it 'autocorrects' do new_source = autocorrect_source("object.#{method}()") expect(new_source).to eq("object.#{method}!()") end end shared_examples 'checks_variable_return_use_offense' do |method, pass| it "when assigning the return value of #{method}" do inspect_source("x = object.#{method}\n") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["Use `#{method}!` instead of `#{method}` " \ 'if the return value is not checked.' \ " Or check `persisted?` on model returned from `#{method}`."]) end end it "when assigning the return value of #{method} with block" do inspect_source("x = object.#{method} do |obj|\n" \ " obj.name = 'Tom'\n" \ 'end') if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["Use `#{method}!` instead of `#{method}` " \ 'if the return value is not checked.' \ " Or check `persisted?` on model returned from `#{method}`."]) end end it "when using #{method} with if" do inspect_source("if object.#{method}; something; end") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with multiple conditional" do inspect_source(<<-RUBY.strip_indent) if true && object.active? && object.#{method} something end RUBY if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with oneline if" do inspect_source("something if object.#{method}") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with oneline if and multiple conditional" do inspect_source("something if false || object.#{method}") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with case statement" do inspect_source(<<-RUBY.strip_indent) case object.#{method} when true puts "true" when false puts "false" end RUBY if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with '&&'" do inspect_source("object.#{method} && false") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with 'and'" do inspect_source("object.#{method} and false") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with '||'" do inspect_source("object.#{method} || false") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} with 'or'" do inspect_source("object.#{method} or false") if pass expect(cop.messages.empty?).to be(true) else expect(cop.messages) .to eq(["`#{method}` returns a model which is always truthy."]) end end it "when using #{method} as last method call" do inspect_source(['def foo', "object.#{method}", 'end']) expect(cop.messages.empty?).to be(true) end # Bug: https://github.com/bbatsov/rubocop/issues/4264 it 'when using the assigned variable as value in a hash' do inspect_source(['def foo', " foo = Foo.#{method}", ' render json: foo', 'end']) if pass expect(cop.offenses.empty?).to be(true) else expect(cop.offenses.size).to eq(1) end end end described_class::MODIFY_PERSIST_METHODS.each do |method| it_behaves_like('checks_common_offense', method) it_behaves_like('checks_variable_return_use_offense', method, true) end shared_examples 'checks_create_offense' do |method| it "when using persisted? after #{method}" do inspect_source("x = object.#{method}\n" \ 'if x.persisted? then; something; end') expect(cop.messages.empty?).to be(true) end it "when using persisted? after #{method} with block" do inspect_source("x = object.#{method} do |obj|\n" \ " obj.name = 'Tom'\n" \ "end\n" \ 'if x.persisted? then; something; end') expect(cop.messages.empty?).to be(true) end end described_class::CREATE_PERSIST_METHODS.each do |method| it_behaves_like('checks_common_offense', method) it_behaves_like('checks_variable_return_use_offense', method, false) it_behaves_like('checks_create_offense', method) end it 'properly ignores lvasign without right hand side' do expect_no_offenses('variable += 1') end end rubocop-0.52.1/spec/rubocop/cop/rails/scope_args_spec.rb000066400000000000000000000024261322072016200232310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::ScopeArgs do subject(:cop) { described_class.new } it 'registers an offense a scope with a method arg' do expect_offense(<<-RUBY.strip_indent) scope :active, where(active: true) ^^^^^^^^^^^^^^^^^^^ Use `lambda`/`proc` instead of a plain method call. RUBY end it 'accepts a non send argument' do expect_no_offenses('scope :active, "adsf"') end it 'accepts a stabby lambda' do expect_no_offenses('scope :active, -> { where(active: true) }') end it 'accepts a stabby lambda with arguments' do expect_no_offenses( 'scope :active, ->(active) { where(active: active) }' ) end it 'accepts a lambda' do expect_no_offenses('scope :active, lambda { where(active: true) }') end it 'accepts a lambda with a block argument' do expect_no_offenses( 'scope :active, lambda { |active| where(active: active) }' ) end it 'accepts a lambda with a multiline block' do expect_no_offenses(<<-RUBY.strip_indent) scope :active, (lambda do |active| where(active: active) end) RUBY end it 'accepts a proc' do expect_no_offenses('scope :active, proc { where(active: true) }') end end rubocop-0.52.1/spec/rubocop/cop/rails/skips_model_validations_spec.rb000066400000000000000000000047471322072016200260220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::SkipsModelValidations, :config do cop_config = { 'Blacklist' => %w[decrement! decrement_counter increment! increment_counter toggle! touch update_all update_attribute update_column update_columns update_counters] } subject(:cop) { described_class.new(config) } let(:msg) { 'Avoid using `%s` because it skips validations.' } let(:cop_config) { cop_config } methods_with_arguments = described_class::METHODS_WITH_ARGUMENTS context 'with default blacklist' do cop_config['Blacklist'].each do |method_name| it "registers an offense for `#{method_name}`" do inspect_source("User.#{method_name}(:attr)") expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq([format(msg, method_name)]) end end it 'accepts FileUtils.touch' do expect_no_offenses("FileUtils.touch('file')") end end context 'with methods that require at least an argument' do methods_with_arguments.each do |method_name| it "doesn't register an offense for `#{method_name}`" do inspect_source("User.#{method_name}") expect(cop.offenses.empty?).to be(true) end end end context "with methods that don't require an argument" do (cop_config['Blacklist'] - methods_with_arguments).each do |method_name| it "registers an offense for `#{method_name}`" do inspect_source("User.#{method_name}") expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq([format(msg, method_name)]) end end end context 'with `update_attribute` method in blacklist' do let(:cop_config) do { 'Blacklist' => %w[update_attribute] } end whitelist = cop_config['Blacklist'].reject do |val| val == 'update_attribute' end whitelist.each do |method_name| it "accepts `#{method_name}`" do inspect_source("User.#{method_name}") expect(cop.offenses.empty?).to be(true) end end it 'registers an offense for `update_attribute`' do expect_offense(<<-RUBY.strip_indent) user.update_attribute('website': 'example.com') ^^^^^^^^^^^^^^^^ Avoid using `update_attribute` because it skips validations. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/rails/time_zone_spec.rb000066400000000000000000000226151322072016200230770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::TimeZone, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is "strict"' do let(:cop_config) { { 'EnforcedStyle' => 'strict' } } described_class::TIMECLASS.each do |klass| it "registers an offense for #{klass}.now" do inspect_source("#{klass}.now") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to include('`Time.zone.now`') end it "registers an offense for #{klass}.current" do inspect_source("#{klass}.current") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to include('`Time.zone.now`') end it "registers an offense for #{klass}.new without argument" do inspect_source("#{klass}.new") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to include('`Time.zone.now`') end it "registers an offense for #{klass}.new with argument" do inspect_source("#{klass}.new(2012, 6, 10, 12, 00)") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to include('`Time.zone.local`') end it 'does not register an offense when a .new method is made independently of the Time class' do inspect_source('Range.new(1, Time.days_in_month(date.month, date.year))') expect(cop.offenses.empty?).to be(true) end it "does not register an offense for #{klass}.new with zone argument" do inspect_source("#{klass}.new(1988, 3, 15, 3, 0, 0, '-05:00')") expect(cop.offenses.empty?).to be(true) end it "registers an offense for ::#{klass}.now" do inspect_source("::#{klass}.now") expect(cop.offenses.size).to eq(1) end it "accepts Some::#{klass}.now" do inspect_source("Some::#{klass}.forward(0).strftime('%H:%M')") expect(cop.offenses.empty?).to be(true) end described_class::ACCEPTED_METHODS.each do |a_method| it "registers an offense #{klass}.now.#{a_method}" do inspect_source("#{klass}.now.#{a_method}") expect(cop.offenses.size).to eq(1) end end end it 'registers an offense for Time.parse' do expect_offense(<<-RUBY.strip_indent) Time.parse("2012-03-02 16:05:37") ^^^^^ Do not use `Time.parse` without zone. Use `Time.zone.parse` instead. RUBY end it 'registers an offense for Time.strftime' do expect_offense(<<-RUBY.strip_indent) Time.strftime(time_string, "%Y-%m-%dT%H:%M:%S%z") ^^^^^^^^ Do not use `Time.strftime` without zone. Use `Time.zone.strftime` instead. RUBY end it 'registers an offense for Time.strftime.in_time_zone' do expect_offense(<<-RUBY.strip_indent) Time.strftime(time_string, "%Y-%m-%dT%H:%M:%S%z").in_time_zone ^^^^^^^^ Do not use `Time.strftime` without zone. Use `Time.zone.strftime` instead. RUBY end it 'registers an offense for Time.strftime with nested Time.zone' do expect_offense(<<-RUBY.strip_indent) Time.strftime(Time.zone.now.to_s, "%Y-%m-%dT%H:%M:%S%z") ^^^^^^^^ Do not use `Time.strftime` without zone. Use `Time.zone.strftime` instead. RUBY end it 'registers an offense for Time.zone.strftime with nested Time.now' do expect_offense(<<-RUBY.strip_indent) Time.zone.strftime(Time.now.to_s, "%Y-%m-%dT%H:%M:%S%z") ^^^ Do not use `Time.now.strftime` without zone. Use `Time.zone.now.strftime` instead. RUBY end it 'registers an offense for Time.at' do expect_offense(<<-RUBY.strip_indent) Time.at(ts) ^^ Do not use `Time.at` without zone. Use `Time.zone.at` instead. RUBY end it 'registers an offense for Time.at.in_time_zone' do expect_offense(<<-RUBY.strip_indent) Time.at(ts).in_time_zone ^^ Do not use `Time.at` without zone. Use `Time.zone.at` instead. RUBY end it 'registers an offense for Time.parse.localtime(offset)' do expect_offense(<<-RUBY.strip_indent) Time.parse('12:00').localtime('+03:00') ^^^^^ Do not use `Time.parse` without zone. Use `Time.zone.parse` instead. RUBY end it 'registers an offense for Time.parse.localtime' do expect_offense(<<-RUBY.strip_indent) Time.parse('12:00').localtime ^^^^^ Do not use `Time.parse` without zone. Use `Time.zone.parse` instead. RUBY end it 'registers an offense for Time.parse in return' do expect_offense(<<-RUBY.strip_indent) return Foo, Time.parse("2012-03-02 16:05:37") ^^^^^ Do not use `Time.parse` without zone. Use `Time.zone.parse` instead. RUBY end it 'accepts Time.zone.now' do expect_no_offenses('Time.zone.now') end it 'accepts Time.zone.today' do expect_no_offenses('Time.zone.today') end it 'accepts Time.zone.local' do expect_no_offenses('Time.zone.local(2012, 6, 10, 12, 00)') end it 'accepts Time.zone.parse' do expect_no_offenses('Time.zone.parse("2012-03-02 16:05:37")') end it 'accepts Time.zone.at' do expect_no_offenses('Time.zone.at(ts)') end it 'accepts Time.strptime' do expect_no_offenses('Time.strptime(datetime, format).in_time_zone') end it 'accepts Time.zone.strftime' do expect_no_offenses( 'Time.zone.strftime(time_string, "%Y-%m-%dT%H:%M:%S%z")' ) end it 'accepts Time.zone.parse.localtime' do expect_no_offenses("Time.zone.parse('12:00').localtime") end it 'accepts Time.zone.parse.localtime(offset)' do expect_no_offenses("Time.zone.parse('12:00').localtime('+03:00')") end it 'accepts Time.zone_default.now' do expect_no_offenses('Time.zone_default.now') end it 'accepts Time.zone_default.today' do expect_no_offenses('Time.zone_default.today') end it 'accepts Time.zone_default.local' do expect_no_offenses('Time.zone_default.local(2012, 6, 10, 12, 00)') end it 'accepts Time.find_zone(time_zone).now' do expect_no_offenses("Time.find_zone('EST').now") end it 'accepts Time.find_zone(time_zone).today' do expect_no_offenses("Time.find_zone('EST').today") end it 'accepts Time.find_zone(time_zone).local' do expect_no_offenses("Time.find_zone('EST').local(2012, 6, 10, 12, 00)") end it 'accepts Time.find_zone!(time_zone).now' do expect_no_offenses("Time.find_zone!('EST').now") end it 'accepts Time.find_zone!(time_zone).today' do expect_no_offenses("Time.find_zone!('EST').today") end it 'accepts Time.find_zone!(time_zone).local' do expect_no_offenses("Time.find_zone!('EST').local(2012, 6, 10, 12, 00)") end described_class::DANGEROUS_METHODS.each do |a_method| it "accepts Some::Time.#{a_method}" do inspect_source("Some::Time.#{a_method}") expect(cop.offenses.empty?).to be(true) end end end context 'when EnforcedStyle is "flexible"' do let(:cop_config) { { 'EnforcedStyle' => 'flexible' } } described_class::TIMECLASS.each do |klass| it "registers an offense for #{klass}.now" do inspect_source("#{klass}.now") expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to include('Use one of') expect(cop.offenses.first.message).to include('`Time.zone.now`') expect(cop.offenses.first.message).to include("`#{klass}.current`") described_class::ACCEPTED_METHODS.each do |a_method| expect(cop.offenses.first.message) .to include("#{klass}.now.#{a_method}") end end it "accepts #{klass}.current" do inspect_source("#{klass}.current") expect(cop.offenses.empty?).to be(true) end described_class::ACCEPTED_METHODS.each do |a_method| it "accepts #{klass}.now.#{a_method}" do inspect_source("#{klass}.now.#{a_method}") expect(cop.offenses.empty?).to be(true) end end it "accepts #{klass}.zone.now" do inspect_source("#{klass}.zone.now") expect(cop.offenses.empty?).to be(true) end it "accepts #{klass}.zone_default.now" do inspect_source("#{klass}.zone_default.now") expect(cop.offenses.empty?).to be(true) end it "accepts #{klass}.find_zone(time_zone).now" do inspect_source("#{klass}.find_zone('EST').now") expect(cop.offenses.empty?).to be(true) end it "accepts #{klass}.find_zone!(time_zone).now" do inspect_source("#{klass}.find_zone!('EST').now") expect(cop.offenses.empty?).to be(true) end described_class::DANGEROUS_METHODS.each do |a_method| it "accepts #{klass}.current.#{a_method}" do inspect_source("#{klass}.current.#{a_method}") expect(cop.offenses.empty?).to be(true) end end end it 'accepts Time.strftime.in_time_zone' do expect_no_offenses( 'Time.strftime(time_string, "%Y-%m-%dT%H:%M:%S%z").in_time_zone' ) end it 'accepts Time.parse.localtime(offset)' do expect_no_offenses("Time.parse('12:00').localtime('+03:00')") end it 'does not blow up in the presence of a single constant to inspect' do expect_no_offenses('A') end end end rubocop-0.52.1/spec/rubocop/cop/rails/uniq_before_pluck_spec.rb000066400000000000000000000061151322072016200245770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::UniqBeforePluck, :config do subject(:cop) { described_class.new(config) } shared_examples_for 'UniqBeforePluck cop' \ do |method, source, action, corrected = nil| if action == :correct it "finds the use of #{method} after pluck in #{source}" do inspect_source(source) expect(cop.messages).to eq(["Use `#{method}` before `pluck`."]) expect(cop.highlights).to eq([method]) corrected_source = corrected || "Model.#{method}.pluck(:id)" expect(autocorrect_source(source)).to eq(corrected_source) end else it "ignores pluck without errors in #{source}" do inspect_source(source) expect(cop.messages.empty?).to be(true) expect(cop.highlights.empty?).to be(true) expect(cop.offenses.empty?).to be(true) end end end shared_examples_for 'mode independent behavior' do |method| it_behaves_like 'UniqBeforePluck cop', method, "Model.pluck(:id).#{method}", :correct it_behaves_like 'UniqBeforePluck cop', method, ['Model.pluck(:id)', " .#{method}"], :correct it_behaves_like 'UniqBeforePluck cop', method, ['Model.pluck(:id).', " #{method}"], :correct context "#{method} before pluck" do it_behaves_like 'UniqBeforePluck cop', method, "Model.where(foo: 1).#{method}.pluck(:something)", :ignore end context "#{method} without a receiver" do it_behaves_like 'UniqBeforePluck cop', method, "#{method}.something", :ignore end context "#{method} without pluck" do it_behaves_like 'UniqBeforePluck cop', method, "Model.#{method}", :ignore end context "#{method} with a block" do it_behaves_like 'UniqBeforePluck cop', method, "Model.where(foo: 1).pluck(:id).#{method} { |k| k[0] }", :ignore end end shared_examples_for 'mode dependent offenses' do |method, action| it_behaves_like 'UniqBeforePluck cop', method, "Model.scope.pluck(:id).#{method}", action, "Model.scope.#{method}.pluck(:id)" it_behaves_like 'UniqBeforePluck cop', method, "instance.assoc.pluck(:id).#{method}", action, "instance.assoc.#{method}.pluck(:id)" end %w[uniq distinct].each do |method| context 'when the enforced mode is conservative' do let(:cop_config) do { 'EnforcedStyle' => 'conservative', 'AutoCorrect' => true } end it_behaves_like 'mode independent behavior', method it_behaves_like 'mode dependent offenses', method, :ignore end context 'when the enforced mode is aggressive' do let(:cop_config) do { 'EnforcedStyle' => 'aggressive', 'AutoCorrect' => true } end it_behaves_like 'mode independent behavior', method it_behaves_like 'mode dependent offenses', method, :correct end end end rubocop-0.52.1/spec/rubocop/cop/rails/unknown_env_spec.rb000066400000000000000000000014731322072016200234540ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::UnknownEnv, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Environments' => %w[ development production test ] } end it 'registers an offense for typo of environment name' do expect_offense(<<-RUBY) Rails.env.proudction? ^^^^^^^^^^^ Unknown environment `proudction?`. Did you mean `production?`? Rails.env.developpment? ^^^^^^^^^^^^^ Unknown environment `developpment?`. Did you mean `development?`? Rails.env.something? ^^^^^^^^^^ Unknown environment `something?`. RUBY end it 'accepts correct environment name' do expect_no_offenses(<<-RUBY) Rails.env.production? RUBY end end rubocop-0.52.1/spec/rubocop/cop/rails/validation_spec.rb000066400000000000000000000023071322072016200232340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Validation do subject(:cop) { described_class.new } described_class::BLACKLIST.each_with_index do |validation, number| it "registers an offense for #{validation}" do inspect_source("#{validation} :name") expect(cop.offenses.size).to eq(1) end it "outputs the correct message for #{validation}" do inspect_source("#{validation} :name") expect(cop.offenses.first.message) .to include(described_class::WHITELIST[number]) end end described_class::TYPES.each do |parameter| it "autocorrect validates_#{parameter}_of" do new_source = autocorrect_source( "validates_#{parameter}_of :full_name, :birth_date" ) expect(new_source).to eq( "validates :full_name, :birth_date, #{parameter}: true" ) end end it 'accepts new style validations' do expect_no_offenses('validates :name') end it 'autocorrect validates_length_of' do new_source = autocorrect_source( 'validates_numericality_of :age, minimum: 0, maximum: 122' ) expect(new_source).to eq( 'validates :age, numericality: { minimum: 0, maximum: 122 }' ) end end rubocop-0.52.1/spec/rubocop/cop/registry_spec.rb000066400000000000000000000117611322072016200216440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Registry do subject(:registry) { described_class.new(cops) } let(:cops) do stub_const('RuboCop::Cop::Test', Module.new) stub_const('RuboCop::Cop::RSpec', Module.new) module RuboCop module Cop module Test # Create another cop with a different namespace class IndentArray < Cop end end module RSpec # Define a dummy rspec cop which has special namespace inflection class Foo < Cop end end end end [ RuboCop::Cop::Lint::ConditionPosition, RuboCop::Cop::Lint::DuplicateMethods, RuboCop::Cop::Layout::IndentArray, RuboCop::Cop::Metrics::MethodLength, RuboCop::Cop::RSpec::Foo, RuboCop::Cop::Test::IndentArray ] end # `RuboCop::Cop::Cop` mutates its `registry` when inherited from. # This can introduce nondeterministic failures in other parts of the # specs if this mutation occurs before code that depends on this global cop # store. The workaround is to replace the global cop store with a temporary # store during these tests around do |test| registry = RuboCop::Cop::Cop.registry temporary_store = described_class.new(registry.cops) RuboCop::Cop::Cop.instance_variable_set(:@registry, temporary_store) test.run RuboCop::Cop::Cop.instance_variable_set(:@registry, registry) end it 'exposes cop departments' do expect(registry.departments).to eql(%i[Lint Layout Metrics RSpec Test]) end it 'can filter down to one type' do expect(registry.with_department(:Lint)) .to eq(described_class.new(cops.first(2))) end it 'can filter down to all but one type' do expect(registry.without_department(:Lint)) .to eq(described_class.new(cops.drop(2))) end context '#contains_cop_matching?' do it 'can find cops matching a given name' do expect(registry.contains_cop_matching?(['Test/IndentArray'])).to be(true) end it 'returns false for cops not included in the store' do expect(registry.contains_cop_matching?(['Style/NotReal'])).to be(false) end end context '#qualified_cop_name' do let(:origin) { '/app/.rubocop.yml' } it 'gives back already properly qualified names' do expect(registry.qualified_cop_name('Layout/IndentArray', origin)) .to eql('Layout/IndentArray') end it 'qualifies names without a namespace' do expect(registry.qualified_cop_name('MethodLength', origin)) .to eql('Metrics/MethodLength') end it 'qualifies names with the correct namespace' do expect(registry.qualified_cop_name('Foo', origin)).to eql('RSpec/Foo') end it 'emits a warning when namespace is incorrect' do warning = '/app/.rubocop.yml: Style/MethodLength has the wrong ' \ "namespace - should be Metrics\n" qualified = nil expect do qualified = registry.qualified_cop_name('Style/MethodLength', origin) end.to output(warning).to_stderr expect(qualified).to eql('Metrics/MethodLength') end it 'raises an error when a cop name is ambiguous' do expect { registry.qualified_cop_name('IndentArray', origin) } .to raise_error(RuboCop::Cop::AmbiguousCopName).with_message( 'Ambiguous cop name `IndentArray` used in /app/.rubocop.yml needs ' \ 'department qualifier. Did you mean Layout/IndentArray or ' \ 'Test/IndentArray?' ) end it 'returns the provided name if no namespace is found' do expect(registry.qualified_cop_name('NotReal', origin)).to eql('NotReal') end end it 'exposes a mapping of cop names to cop classes' do expect(registry.to_h).to eql( 'Lint/ConditionPosition' => [RuboCop::Cop::Lint::ConditionPosition], 'Lint/DuplicateMethods' => [RuboCop::Cop::Lint::DuplicateMethods], 'Layout/IndentArray' => [RuboCop::Cop::Layout::IndentArray], 'Metrics/MethodLength' => [RuboCop::Cop::Metrics::MethodLength], 'Test/IndentArray' => [RuboCop::Cop::Test::IndentArray], 'RSpec/Foo' => [RuboCop::Cop::RSpec::Foo] ) end context '#cops' do it 'exposes a list of cops' do expect(registry.cops).to eql(cops) end end it 'exposes the number of stored cops' do expect(registry.length).to be(6) end context '#enabled' do let(:config) do RuboCop::Config.new('Test/IndentArray' => { 'Enabled' => false }) end it 'selects cops which are enabled in the config' do expect(registry.enabled(config, [])).to eql(cops.first(5)) end it 'overrides config if :only includes the cop' do expect(registry.enabled(config, ['Test/IndentArray'])).to eql(cops) end end it 'exposes a list of cop names' do expect(registry.names).to eql( [ 'Lint/ConditionPosition', 'Lint/DuplicateMethods', 'Layout/IndentArray', 'Metrics/MethodLength', 'RSpec/Foo', 'Test/IndentArray' ] ) end end rubocop-0.52.1/spec/rubocop/cop/security/000077500000000000000000000000001322072016200202765ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/security/eval_spec.rb000066400000000000000000000041051322072016200225640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Security::Eval do subject(:cop) { described_class.new } it 'registers an offense for eval as function' do expect_offense(<<-RUBY.strip_indent) eval(something) ^^^^ The use of `eval` is a serious security risk. RUBY end it 'registers an offense for eval as command' do expect_offense(<<-RUBY.strip_indent) eval something ^^^^ The use of `eval` is a serious security risk. RUBY end it 'registers an offense `Binding#eval`' do expect_offense(<<-RUBY.strip_indent) binding.eval something ^^^^ The use of `eval` is a serious security risk. RUBY end it 'registers an offense for eval with string that has an interpolation' do expect_offense(<<-'RUBY'.strip_indent) eval "something#{foo}" ^^^^ The use of `eval` is a serious security risk. RUBY end it 'accepts eval as variable' do expect_no_offenses('eval = something') end it 'accepts eval as method' do expect_no_offenses('something.eval') end it 'accepts eval on a literal string' do expect_no_offenses('eval("puts 1")') end it 'accepts eval with no arguments' do expect_no_offenses('eval') end it 'accepts eval with a multiline string' do expect_no_offenses('eval "something\nsomething2"') end it 'accepts eval with a string that interpolates a literal' do expect_no_offenses('eval "something#{2}"') end context 'with an explicit binding, filename, and line number' do it 'registers an offense for eval as function' do expect_offense(<<-RUBY.strip_indent) eval(something, binding, "test.rb", 1) ^^^^ The use of `eval` is a serious security risk. RUBY end it 'registers an offense for eval as command' do expect_offense(<<-RUBY.strip_indent) eval something, binding, "test.rb", 1 ^^^^ The use of `eval` is a serious security risk. RUBY end it 'accepts eval on a literal string' do expect_no_offenses('eval("puts 1", binding, "test.rb", 1)') end end end rubocop-0.52.1/spec/rubocop/cop/security/json_load_spec.rb000066400000000000000000000021711322072016200236060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Security::JSONLoad, :config do subject(:cop) { described_class.new(config) } it 'registers an offense for JSON.load' do expect_offense(<<-RUBY.strip_indent) JSON.load(arg) ^^^^ Prefer `JSON.parse` over `JSON.load`. ::JSON.load(arg) ^^^^ Prefer `JSON.parse` over `JSON.load`. RUBY end it 'registers an offense for JSON.restore' do expect_offense(<<-RUBY.strip_indent) JSON.restore(arg) ^^^^^^^ Prefer `JSON.parse` over `JSON.restore`. ::JSON.restore(arg) ^^^^^^^ Prefer `JSON.parse` over `JSON.restore`. RUBY end it 'does not register an offense for JSON under another namespace' do expect_no_offenses(<<-RUBY.strip_indent) SomeModule::JSON.load(arg) SomeModule::JSON.restore(arg) RUBY end it 'allows JSON.parse' do expect_no_offenses(<<-RUBY.strip_indent) JSON.parse(arg) ::JSON.parse(arg) RUBY end it 'allows JSON.dump' do expect_no_offenses(<<-RUBY.strip_indent) JSON.dump(arg) ::JSON.dump(arg) RUBY end end rubocop-0.52.1/spec/rubocop/cop/security/marshal_load_spec.rb000066400000000000000000000026321322072016200242660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Security::MarshalLoad, :config do subject(:cop) { described_class.new(config) } it 'registers an offense for using Marshal.load' do expect_offense(<<-RUBY.strip_indent) Marshal.load('{}') ^^^^ Avoid using `Marshal.load`. ::Marshal.load('{}') ^^^^ Avoid using `Marshal.load`. RUBY end it 'registers an offense for using Marshal.restore' do expect_offense(<<-RUBY.strip_indent) Marshal.restore('{}') ^^^^^^^ Avoid using `Marshal.restore`. ::Marshal.restore('{}') ^^^^^^^ Avoid using `Marshal.restore`. RUBY end it 'does not register an offense for Marshal.dump' do expect_no_offenses(<<-RUBY.strip_indent) Marshal.dump({}) ::Marshal.dump({}) RUBY end it 'does not register an offense Marshal methods under another namespace' do expect_no_offenses(<<-RUBY.strip_indent) SomeNamespace::Marshal.load('') SomeNamespace::Marshal.restore('') SomeNamespace::Marshal.dump('') ::SomeNamespace::Marshal.load('') ::SomeNamespace::Marshal.restore('') ::SomeNamespace::Marshal.dump('') RUBY end it 'allows using dangerous Marshal methods for deep cloning' do expect_no_offenses(<<-RUBY.strip_indent) Marshal.load(Marshal.dump({})) Marshal.restore(Marshal.dump({})) RUBY end end rubocop-0.52.1/spec/rubocop/cop/security/yaml_load_spec.rb000066400000000000000000000020361322072016200235770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Security::YAMLLoad, :config do subject(:cop) { described_class.new(config) } it 'does not register an offense for YAML.dump' do expect_no_offenses(<<-RUBY.strip_indent) YAML.dump("foo") ::YAML.dump("foo") Module::YAML.dump("foo") RUBY end it 'does not register an offense for YAML.load under a different namespace' do expect_no_offenses('Module::YAML.load("foo")') end it 'registers an offense for load with a literal string' do expect_offense(<<-RUBY.strip_indent) YAML.load("--- foo") ^^^^ Prefer using `YAML.safe_load` over `YAML.load`. RUBY end it 'registers an offense for a fully qualified ::YAML.load' do expect_offense(<<-RUBY.strip_indent) ::YAML.load("--- foo") ^^^^ Prefer using `YAML.safe_load` over `YAML.load`. RUBY end it 'autocorrects load to safe_load' do expect(autocorrect_source('::YAML.load("-- foo")')).to eq( '::YAML.safe_load("-- foo")' ) end end rubocop-0.52.1/spec/rubocop/cop/severity_spec.rb000066400000000000000000000046501322072016200216450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Severity do let(:refactor) { described_class.new(:refactor) } let(:convention) { described_class.new(:convention) } let(:warning) { described_class.new(:warning) } let(:error) { described_class.new(:error) } let(:fatal) { described_class.new(:fatal) } it 'has a few required attributes' do expect(convention.name).to eq(:convention) end it 'overrides #to_s' do expect(convention.to_s).to eq('convention') end it 'redefines == to compare severities' do expect(convention).to eq(:convention) expect(convention).to eq(described_class.new(:convention)) expect(convention).not_to eq(:warning) end it 'is frozen' do expect(convention.frozen?).to be(true) end describe '#code' do describe 'refactor' do it { expect(refactor.code).to eq('R') } end describe 'convention' do it { expect(convention.code).to eq('C') } end describe 'warning' do it { expect(warning.code).to eq('W') } end describe 'error' do it { expect(error.code).to eq('E') } end describe 'fatal' do it { expect(fatal.code).to eq('F') } end end describe '#level' do describe 'refactor' do it { expect(refactor.level).to eq(1) } end describe 'convention' do it { expect(convention.level).to eq(2) } end describe 'warning' do it { expect(warning.level).to eq(3) } end describe 'error' do it { expect(error.level).to eq(4) } end describe 'fatal' do it { expect(fatal.level).to eq(5) } end end describe 'constructs from code' do describe 'R' do it { expect(described_class.new('R')).to eq(refactor) } end describe 'C' do it { expect(described_class.new('C')).to eq(convention) } end describe 'W' do it { expect(described_class.new('W')).to eq(warning) } end describe 'E' do it { expect(described_class.new('E')).to eq(error) } end describe 'F' do it { expect(described_class.new('F')).to eq(fatal) } end end describe 'Comparable' do describe 'refactor' do it { expect(refactor).to be < convention } end describe 'convention' do it { expect(convention).to be < warning } end describe 'warning' do it { expect(warning).to be < error } end describe 'error' do it { expect(error).to be < fatal } end end end rubocop-0.52.1/spec/rubocop/cop/style/000077500000000000000000000000001322072016200175675ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/style/alias_spec.rb000066400000000000000000000122131322072016200222160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Alias, :config do subject(:cop) { described_class.new(config) } context 'when EnforcedStyle is prefer_alias_method' do let(:cop_config) { { 'EnforcedStyle' => 'prefer_alias_method' } } it 'registers an offense for alias with symbol args' do expect_offense(<<-RUBY.strip_indent) alias :ala :bala ^^^^^ Use `alias_method` instead of `alias`. RUBY end it 'autocorrects alias with symbol args' do corrected = autocorrect_source('alias :ala :bala') expect(corrected).to eq 'alias_method :ala, :bala' end it 'registers an offense for alias with bareword args' do expect_offense(<<-RUBY.strip_indent) alias ala bala ^^^^^ Use `alias_method` instead of `alias`. RUBY end it 'autocorrects alias with bareword args' do corrected = autocorrect_source('alias ala bala') expect(corrected).to eq 'alias_method :ala, :bala' end it 'does not register an offense for alias_method' do expect_no_offenses('alias_method :ala, :bala') end it 'does not register an offense for alias with gvars' do expect_no_offenses('alias $ala $bala') end it 'does not register an offense for alias in an instance_eval block' do expect_no_offenses(<<-RUBY.strip_indent) module M def foo instance_eval { alias bar baz } end end RUBY end end context 'when EnforcedStyle is prefer_alias' do let(:cop_config) { { 'EnforcedStyle' => 'prefer_alias' } } it 'registers an offense for alias with symbol args' do expect_offense(<<-RUBY.strip_indent) alias :ala :bala ^^^^^^^^^^ Use `alias ala bala` instead of `alias :ala :bala`. RUBY end it 'autocorrects alias with symbol args' do corrected = autocorrect_source(['alias :ala :bala']) expect(corrected).to eq 'alias ala bala' end it 'does not register an offense for alias with bareword args' do expect_no_offenses('alias ala bala') end it 'registers an offense for alias_method at the top level' do expect_offense(<<-RUBY.strip_indent) alias_method :ala, :bala ^^^^^^^^^^^^ Use `alias` instead of `alias_method` at the top level. RUBY end it 'autocorrects alias_method at the top level' do corrected = autocorrect_source('alias_method :ala, :bala') expect(corrected).to eq 'alias ala bala' end it 'registers an offense for alias_method in a class block' do expect_offense(<<-RUBY.strip_indent) class C alias_method :ala, :bala ^^^^^^^^^^^^ Use `alias` instead of `alias_method` in a class body. end RUBY end it 'autocorrects alias_method in a class block' do corrected = autocorrect_source(<<-RUBY.strip_indent) class C alias_method :ala, :bala end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) class C alias ala bala end RUBY end it 'registers an offense for alias_method in a module block' do expect_offense(<<-RUBY.strip_indent) module M alias_method :ala, :bala ^^^^^^^^^^^^ Use `alias` instead of `alias_method` in a module body. end RUBY end it 'autocorrects alias_method in a module block' do corrected = autocorrect_source(<<-RUBY.strip_indent) module M alias_method :ala, :bala end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) module M alias ala bala end RUBY end it 'does not register an offense for alias_method with explicit receiver' do expect_no_offenses(<<-RUBY.strip_indent) class C receiver.alias_method :ala, :bala end RUBY end it 'does not register an offense for alias_method in a method def' do expect_no_offenses(<<-RUBY.strip_indent) def method alias_method :ala, :bala end RUBY end it 'does not register an offense for alias_method in self.method def' do expect_no_offenses(<<-RUBY.strip_indent) def self.method alias_method :ala, :bala end RUBY end it 'does not register an offense for alias_method in a block' do expect_no_offenses(<<-RUBY.strip_indent) dsl_method do alias_method :ala, :bala end RUBY end it 'does not register an offense for alias_method with non-literal '\ 'argument' do expect_no_offenses(<<-RUBY.strip_indent) alias_method :bar, FOO RUBY end it 'does not register an offense for alias_method with non-literal ' \ 'argument' do expect_no_offenses(<<-RUBY.strip_indent) alias_method :baz, foo.bar RUBY end it 'does not register an offense for alias in an instance_eval block' do expect_no_offenses(<<-RUBY.strip_indent) module M def foo instance_eval { alias bar baz } end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/and_or_spec.rb000066400000000000000000000323061322072016200223740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::AndOr, :config do context 'when style is conditionals' do cop_config = { 'EnforcedStyle' => 'conditionals' } subject(:cop) { described_class.new(config) } let(:cop_config) { cop_config } %w[and or].each do |operator| it "accepts \"#{operator}\" outside of conditional" do inspect_source("x = a + b #{operator} return x") expect(cop.offenses.empty?).to be(true) end { 'if' => 'if %s; %s; end', 'while' => 'while %s; %s; end', 'until' => 'until %s; %s; end', 'post-conditional while' => 'begin; %s; end while %s', 'post-conditional until' => 'begin; %s; end until %s' }.each do |type, snippet_format| it "registers an offense for \"#{operator}\" in #{type} conditional" do elements = { condition: "a #{operator} b", body: 'do_something' } source = format(snippet_format, elements) inspect_source(source) expect(cop.offenses.size).to eq(1) end it "accepts \"#{operator}\" in #{type} body" do elements = { condition: 'some_condition', body: "do_something #{operator} return" } source = format(snippet_format, elements) inspect_source(source) expect(cop.offenses.empty?).to be(true) end end end %w[&& ||].each do |operator| it "accepts #{operator} inside of conditional" do inspect_source("test if a #{operator} b") expect(cop.offenses.empty?).to be(true) end it "accepts #{operator} outside of conditional" do inspect_source("x = a #{operator} b") expect(cop.offenses.empty?).to be(true) end end end context 'when style is always' do cop_config = { 'EnforcedStyle' => 'always' } subject(:cop) { described_class.new(config) } let(:cop_config) { cop_config } it 'registers an offense for "or"' do expect_offense(<<-RUBY.strip_indent) test if a or b ^^ Use `||` instead of `or`. RUBY end it 'registers an offense for "and"' do expect_offense(<<-RUBY.strip_indent) test if a and b ^^^ Use `&&` instead of `and`. RUBY end it 'accepts ||' do expect_no_offenses('test if a || b') end it 'accepts &&' do expect_no_offenses('test if a && b') end it 'auto-corrects "and" with &&' do new_source = autocorrect_source('true and false') expect(new_source).to eq('true && false') end it 'auto-corrects "or" with ||' do new_source = autocorrect_source(<<-RUBY.strip_indent) x = 12345 true or false RUBY expect(new_source).to eq(<<-RUBY.strip_indent) x = 12345 true || false RUBY end it 'auto-corrects "or" with || inside def' do new_source = autocorrect_source(<<-RUBY.strip_indent) def z(a, b) return true if a or b end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def z(a, b) return true if a || b end RUBY end it 'autocorrects "or" with an assignment on the left' do src = "x = y or teststring.include? 'b'" new_source = autocorrect_source(src) expect(new_source).to eq("(x = y) || teststring.include?('b')") end it 'autocorrects "or" with an assignment on the right' do src = "teststring.include? 'b' or x = y" new_source = autocorrect_source(src) expect(new_source).to eq("teststring.include?('b') || (x = y)") end it 'autocorrects "and" with an assignment and return on either side' do src = 'x = a + b and return x' new_source = autocorrect_source(src) expect(new_source).to eq('(x = a + b) && (return x)') end it 'autocorrects "and" with an Enumerable accessor on either side' do src = 'foo[:bar] and foo[:baz]' new_source = autocorrect_source(src) expect(new_source).to eq('foo[:bar] && foo[:baz]') end it 'warns on short-circuit (and)' do expect_offense(<<-RUBY.strip_indent) x = a + b and return x ^^^ Use `&&` instead of `and`. RUBY end it 'also warns on non short-circuit (and)' do expect_offense(<<-RUBY.strip_indent) x = a + b if a and b ^^^ Use `&&` instead of `and`. RUBY end it 'also warns on non short-circuit (and) (unless)' do expect_offense(<<-RUBY.strip_indent) x = a + b unless a and b ^^^ Use `&&` instead of `and`. RUBY end it 'warns on short-circuit (or)' do expect_offense(<<-RUBY.strip_indent) x = a + b or return x ^^ Use `||` instead of `or`. RUBY end it 'also warns on non short-circuit (or)' do expect_offense(<<-RUBY.strip_indent) x = a + b if a or b ^^ Use `||` instead of `or`. RUBY end it 'also warns on non short-circuit (or) (unless)' do expect_offense(<<-RUBY.strip_indent) x = a + b unless a or b ^^ Use `||` instead of `or`. RUBY end it 'also warns on while (or)' do expect_offense(<<-RUBY.strip_indent) x = a + b while a or b ^^ Use `||` instead of `or`. RUBY end it 'also warns on until (or)' do expect_offense(<<-RUBY.strip_indent) x = a + b until a or b ^^ Use `||` instead of `or`. RUBY end it 'auto-corrects "or" with || in method calls' do new_source = autocorrect_source('method a or b') expect(new_source).to eq('method(a) || b') end it 'auto-corrects "or" with || in method calls (2)' do new_source = autocorrect_source('method a,b or b') expect(new_source).to eq('method(a,b) || b') end it 'auto-corrects "or" with || in method calls (3)' do new_source = autocorrect_source('obj.method a or b') expect(new_source).to eq('obj.method(a) || b') end it 'auto-corrects "or" with || in method calls (4)' do new_source = autocorrect_source('obj.method a,b or b') expect(new_source).to eq('obj.method(a,b) || b') end it 'auto-corrects "or" with || and doesn\'t add extra parentheses' do new_source = autocorrect_source('method(a, b) or b') expect(new_source).to eq('method(a, b) || b') end it 'auto-corrects "or" with || and adds parentheses to expr' do new_source = autocorrect_source('b or method a,b') expect(new_source).to eq('b || method(a,b)') end it 'auto-corrects "and" with && in method calls' do new_source = autocorrect_source('method a and b') expect(new_source).to eq('method(a) && b') end it 'auto-corrects "and" with && in method calls (2)' do new_source = autocorrect_source('method a,b and b') expect(new_source).to eq('method(a,b) && b') end it 'auto-corrects "and" with && in method calls (3)' do new_source = autocorrect_source('obj.method a and b') expect(new_source).to eq('obj.method(a) && b') end it 'auto-corrects "and" with && in method calls (4)' do new_source = autocorrect_source('obj.method a,b and b') expect(new_source).to eq('obj.method(a,b) && b') end it 'auto-corrects "and" with && and doesn\'t add extra parentheses' do new_source = autocorrect_source('method(a, b) and b') expect(new_source).to eq('method(a, b) && b') end it 'auto-corrects "and" with && and adds parentheses to expr' do new_source = autocorrect_source('b and method a,b') expect(new_source).to eq('b && method(a,b)') end context 'with !obj.method arg on right' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('x and !obj.method arg') expect(new_source).to eq('x && !obj.method(arg)') end end context 'with !obj.method arg on left' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('!obj.method arg and x') expect(new_source).to eq('!obj.method(arg) && x') end end context 'with obj.method = arg on left' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('obj.method = arg and x') expect(new_source).to eq('(obj.method = arg) && x') end end context 'with obj.method= arg on left' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('obj.method= arg and x') expect(new_source).to eq('(obj.method= arg) && x') end end context 'with predicate method with arg without space on right' do it 'autocorrects "or" with || and adds parens' do new_source = autocorrect_source('false or 3.is_a?Integer') expect(new_source).to eq('false || 3.is_a?(Integer)') end it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('false and 3.is_a?Integer') expect(new_source).to eq('false && 3.is_a?(Integer)') end end context 'with two predicate methods with args without spaces on right' do it 'autocorrects "or" with || and adds parens' do new_source = autocorrect_source("'1'.is_a?Integer " \ 'or 1.is_a?Integer') expect(new_source).to eq('\'1\'.is_a?(Integer) || 1.is_a?(Integer)') end it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source("'1'.is_a?Integer and" \ ' 1.is_a?Integer') expect(new_source).to eq('\'1\'.is_a?(Integer) && 1.is_a?(Integer)') end end context 'with one predicate method without space on right and another ' \ 'method' do it 'autocorrects "or" with || and adds parens' do new_source = autocorrect_source("'1'.is_a?Integer or" \ ' 1.is_a? Integer') expect(new_source).to eq("'1'.is_a?(Integer) || 1.is_a?(Integer)") end it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source("'1'.is_a?Integer " \ 'and 1.is_a? Integer') expect(new_source).to eq('\'1\'.is_a?(Integer) && 1.is_a?(Integer)') end end context 'with `not` expression on right' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('x and not arg') expect(new_source).to eq('x && (not arg)') end end context 'with `not` expression on left' do it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source('not arg and x') expect(new_source).to eq('(not arg) && x') end end context 'with !variable on left' do it "doesn't crash and burn" do # regression test; see GH issue 2482 expect_offense(<<-RUBY.strip_indent) !var or var.empty? ^^ Use `||` instead of `or`. RUBY end end context 'within a nested begin node' do # regression test; see GH issue 2531 it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source(<<-RUBY.strip_indent) def x end def y a = b and a.c end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def x end def y (a = b) && a.c end RUBY end end context 'when left hand side is a comparison method' do # Regression: https://github.com/bbatsov/rubocop/issues/4451 it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo == bar and baz RUBY expect(new_source).to eq(<<-RUBY.strip_indent) (foo == bar) && baz RUBY end end context 'within a nested begin node with one child only' do # regression test; see GH issue 2531 it 'autocorrects "and" with && and adds parens' do new_source = autocorrect_source(<<-RUBY.strip_indent) (def y a = b and a.c end) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) (def y (a = b) && a.c end) RUBY end end context 'with a file which contains __FILE__' do let(:source) do <<-RUBY.strip_indent APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) system('bundle check') or system!('bundle install') RUBY end # regression test; see GH issue 2609 it 'autocorrects "or" with ||' do new_source = autocorrect_source(source) expect(new_source).to eq( <<-RUBY.strip_indent APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) system('bundle check') || system!('bundle install') RUBY ) end end end end rubocop-0.52.1/spec/rubocop/cop/style/array_join_spec.rb000066400000000000000000000022051322072016200232620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ArrayJoin do subject(:cop) { described_class.new } it 'registers an offense for an array followed by string' do expect_offense(<<-RUBY.strip_indent) %w(one two three) * ", " ^ Favor `Array#join` over `Array#*`. RUBY end it "autocorrects '*' to 'join' when there are spaces" do corrected = autocorrect_source('%w(one two three) * ", "') expect(corrected).to eq '%w(one two three).join(", ")' end it "autocorrects '*' to 'join' when there are no spaces" do corrected = autocorrect_source('%w(one two three)*", "') expect(corrected).to eq '%w(one two three).join(", ")' end it "autocorrects '*' to 'join' when setting to a variable" do corrected = autocorrect_source('foo = %w(one two three)*", "') expect(corrected).to eq 'foo = %w(one two three).join(", ")' end it 'does not register an offense for numbers' do expect_no_offenses('%w(one two three) * 4') end it 'does not register an offense for ambiguous cases' do expect_no_offenses('%w(one two three) * test') end end rubocop-0.52.1/spec/rubocop/cop/style/ascii_comments_spec.rb000066400000000000000000000022511322072016200241230ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::AsciiComments do subject(:cop) { described_class.new } it 'registers an offense for a comment with non-ascii chars' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 # 这是什么? ^^^^^ Use only ascii symbols in comments. RUBY end it 'registers an offense for comments with mixed chars' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 # foo ∂ bar ^ Use only ascii symbols in comments. RUBY end it 'accepts comments with only ascii chars' do expect_no_offenses('# AZaz1@$%~,;*_`|') end context 'when certain non-ascii chars are allowed', :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowedChars' => ['∂'] } } it 'accepts comment with allowed non-ascii chars' do expect_no_offenses('# foo ∂ bar') end it 'registers an offense for comments with non-allowed non-ascii chars' do expect_offense(<<-RUBY.strip_indent) # encoding: utf-8 # 这是什么? ^^^^^ Use only ascii symbols in comments. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/attr_spec.rb000066400000000000000000000040231322072016200220770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Attr do subject(:cop) { described_class.new } it 'registers an offense attr' do expect_offense(<<-RUBY.strip_indent) class SomeClass attr :name ^^^^ Do not use `attr`. Use `attr_reader` instead. end RUBY end it 'accepts attr when it does not take arguments' do expect_no_offenses('func(attr)') end it 'accepts attr when it has a receiver' do expect_no_offenses('x.attr arg') end context 'auto-corrects' do it 'attr to attr_reader' do new_source = autocorrect_source('attr :name') expect(new_source).to eq('attr_reader :name') end it 'attr, false to attr_reader' do new_source = autocorrect_source('attr :name, false') expect(new_source).to eq('attr_reader :name') end it 'attr :name, true to attr_accessor :name' do new_source = autocorrect_source('attr :name, true') expect(new_source).to eq('attr_accessor :name') end it 'attr with multiple names to attr_reader' do new_source = autocorrect_source('attr :foo, :bar') expect(new_source).to eq('attr_reader :foo, :bar') end end context 'offense message' do let(:msg_reader) { 'Do not use `attr`. Use `attr_reader` instead.' } let(:msg_accessor) { 'Do not use `attr`. Use `attr_accessor` instead.' } it 'for attr :name suggests to use attr_reader' do inspect_source('attr :name') expect(cop.offenses.first.message).to eq(msg_reader) end it 'for attr :name, false suggests to use attr_reader' do inspect_source('attr :name, false') expect(cop.offenses.first.message).to eq(msg_reader) end it 'for attr :name, true suggests to use attr_accessor' do inspect_source('attr :name, true') expect(cop.offenses.first.message).to eq(msg_accessor) end it 'for attr with multiple names suggests to use attr_reader' do inspect_source('attr :foo, :bar') expect(cop.offenses.first.message).to eq(msg_reader) end end end rubocop-0.52.1/spec/rubocop/cop/style/auto_resource_cleanup_spec.rb000066400000000000000000000013541322072016200255170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::AutoResourceCleanup do subject(:cop) { described_class.new } it 'registers an offense for File.open without block' do expect_offense(<<-RUBY.strip_indent) File.open("filename") ^^^^^^^^^^^^^^^^^^^^^ Use the block version of `File.open`. RUBY end it 'does not register an offense for File.open with block' do expect_no_offenses('File.open("file") { |f| something }') end it 'does not register an offense for File.open with block-pass' do expect_no_offenses('File.open("file", &:read)') end it 'does not register an offense for File.open with immediate close' do expect_no_offenses('File.open("file", "w", 0o777).close') end end rubocop-0.52.1/spec/rubocop/cop/style/bare_percent_literals_spec.rb000066400000000000000000000055771322072016200254740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::BarePercentLiterals, :config do subject(:cop) { described_class.new(config) } shared_examples 'accepts other delimiters' do it 'accepts __FILE__' do expect_no_offenses('__FILE__') end it 'accepts regular expressions' do expect_no_offenses('/%Q?/') end it 'accepts ""' do expect_no_offenses('""') end it 'accepts "" string with interpolation' do expect_no_offenses('"#{file}hi"') end it "accepts ''" do expect_no_offenses("'hi'") end it 'accepts %q' do expect_no_offenses('%q(hi)') end it 'accepts heredoc' do expect_no_offenses(<<-RUBY.strip_indent) func < 'percent_q' } } context 'and strings are static' do it 'registers an offense for %()' do expect_offense(<<-RUBY.strip_indent) %(hi) ^^ Use `%Q` instead of `%`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('%(hi)') expect(new_source).to eq('%Q(hi)') end it 'accepts %Q()' do expect_no_offenses('%Q(hi)') end include_examples 'accepts other delimiters' end context 'and strings are dynamic' do it 'registers an offense for %()' do expect_offense(<<-'RUBY'.strip_indent) %(#{x}) ^^ Use `%Q` instead of `%`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('%(#{x})') expect(new_source).to eq('%Q(#{x})') end it 'accepts %Q()' do expect_no_offenses('%Q(#{x})') end include_examples 'accepts other delimiters' end end context 'when EnforcedStyle is bare_percent' do let(:cop_config) { { 'EnforcedStyle' => 'bare_percent' } } context 'and strings are static' do it 'registers an offense for %Q()' do expect_offense(<<-RUBY.strip_indent) %Q(hi) ^^^ Use `%` instead of `%Q`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('%Q(hi)') expect(new_source).to eq('%(hi)') end it 'accepts %()' do expect_no_offenses('%(hi)') end include_examples 'accepts other delimiters' end context 'and strings are dynamic' do it 'registers an offense for %Q()' do expect_offense(<<-'RUBY'.strip_indent) %Q(#{x}) ^^^ Use `%` instead of `%Q`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('%Q(#{x})') expect(new_source).to eq('%(#{x})') end it 'accepts %()' do expect_no_offenses('%(#{x})') end include_examples 'accepts other delimiters' end end end rubocop-0.52.1/spec/rubocop/cop/style/begin_block_spec.rb000066400000000000000000000004151322072016200233640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::BeginBlock do subject(:cop) { described_class.new } it 'reports an offense for a BEGIN block' do src = 'BEGIN { test }' inspect_source(src) expect(cop.offenses.size).to eq(1) end end rubocop-0.52.1/spec/rubocop/cop/style/block_comments_spec.rb000066400000000000000000000020011322072016200241160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::BlockComments do subject(:cop) { described_class.new } it 'registers an offense for block comments' do expect_offense(<<-RUBY.strip_indent) =begin ^^^^^^ Do not use block comments. comment =end RUBY end it 'accepts regular comments' do expect_no_offenses('# comment') end it 'auto-corrects a block comment into a regular comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) =begin comment line 1 comment line 2 =end def foo end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # comment line 1 # # comment line 2 def foo end RUBY end it 'auto-corrects an empty block comment by removing it' do new_source = autocorrect_source(<<-RUBY.strip_indent) =begin =end def foo end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/block_delimiters_spec.rb000066400000000000000000000316551322072016200244530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::BlockDelimiters, :config do subject(:cop) { described_class.new(config) } shared_examples 'syntactic styles' do it 'registers an offense for a single line block with do-end' do inspect_source('each do |x| end') expect(cop.messages) .to eq(['Prefer `{...}` over `do...end` for single-line blocks.']) end it 'accepts a single line block with braces' do expect_no_offenses('each { |x| }') end it 'accepts a multi-line block with do-end' do expect_no_offenses(<<-RUBY.strip_indent) each do |x| end RUBY end it 'accepts a multi-line block that needs braces to be valid ruby' do inspect_source(<<-RUBY.strip_indent) puts [1, 2, 3].map { |n| n * n }, 1 RUBY expect(cop.messages.empty?).to be(true) end end context 'Semantic style' do cop_config = { 'EnforcedStyle' => 'semantic', 'ProceduralMethods' => %w[tap], 'FunctionalMethods' => %w[let], 'IgnoredMethods' => %w[lambda] } let(:cop_config) { cop_config } it 'accepts a multi-line block with braces if the return value is ' \ 'assigned' do inspect_source(<<-RUBY.strip_indent) foo = map { |x| x } RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a multi-line block with braces if it is the return value ' \ 'of its scope' do inspect_source(<<-RUBY.strip_indent) block do map { |x| x } end RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a multi-line block with braces when passed to a method' do expect_no_offenses(<<-RUBY.strip_indent) puts map { |x| x } RUBY end it 'accepts a multi-line block with braces when chained' do expect_no_offenses(<<-RUBY.strip_indent) map { |x| x }.inspect RUBY end it 'accepts a multi-line block with braces when passed to a known ' \ 'functional method' do inspect_source(<<-RUBY.strip_indent) let(:foo) { x } RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for a multi-line block with braces if the ' \ 'return value is not used' do inspect_source(<<-RUBY.strip_indent) each { |x| x } RUBY expect(cop.messages) .to eq(['Prefer `do...end` over `{...}` for procedural blocks.']) end it 'registers an offense for a multi-line block with do-end if the ' \ 'return value is assigned' do inspect_source(<<-RUBY.strip_indent) foo = map do |x| x end RUBY expect(cop.messages) .to eq(['Prefer `{...}` over `do...end` for functional blocks.']) end it 'registers an offense for a multi-line block with do-end if the ' \ 'return value is passed to a method' do inspect_source(<<-RUBY.strip_indent) puts (map do |x| x end) RUBY expect(cop.messages) .to eq(['Prefer `{...}` over `do...end` for functional blocks.']) end it 'accepts a multi-line block with do-end if it is the return value ' \ 'of its scope' do inspect_source(<<-RUBY.strip_indent) block do map do |x| x end end RUBY expect(cop.messages.empty?).to be(true) end it 'accepts a single line block with {} if used in an if statement' do expect_no_offenses('return if any? { |x| x }') end it 'accepts a single line block with {} if used in a logical or' do expect_no_offenses('any? { |c| c } || foo') end it 'accepts a single line block with {} if used in a logical and' do expect_no_offenses('any? { |c| c } && foo') end it 'accepts a single line block with {} if used in an array' do expect_no_offenses('[detect { true }, other]') end it 'accepts a single line block with {} if used in an irange' do expect_no_offenses('detect { true }..other') end it 'accepts a single line block with {} if used in an erange' do expect_no_offenses('detect { true }...other') end it 'accepts a multi-line functional block with do-end if it is ' \ 'a known procedural method' do inspect_source(<<-RUBY.strip_indent) foo = bar.tap do |x| x.age = 3 end RUBY expect(cop.messages.empty?).to be(true) end it 'accepts a multi-line functional block with do-end if it is ' \ 'an ignored method' do inspect_source(<<-RUBY.strip_indent) foo = lambda do puts 42 end RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense for a single line procedural block' do expect_offense(<<-RUBY.strip_indent) each { |x| puts x } ^ Prefer `do...end` over `{...}` for procedural blocks. RUBY end it 'accepts a single line block with do-end if it is procedural' do expect_no_offenses('each do |x| puts x; end') end context 'with a procedural block' do let(:corrected_source) do <<-RUBY.strip_indent each do |x| x end RUBY end it 'auto-corrects { and } to do and end' do source = <<-RUBY.strip_indent each { |x| x } RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected_source) end it 'auto-corrects { and } to do and end with appropriate spacing' do source = <<-RUBY.strip_indent each {|x| x } RUBY new_source = autocorrect_source(source) expect(new_source).to eq(corrected_source) end end it 'does not auto-correct {} to do-end if it is a known functional ' \ 'method' do source = <<-RUBY.strip_indent let(:foo) { |x| x } RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not autocorrect do-end to {} if it is a known procedural ' \ 'method' do source = <<-RUBY.strip_indent foo = bar.tap do |x| x.age = 1 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'auto-corrects do-end to {} if it is a functional block' do source = <<-RUBY.strip_indent foo = map do |x| x end RUBY expected_source = <<-RUBY.strip_indent foo = map { |x| x } RUBY new_source = autocorrect_source(source) expect(new_source).to eq(expected_source) end it 'auto-corrects do-end to {} with appropriate spacing' do source = <<-RUBY.strip_indent foo = map do|x| x end RUBY expected_source = <<-RUBY.strip_indent foo = map { |x| x } RUBY new_source = autocorrect_source(source) expect(new_source).to eq(expected_source) end it 'auto-corrects do-end to {} if it is a functional block and does ' \ 'not change the meaning' do source = <<-RUBY.strip_indent puts (map do |x| x end) RUBY expected_source = <<-RUBY.strip_indent puts (map { |x| x }) RUBY new_source = autocorrect_source(source) expect(new_source).to eq(expected_source) end end context 'line count-based style' do cop_config = { 'EnforcedStyle' => 'line_count_based', 'IgnoredMethods' => %w[proc] } let(:cop_config) { cop_config } include_examples 'syntactic styles' it 'auto-corrects do and end for single line blocks to { and }' do new_source = autocorrect_source('block do |x| end') expect(new_source).to eq('block { |x| }') end it 'does not auto-correct do-end if {} would change the meaning' do src = "s.subspec 'Subspec' do |sp| end" new_source = autocorrect_source(src) expect(new_source).to eq(src) end it 'does not auto-correct {} if do-end would change the meaning' do src = <<-RUBY.strip_indent foo :bar, :baz, qux: lambda { |a| bar a } RUBY new_source = autocorrect_source(src) expect(new_source).to eq(src) end context 'when there are braces around a multi-line block' do it 'registers an offense in the simple case' do expect_offense(<<-RUBY.strip_indent) each { |x| ^ Avoid using `{...}` for multi-line blocks. } RUBY end it 'accepts braces if do-end would change the meaning' do src = <<-RUBY.strip_indent scope :foo, lambda { |f| where(condition: "value") } expect { something }.to raise_error(ErrorClass) { |error| # ... } expect { x }.to change { Counter.count }.from(0).to(1) cr.stubs client: mock { expects(:email_disabled=).with(true) expects :save } RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'accepts a multi-line functional block with {} if it is ' \ 'an ignored method' do inspect_source(<<-RUBY.strip_indent) foo = proc { puts 42 } RUBY expect(cop.messages.empty?).to be(true) end it 'registers an offense for braces if do-end would not change ' \ 'the meaning' do src = <<-RUBY.strip_indent scope :foo, (lambda { |f| where(condition: "value") }) expect { something }.to(raise_error(ErrorClass) { |error| # ... }) RUBY inspect_source(src) expect(cop.offenses.size).to eq(2) end it 'can handle special method names such as []= and done?' do src = <<-RUBY.strip_indent h2[k2] = Hash.new { |h3,k3| h3[k3] = 0 } x = done? list.reject { |e| e.nil? } RUBY inspect_source(src) expect(cop.messages) .to eq(['Avoid using `{...}` for multi-line blocks.']) end it 'auto-corrects { and } to do and end' do source = <<-RUBY.strip_indent each{ |x| some_method other_method } RUBY expected_source = <<-RUBY.strip_indent each do |x| some_method other_method end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(expected_source) end it 'auto-corrects adjacent curly braces correctly' do source = <<-RUBY.strip_indent (0..3).each { |a| a.times { puts a }} RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) (0..3).each do |a| a.times do puts a end end RUBY end it 'does not auto-correct {} if do-end would introduce a syntax error' do src = <<-RUBY.strip_indent my_method :arg1, arg2: proc { something }, arg3: :another_value RUBY new_source = autocorrect_source(src) expect(new_source).to eq(src) end end end context 'braces for chaining style' do cop_config = { 'EnforcedStyle' => 'braces_for_chaining', 'IgnoredMethods' => %w[proc] } let(:cop_config) { cop_config } include_examples 'syntactic styles' it 'registers an offense for multi-line chained do-end blocks' do expect_offense(<<-RUBY.strip_indent) each do |x| ^^ Prefer `{...}` over `do...end` for multi-line chained blocks. end.map(&:to_s) RUBY end it 'auto-corrects do-end for chained blocks' do src = <<-RUBY.strip_indent each do |x| end.map(&:to_s) RUBY new_source = autocorrect_source(src) expect(new_source).to eq(<<-RUBY.strip_indent) each { |x| }.map(&:to_s) RUBY end it 'accepts a multi-line functional block with {} if it is ' \ 'an ignored method' do inspect_source(<<-RUBY.strip_indent) foo = proc { puts 42 } RUBY expect(cop.messages.empty?).to be(true) end context 'when there are braces around a multi-line block' do it 'registers an offense in the simple case' do expect_offense(<<-RUBY.strip_indent) each { |x| ^ Prefer `do...end` for multi-line blocks without chaining. } RUBY end it 'allows when the block is being chained' do expect_no_offenses(<<-RUBY.strip_indent) each { |x| }.map(&:to_sym) RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb000066400000000000000000000304161322072016200271670ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::BracesAroundHashParameters, :config do subject(:cop) { described_class.new(config) } shared_examples 'general non-offenses' do it 'accepts one non-hash parameter' do expect_no_offenses('where(2)') end it 'accepts multiple non-hash parameters' do expect_no_offenses('where(1, "2")') end it 'accepts one empty hash parameter' do expect_no_offenses('where({})') end it 'accepts one empty hash parameter with whitespace' do expect_no_offenses(['where( { ', " }\t ) "]) end end shared_examples 'no_braces and context_dependent non-offenses' do it 'accepts one hash parameter without braces' do expect_no_offenses('where(x: "y")') end it 'accepts one hash parameter without braces and with multiple keys' do expect_no_offenses('where(x: "y", foo: "bar")') end it 'accepts one hash parameter without braces and with one hash value' do expect_no_offenses('where(x: { "y" => "z" })') end it 'accepts property assignment with braces' do expect_no_offenses('x.z = { y: "z" }') end it 'accepts operator with a hash parameter with braces' do expect_no_offenses('x.z - { y: "z" }') end end shared_examples 'no_braces and context_dependent offenses' do let(:msg) { 'Redundant curly braces around a hash parameter.' } it 'registers an offense for one non-hash parameter followed by a hash ' \ 'parameter with braces' do inspect_source('where(1, { y: 2 })') expect(cop.messages).to eq([msg]) expect(cop.highlights).to eq(['{ y: 2 }']) end it 'registers an offense for one object method hash parameter with ' \ 'braces' do inspect_source('x.func({ y: "z" })') expect(cop.messages).to eq([msg]) expect(cop.highlights).to eq(['{ y: "z" }']) end it 'registers an offense for one hash parameter with braces' do inspect_source('where({ x: 1 })') expect(cop.messages).to eq([msg]) expect(cop.highlights).to eq(['{ x: 1 }']) end it 'registers an offense for one hash parameter with braces and ' \ 'whitespace' do inspect_source("where( \n { x: 1 } )") expect(cop.messages).to eq([msg]) expect(cop.highlights).to eq(['{ x: 1 }']) end it 'registers an offense for one hash parameter with braces and multiple ' \ 'keys' do inspect_source('where({ x: 1, foo: "bar" })') expect(cop.messages).to eq([msg]) expect(cop.highlights).to eq(['{ x: 1, foo: "bar" }']) end end shared_examples 'no_braces and context_dependent auto-corrections' do it 'corrects one non-hash parameter followed by a hash parameter with ' \ 'braces' do corrected = autocorrect_source(['where(1, { y: 2 })']) expect(corrected).to eq('where(1, y: 2)') end it 'corrects one object method hash parameter with braces' do corrected = autocorrect_source(['x.func({ y: "z" })']) expect(corrected).to eq('x.func(y: "z")') end it 'corrects one hash parameter with braces' do corrected = autocorrect_source(['where({ x: 1 })']) expect(corrected).to eq('where(x: 1)') end it 'corrects one hash parameter with braces and whitespace' do corrected = autocorrect_source(['where( ', ' { x: 1 } )']) expect(corrected).to eq(['where( ', ' x: 1 )'].join("\n")) end it 'corrects one hash parameter with braces and multiple keys' do corrected = autocorrect_source(['where({ x: 1, foo: "bar" })']) expect(corrected).to eq('where(x: 1, foo: "bar")') end it 'corrects one hash parameter with braces and extra leading whitespace' do corrected = autocorrect_source(['where({ x: 1, y: 2 })']) expect(corrected).to eq('where(x: 1, y: 2)') end it 'corrects one hash parameter with braces and extra trailing ' \ 'whitespace' do corrected = autocorrect_source(['where({ x: 1, y: 2 })']) expect(corrected).to eq('where(x: 1, y: 2)') end it 'corrects one hash parameter with braces and a trailing comma' do corrected = autocorrect_source(['where({ x: 1, y: 2, })']) expect(corrected).to eq('where(x: 1, y: 2)') end it 'corrects one hash parameter with braces and trailing comma and ' \ 'whitespace' do corrected = autocorrect_source(['where({ x: 1, y: 2, })']) expect(corrected).to eq('where(x: 1, y: 2)') end it 'corrects one hash parameter with braces without adding extra space' do corrected = autocorrect_source('get :i, { q: { x: 1 } }') expect(corrected).to eq('get :i, q: { x: 1 }') end it 'does not break indent' do src = <<-RUBY foo({ a: 1, b: 2 }) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY) foo( a: 1, b: 2 ) RUBY end it 'does not remove trailing comma nor realign args' do src = <<-RUBY.strip_indent foo({ a: 1, b: 2, }) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( a: 1, b: 2, ) RUBY end it 'corrects brace removal with 2 extra lines' do src = <<-RUBY.strip_indent foo( { baz: 10 } ) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( baz: 10 ) RUBY end it 'corrects brace removal with extra lines & mulitple pairs' do src = <<-RUBY.strip_indent foo( { qux: "bar", baz: "bar", thud: "bar" } ) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( qux: "bar", baz: "bar", thud: "bar" ) RUBY end it 'corrects brace removal with lower extra line' do src = <<-RUBY.strip_indent foo({ baz: 7 } ) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( baz: 7 ) RUBY end it 'corrects brace removal with top extra line' do src = <<-RUBY.strip_indent foo( { baz: 5 }) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( baz: 5 ) RUBY end context 'with a comment following the last key-value pair' do it 'corrects and leaves line breaks' do src = <<-RUBY.strip_indent r = opts.merge({ p1: opts[:a], p2: (opts[:b] || opts[:c]) # a comment }) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) r = opts.merge( p1: opts[:a], p2: (opts[:b] || opts[:c]) # a comment ) RUBY end end context 'in a method call without parentheses' do it 'corrects a hash parameter with trailing comma' do src = 'get :i, { x: 1, }' corrected = autocorrect_source(src) expect(corrected).to eq('get :i, x: 1') end end end context 'when EnforcedStyle is no_braces' do let(:cop_config) { { 'EnforcedStyle' => 'no_braces' } } context 'for correct code' do include_examples 'general non-offenses' include_examples 'no_braces and context_dependent non-offenses' end context 'for incorrect code' do include_examples 'no_braces and context_dependent offenses' it 'registers an offense for two hash parameters with braces' do expect_offense(<<-RUBY.strip_indent) where({ x: 1 }, { y: 2 }) ^^^^^^^^ Redundant curly braces around a hash parameter. RUBY end end describe '#autocorrect' do include_examples 'no_braces and context_dependent auto-corrections' it 'corrects one hash parameter with braces' do corrected = autocorrect_source(['where(1, { x: 1 })']) expect(corrected).to eq('where(1, x: 1)') end it 'corrects two hash parameters with braces' do corrected = autocorrect_source(['where(1, { x: 1 }, { y: 2 })']) expect(corrected).to eq('where(1, { x: 1 }, y: 2)') end it 'corrects two hash parameters with braces & extra lines' do src = <<-RUBY.strip_indent foo( { qux: 9 }, { bar: 0 } ) RUBY corrected = autocorrect_source(src) expect(corrected).to eq(<<-RUBY.strip_indent) foo( { qux: 9 }, bar: 0 ) RUBY end end end context 'when EnforcedStyle is context_dependent' do let(:cop_config) { { 'EnforcedStyle' => 'context_dependent' } } context 'for correct code' do include_examples 'general non-offenses' include_examples 'no_braces and context_dependent non-offenses' it 'accepts two hash parameters with braces' do expect_no_offenses('where({ x: 1 }, { y: 2 })') end end context 'for incorrect code' do include_examples 'no_braces and context_dependent offenses' it 'registers an offense for one hash parameter with braces and one ' \ 'without' do inspect_source('where({ x: 1 }, y: 2)') expect(cop.messages) .to eq(['Missing curly braces around a hash parameter.']) expect(cop.highlights).to eq(['y: 2']) end end describe '#autocorrect' do include_examples 'no_braces and context_dependent auto-corrections' it 'corrects one hash parameter with braces and one without' do corrected = autocorrect_source(['where(1, { x: 1 }, y: 2)']) expect(corrected).to eq('where(1, { x: 1 }, {y: 2})') end it 'corrects one hash parameter with braces' do corrected = autocorrect_source(['where(1, { x: 1 })']) expect(corrected).to eq('where(1, x: 1)') end end end context 'when EnforcedStyle is braces' do let(:cop_config) { { 'EnforcedStyle' => 'braces' } } context 'for correct code' do include_examples 'general non-offenses' it 'accepts one hash parameter with braces' do expect_no_offenses('where({ x: 1 })') end it 'accepts multiple hash parameters with braces' do expect_no_offenses('where({ x: 1 }, { y: 2 })') end it 'accepts one hash parameter with braces and whitespace' do expect_no_offenses(<<-RUBY.strip_indent) where( { x: 1 } ) RUBY end end context 'for incorrect code' do it 'registers an offense for one hash parameter without braces' do expect_offense(<<-RUBY.strip_indent) where(x: "y") ^^^^^^ Missing curly braces around a hash parameter. RUBY end it 'registers an offense for one hash parameter with multiple keys and ' \ 'without braces' do expect_offense(<<-RUBY.strip_indent) where(x: "y", foo: "bar") ^^^^^^^^^^^^^^^^^^ Missing curly braces around a hash parameter. RUBY end it 'registers an offense for one hash parameter without braces with ' \ 'one hash value' do expect_offense(<<-RUBY.strip_indent) where(x: { "y" => "z" }) ^^^^^^^^^^^^^^^^^ Missing curly braces around a hash parameter. RUBY end end describe '#autocorrect' do it 'corrects one hash parameter without braces' do corrected = autocorrect_source(['where(x: "y")']) expect(corrected).to eq('where({x: "y"})') end it 'corrects one hash parameter with multiple keys and without braces' do corrected = autocorrect_source(['where(x: "y", foo: "bar")']) expect(corrected).to eq('where({x: "y", foo: "bar"})') end it 'corrects one hash parameter without braces with one hash value' do corrected = autocorrect_source(['where(x: { "y" => "z" })']) expect(corrected).to eq('where({x: { "y" => "z" }})') end end end end rubocop-0.52.1/spec/rubocop/cop/style/case_equality_spec.rb000066400000000000000000000004661322072016200237640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CaseEquality do subject(:cop) { described_class.new } it 'registers an offense for ===' do expect_offense(<<-RUBY.strip_indent) Array === var ^^^ Avoid the use of the case equality operator `===`. RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/character_literal_spec.rb000066400000000000000000000021001322072016200245670ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CharacterLiteral do subject(:cop) { described_class.new } it 'registers an offense for character literals' do expect_offense(<<-RUBY.strip_indent) x = ?x ^^ Do not use the character literal - use string literal instead. RUBY end it 'registers an offense for literals like \n' do expect_offense(<<-'RUBY'.strip_indent) x = ?\n ^^^ Do not use the character literal - use string literal instead. RUBY end it 'accepts literals like ?\C-\M-d' do expect_no_offenses('x = ?\C-\M-d') end it 'accepts ? in a %w literal' do expect_no_offenses('%w{? A}') end it "auto-corrects ?x to 'x'" do new_source = autocorrect_source('x = ?x') expect(new_source).to eq("x = 'x'") end it 'auto-corrects ?\n to "\\n"' do new_source = autocorrect_source('x = ?\n') expect(new_source).to eq('x = "\\n"') end it 'auto-corrects ?\' to "\'"' do new_source = autocorrect_source('x = ?\'') expect(new_source).to eq('x = "\'"') end end rubocop-0.52.1/spec/rubocop/cop/style/class_and_module_children_spec.rb000066400000000000000000000165021322072016200262760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ClassAndModuleChildren, :config do subject(:cop) { described_class.new(config) } context 'nested style' do let(:cop_config) { { 'EnforcedStyle' => 'nested' } } it 'registers an offense for not nested classes' do expect_offense(<<-RUBY.strip_indent) class FooClass::BarClass ^^^^^^^^^^^^^^^^^^ Use nested module/class definitions instead of compact style. end RUBY end it 'registers an offense for not nested classes with explicit superclass' do expect_offense(<<-RUBY.strip_indent) class FooClass::BarClass < Super ^^^^^^^^^^^^^^^^^^ Use nested module/class definitions instead of compact style. end RUBY end it 'registers an offense for not nested modules' do expect_offense(<<-RUBY.strip_indent) module FooModule::BarModule ^^^^^^^^^^^^^^^^^^^^ Use nested module/class definitions instead of compact style. end RUBY end it 'accepts nested children' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass class BarClass end end module FooModule module BarModule end end RUBY end it 'accepts :: in parent class on inheritance' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass class BarClass end end class BazClass < FooClass::BarClass end RUBY end end context 'compact style' do let(:cop_config) { { 'EnforcedStyle' => 'compact' } } it 'registers a offense for classes with nested children' do expect_offense(<<-RUBY.strip_indent) class FooClass ^^^^^^^^ Use compact module/class definition instead of nested style. class BarClass end end RUBY end it 'registers a offense for modules with nested children' do expect_offense(<<-RUBY.strip_indent) module FooModule ^^^^^^^^^ Use compact module/class definition instead of nested style. module BarModule end end RUBY end it 'accepts compact style for classes/modules' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass::BarClass end module FooClass::BarModule end RUBY end it 'accepts nesting for classes/modules with more than one child' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass class BarClass end class BazClass end end module FooModule module BarModule end class BazModule end end RUBY end it 'accepts class/module with single method' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass def bar_method end end RUBY end it 'accepts nesting for classes with an explicit superclass' do expect_no_offenses(<<-RUBY.strip_indent) class FooClass < Super class BarClass end end RUBY end end context 'autocorrect' do let(:cop_config) do { 'AutoCorrect' => 'true', 'EnforcedStyle' => enforced_style } end context 'nested style' do let(:enforced_style) { 'nested' } it 'corrects a not nested class' do source = <<-RUBY.strip_indent class FooClass::BarClass end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) module FooClass class BarClass end end RUBY end it 'corrects a not nested class with explicit superclass' do source = <<-RUBY.strip_indent class FooClass::BarClass < Super end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) module FooClass class BarClass < Super end end RUBY end it 'corrects a not nested module' do source = <<-RUBY.strip_indent module FooClass::BarClass end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) module FooClass module BarClass end end RUBY end it 'does not correct nested children' do source = <<-RUBY.strip_indent class FooClass class BarClass end end module FooModule module BarModule end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not correct :: in parent class on inheritance' do source = <<-RUBY.strip_indent class FooClass class BarClass end end class BazClass < FooClass::BarClass end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end end context 'compact style' do let(:enforced_style) { 'compact' } it 'corrects nested children' do source = <<-RUBY.strip_indent class FooClass class BarClass end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) class FooClass::BarClass end RUBY end it 'corrects modules with nested children' do source = <<-RUBY.strip_indent module FooModule module BarModule end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) module FooModule::BarModule end RUBY end it 'does not correct compact style for classes/modules' do source = <<-RUBY.strip_indent class FooClass::BarClass end module FooClass::BarModule end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not correct nested classes/modules with more than one child' do source = <<-RUBY.strip_indent class FooClass class BarClass end class BazClass end end module FooModule module BarModule end class BazModule end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not correct class/module with single method' do source = <<-RUBY.strip_indent class FooClass def bar_method end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end it 'does not correct nesting for classes with an explicit superclass' do source = <<-RUBY.strip_indent class FooClass < Super class BarClass end end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end end rubocop-0.52.1/spec/rubocop/cop/style/class_check_spec.rb000066400000000000000000000020231322072016200233650ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ClassCheck, :config do subject(:cop) { described_class.new(config) } context 'when enforced style is is_a?' do let(:cop_config) { { 'EnforcedStyle' => 'is_a?' } } it 'registers an offense for kind_of?' do expect_offense(<<-RUBY.strip_indent) x.kind_of? y ^^^^^^^^ Prefer `Object#is_a?` over `Object#kind_of?`. RUBY end it 'auto-corrects kind_of? to is_a?' do corrected = autocorrect_source(['x.kind_of? y']) expect(corrected).to eq 'x.is_a? y' end end context 'when enforced style is kind_of?' do let(:cop_config) { { 'EnforcedStyle' => 'kind_of?' } } it 'registers an offense for is_a?' do expect_offense(<<-RUBY.strip_indent) x.is_a? y ^^^^^ Prefer `Object#kind_of?` over `Object#is_a?`. RUBY end it 'auto-corrects is_a? to kind_of?' do corrected = autocorrect_source(['x.is_a? y']) expect(corrected).to eq 'x.kind_of? y' end end end rubocop-0.52.1/spec/rubocop/cop/style/class_methods_spec.rb000066400000000000000000000033331322072016200237600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ClassMethods do subject(:cop) { described_class.new } it 'registers an offense for methods using a class name' do expect_offense(<<-RUBY.strip_indent) class Test def Test.some_method ^^^^ Use `self.some_method` instead of `Test.some_method`. do_something end end RUBY end it 'registers an offense for methods using a module name' do expect_offense(<<-RUBY.strip_indent) module Test def Test.some_method ^^^^ Use `self.some_method` instead of `Test.some_method`. do_something end end RUBY end it 'does not register an offense for methods using self' do expect_no_offenses(<<-RUBY.strip_indent) module Test def self.some_method do_something end end RUBY end it 'does not register an offense for other top-level singleton methods' do expect_no_offenses(<<-RUBY.strip_indent) class Test X = Something.new def X.some_method do_something end end RUBY end it 'does not register an offense outside class/module bodies' do expect_no_offenses(<<-RUBY.strip_indent) def Test.some_method do_something end RUBY end it 'autocorrects class name to self' do src = <<-RUBY.strip_indent class Test def Test.some_method do_something end end RUBY correct_source = <<-RUBY.strip_indent class Test def self.some_method do_something end end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(correct_source) end end rubocop-0.52.1/spec/rubocop/cop/style/class_vars_spec.rb000066400000000000000000000007361322072016200232740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ClassVars do subject(:cop) { described_class.new } it 'registers an offense for class variable declaration' do expect_offense(<<-RUBY.strip_indent) class TestClass; @@test = 10; end ^^^^^^ Replace class var @@test with a class instance var. RUBY end it 'does not register an offense for class variable usage' do expect_no_offenses('@@test.test(20)') end end rubocop-0.52.1/spec/rubocop/cop/style/collection_methods_spec.rb000066400000000000000000000026161322072016200250110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CollectionMethods, :config do cop_config = { 'PreferredMethods' => { 'collect' => 'map', 'inject' => 'reduce', 'detect' => 'find', 'find_all' => 'select' } } subject(:cop) { described_class.new(config) } let(:cop_config) { cop_config } cop_config['PreferredMethods'].each do |method, preferred_method| it "registers an offense for #{method} with block" do inspect_source("[1, 2, 3].#{method} { |e| e + 1 }") expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Prefer `#{preferred_method}` over `#{method}`."]) end it "registers an offense for #{method} with proc param" do inspect_source("[1, 2, 3].#{method}(&:test)") expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Prefer `#{preferred_method}` over `#{method}`."]) end it "accepts #{method} with more than 1 param" do inspect_source("[1, 2, 3].#{method}(other, &:test)") expect(cop.offenses.empty?).to be(true) end it "accepts #{method} without a block" do inspect_source("[1, 2, 3].#{method}") expect(cop.offenses.empty?).to be(true) end it 'auto-corrects to preferred method' do new_source = autocorrect_source('some.collect(&:test)') expect(new_source).to eq('some.map(&:test)') end end end rubocop-0.52.1/spec/rubocop/cop/style/colon_method_call_spec.rb000066400000000000000000000030751322072016200246000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ColonMethodCall do subject(:cop) { described_class.new } it 'registers an offense for instance method call' do expect_offense(<<-RUBY.strip_indent) test::method_name ^^ Do not use `::` for method calls. RUBY end it 'registers an offense for instance method call with arg' do expect_offense(<<-RUBY.strip_indent) test::method_name(arg) ^^ Do not use `::` for method calls. RUBY end it 'registers an offense for class method call' do expect_offense(<<-RUBY.strip_indent) Class::method_name ^^ Do not use `::` for method calls. RUBY end it 'registers an offense for class method call with arg' do expect_offense(<<-RUBY.strip_indent) Class::method_name(arg, arg2) ^^ Do not use `::` for method calls. RUBY end it 'does not register an offense for constant access' do expect_no_offenses('Tip::Top::SOME_CONST') end it 'does not register an offense for nested class' do expect_no_offenses('Tip::Top.some_method') end it 'does not register an offense for op methods' do expect_no_offenses('Tip::Top.some_method[3]') end it 'does not register an offense when for constructor methods' do expect_no_offenses('Tip::Top(some_arg)') end it 'does not register an offense for Java static types' do expect_no_offenses('Java::int') end it 'auto-corrects "::" with "."' do new_source = autocorrect_source('test::method') expect(new_source).to eq('test.method') end end rubocop-0.52.1/spec/rubocop/cop/style/colon_method_definition_spec.rb000066400000000000000000000032131322072016200260070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ColonMethodDefinition do subject(:cop) { described_class.new } it 'accepts a class method defined using .' do expect_no_offenses(<<-RUBY.strip_indent) class Foo def self.bar something end end RUBY end context 'using self' do it 'registers an offense for a class method defined using ::' do expect_offense(<<-RUBY.strip_indent) class Foo def self::bar ^^ Do not use `::` for defining class methods. something end end RUBY end it 'corrects :: to .' do new_source = autocorrect_source(<<-RUBY.strip_indent) class Foo def self::bar something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class Foo def self.bar something end end RUBY end end context 'using the class name' do it 'registers an offense for a class method defined using ::' do expect_offense(<<-RUBY.strip_indent) class Foo def Foo::bar ^^ Do not use `::` for defining class methods. something end end RUBY end it 'corrects :: to .' do new_source = autocorrect_source(<<-RUBY.strip_indent) class Foo def Foo::bar something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) class Foo def Foo.bar something end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/command_literal_spec.rb000066400000000000000000000305421322072016200242640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CommandLiteral, :config do subject(:cop) { described_class.new(config) } let(:config) do supported_styles = { 'SupportedStyles' => %w[backticks percent_x mixed] } RuboCop::Config.new('Style/PercentLiteralDelimiters' => percent_literal_delimiters_config, 'Style/CommandLiteral' => cop_config.merge(supported_styles)) end let(:percent_literal_delimiters_config) do { 'PreferredDelimiters' => { '%x' => '()' } } end describe '%x commands with other delimiters than parentheses' do let(:cop_config) { { 'EnforcedStyle' => 'backticks' } } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) %x$ls$ ^^^^^^ Use backticks around command string. RUBY end end describe 'when PercentLiteralDelimiters is configured with curly braces' do let(:cop_config) { { 'EnforcedStyle' => 'percent_x' } } let(:percent_literal_delimiters_config) do { 'PreferredDelimiters' => { '%x' => '[]' } } end it 'respects the configuration when auto-correcting' do new_source = autocorrect_source('`ls`') expect(new_source).to eq('%x[ls]') end end describe 'heredoc commands' do let(:cop_config) { { 'EnforcedStyle' => 'backticks' } } it 'is ignored' do expect_no_offenses(<<-RUBY.strip_indent) <<`COMMAND` ls COMMAND RUBY end end context 'when EnforcedStyle is set to backticks' do let(:cop_config) { { 'EnforcedStyle' => 'backticks' } } describe 'a single-line ` string without backticks' do it 'is accepted' do expect_no_offenses('foo = `ls`') end end describe 'a single-line ` string with backticks' do let(:source) { 'foo = `echo \`ls\``' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = `echo \`ls\`` ^^^^^^^^^^^^^ Use `%x` around command string. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'is accepted' do expect_no_offenses('foo = `echo \\`ls\\``') end end end describe 'a multi-line ` string without backticks' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = ` ls ls -l ` RUBY end end describe 'a multi-line ` string with backticks' do let(:source) do ['foo = `', ' echo \`ls\`', ' echo \`ls -l\`', '`'] end it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = ` ^ Use `%x` around command string. echo \`ls\` echo \`ls -l\` ` RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'is accepted' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = ` echo \`ls\` echo \`ls -l\` ` RUBY end end end describe 'a single-line %x string without backticks' do let(:source) { 'foo = %x(ls)' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x(ls) ^^^^^^ Use backticks around command string. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = `ls`') end end describe 'a single-line %x string with backticks' do let(:source) { 'foo = %x(echo `ls`)' } it 'is accepted' do expect_no_offenses('foo = %x(echo `ls`)') end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x(echo `ls`) ^^^^^^^^^^^^^ Use backticks around command string. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end describe 'a multi-line %x string without backticks' do let(:source) do ['foo = %x(', ' ls', ' ls -l', ')'] end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x( ^^^ Use backticks around command string. ls ls -l ) RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = `\n ls\n ls -l\n`") end end describe 'a multi-line %x string with backticks' do let(:source) do ['foo = %x(', ' echo `ls`', ' echo `ls -l`', ')'] end it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %x( echo `ls` echo `ls -l` ) RUBY end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x( ^^^ Use backticks around command string. echo `ls` echo `ls -l` ) RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end end end context 'when EnforcedStyle is set to percent_x' do let(:cop_config) { { 'EnforcedStyle' => 'percent_x' } } describe 'a single-line ` string without backticks' do let(:source) { 'foo = `ls`' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = `ls` ^^^^ Use `%x` around command string. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = %x(ls)') end end describe 'a single-line ` string with backticks' do let(:source) { 'foo = `echo \`ls\``' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = `echo \`ls\`` ^^^^^^^^^^^^^ Use `%x` around command string. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end describe 'a multi-line ` string without backticks' do let(:source) do ['foo = `', ' ls', ' ls -l', '`'] end it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = ` ^ Use `%x` around command string. ls ls -l ` RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = %x(\n ls\n ls -l\n)") end end describe 'a multi-line ` string with backticks' do let(:source) do ['foo = `', ' echo \`ls\`', ' echo \`ls -l\`', '`'] end it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = ` ^ Use `%x` around command string. echo \`ls\` echo \`ls -l\` ` RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end describe 'a single-line %x string without backticks' do it 'is accepted' do expect_no_offenses('foo = %x(ls)') end end describe 'a single-line %x string with backticks' do it 'is accepted' do expect_no_offenses('foo = %x(echo `ls`)') end end describe 'a multi-line %x string without backticks' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %x( ls ls -l ) RUBY end end describe 'a multi-line %x string with backticks' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %x( echo `ls` echo `ls -l` ) RUBY end end end context 'when EnforcedStyle is set to mixed' do let(:cop_config) { { 'EnforcedStyle' => 'mixed' } } describe 'a single-line ` string without backticks' do it 'is accepted' do expect_no_offenses('foo = `ls`') end end describe 'a single-line ` string with backticks' do let(:source) { 'foo = `echo \`ls\``' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = `echo \`ls\`` ^^^^^^^^^^^^^ Use `%x` around command string. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'is accepted' do expect_no_offenses('foo = `echo \\`ls\\``') end end end describe 'a multi-line ` string without backticks' do let(:source) do ['foo = `', ' ls', ' ls -l', '`'] end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = ` ^ Use `%x` around command string. ls ls -l ` RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = %x(\n ls\n ls -l\n)") end end describe 'a multi-line ` string with backticks' do let(:source) do ['foo = `', ' echo \`ls\`', ' echo \`ls -l\`', '`'] end it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = ` ^ Use `%x` around command string. echo \`ls\` echo \`ls -l\` ` RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end describe 'a single-line %x string without backticks' do let(:source) { 'foo = %x(ls)' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x(ls) ^^^^^^ Use backticks around command string. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = `ls`') end end describe 'a single-line %x string with backticks' do let(:source) { 'foo = %x(echo `ls`)' } it 'is accepted' do expect_no_offenses('foo = %x(echo `ls`)') end describe 'when configured to allow inner backticks' do before { cop_config['AllowInnerBackticks'] = true } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %x(echo `ls`) ^^^^^^^^^^^^^ Use backticks around command string. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end describe 'a multi-line %x string without backticks' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %x( ls ls -l ) RUBY end end describe 'a multi-line %x string with backticks' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %x( echo `ls` echo `ls -l` ) RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/comment_annotation_spec.rb000066400000000000000000000101471322072016200250250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CommentAnnotation, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Keywords' => %w[TODO FIXME OPTIMIZE HACK REVIEW] } end context 'missing colon' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # TODO make better ^^^^^ Annotation keywords like `TODO` should be all upper case, followed by a colon, and a space, then a note describing the problem. RUBY end it 'autocorrects' do corrected = autocorrect_source('# TODO make better') expect(corrected).to eq('# TODO: make better') end end context 'with configured keyword' do let(:cop_config) { { 'Keywords' => %w[ISSUE] } } it 'registers an offense for a missing colon after the word' do expect_offense(<<-RUBY.strip_indent) # ISSUE wrong order ^^^^^^ Annotation keywords like `ISSUE` should be all upper case, followed by a colon, and a space, then a note describing the problem. RUBY end it 'autocorrects a missing colon after keyword' do corrected = autocorrect_source('# ISSUE wrong order') expect(corrected).to eq('# ISSUE: wrong order') end end context 'missing space after colon' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # TODO:make better ^^^^^ Annotation keywords like `TODO` should be all upper case, followed by a colon, and a space, then a note describing the problem. RUBY end it 'autocorrects' do corrected = autocorrect_source('# TODO:make better') expect(corrected).to eq('# TODO: make better') end end context 'lower case keyword' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # fixme: does not work ^^^^^^^ Annotation keywords like `fixme` should be all upper case, followed by a colon, and a space, then a note describing the problem. RUBY end it 'autocorrects' do corrected = autocorrect_source('# fixme: does not work') expect(corrected).to eq('# FIXME: does not work') end end context 'capitalized keyword' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # Optimize: does not work ^^^^^^^^^^ Annotation keywords like `Optimize` should be all upper case, followed by a colon, and a space, then a note describing the problem. RUBY end it 'autocorrects' do corrected = autocorrect_source('# Optimize: does not work') expect(corrected).to eq('# OPTIMIZE: does not work') end end context 'upper case keyword with colon by no note' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) # HACK: ^^^^^ Annotation comment, with keyword `HACK`, is missing a note. RUBY end it 'does not autocorrects' do source = '# HACK:' corrected = autocorrect_source(source) expect(corrected).to eq(source) end end it 'accepts upper case keyword with colon, space and note' do expect_no_offenses('# REVIEW: not sure about this') end it 'accepts upper case keyword alone' do expect_no_offenses('# OPTIMIZE') end it 'accepts a comment that is obviously a code example' do expect_no_offenses('# Todo.destroy(1)') end it 'accepts a keyword that is just the beginning of a sentence' do expect_no_offenses(<<-RUBY.strip_indent) # Optimize if you want. I wouldn't recommend it. # Hack is a fun game. RUBY end it 'accepts a keyword that is somewhere in a sentence' do expect_no_offenses(<<-RUBY.strip_indent) # Example: There are three reviews, with ranks 1, 2, and 3. A new # review is saved with rank 2. The two reviews that originally had # ranks 2 and 3 will have their ranks increased to 3 and 4. RUBY end context 'when a keyword is not in the configuration' do let(:cop_config) do { 'Keywords' => %w[FIXME OPTIMIZE HACK REVIEW] } end it 'accepts the word without colon' do expect_no_offenses('# TODO make better') end end end rubocop-0.52.1/spec/rubocop/cop/style/commented_keyword_spec.rb000066400000000000000000000111101322072016200246370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::CommentedKeyword do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when commenting on the same line as `end`' do inspect_source(<<-RUBY.strip_indent) if x y end # comment RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `end` keyword.']) end it 'registers an offense when commenting on the same line as `begin`' do inspect_source(<<-RUBY.strip_indent) begin # comment y end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `begin` keyword.']) end it 'registers an offense when commenting on the same line as `class`' do inspect_source(<<-RUBY.strip_indent) class X # comment y end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `class` keyword.']) end it 'registers an offense when commenting on the same line as `module`' do inspect_source(<<-RUBY.strip_indent) module X # comment y end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `module` keyword.']) end it 'registers an offense when commenting on the same line as `def`' do inspect_source(<<-RUBY.strip_indent) def x # comment y end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `def` keyword.']) end it 'registers an offense when commenting on indented keywords' do inspect_source(<<-RUBY.strip_indent) module X class Y # comment z end end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `class` keyword.']) end it 'registers an offense when commenting after keyword with spaces' do inspect_source(<<-RUBY.strip_indent) def x(a, b) # comment y end RUBY expect(cop.highlights).to eq(['# comment']) expect(cop.messages).to eq(['Do not place comments on the same line as ' \ 'the `def` keyword.']) end it 'registers an offense for one-line cases' do expect_offense(<<-RUBY.strip_indent) def x; end # comment' ^^^^^^^^^^ Do not place comments on the same line as the `def` keyword. RUBY end it 'does not register an offense if there are no comments after keywords' do expect_no_offenses(<<-RUBY.strip_indent) if x y end RUBY expect_no_offenses(<<-RUBY.strip_indent) class X y end RUBY expect_no_offenses(<<-RUBY.strip_indent) begin x end RUBY expect_no_offenses(<<-RUBY.strip_indent) def x y end RUBY expect_no_offenses(<<-RUBY.strip_indent) module X y end RUBY expect_no_offenses(<<-RUBY.strip_indent) # module Y # trap comment RUBY expect_no_offenses(<<-RUBY.strip_indent) 'end' # comment RUBY expect_no_offenses(<<-RUBY.strip_indent) <<-HEREDOC def # not a comment HEREDOC RUBY end it 'does not register an offense for certain comments' do expect_no_offenses(<<-RUBY.strip_indent) class X # :nodoc: y end RUBY expect_no_offenses(<<-RUBY.strip_indent) def x # rubocop:disable Metrics/MethodLength y end RUBY end it 'does not register an offense if AST contains # symbol' do expect_no_offenses(<<-RUBY.strip_indent) def x(y = "#value") y end RUBY expect_no_offenses(<<-RUBY.strip_indent) def x(y: "#value") y end RUBY end it 'accepts keyword letter sequences that are not keywords' do expect_no_offenses(<<-RUBY.strip_indent) options = { end_buttons: true, # comment } RUBY expect_no_offenses(<<-RUBY.strip_indent) defined?(SomeModule).should be_nil # comment RUBY expect_no_offenses(<<-RUBY.strip_indent) foo = beginning_statement # comment RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/conditional_assignment_assign_in_condition_spec.rb000066400000000000000000001041541322072016200317660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ConditionalAssignment do subject(:cop) { described_class.new(config) } shared_examples 'all variable types' do |variable| it 'registers an offense assigning any variable type to ternary' do inspect_source("#{variable} = foo? ? 1 : 2") expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'allows assigning any variable type inside ternary' do inspect_source("foo? ? #{variable} = 1 : #{variable} = 2") expect(cop.offenses.empty?).to be(true) end it 'registers an offense assigning any variable type to if else' do source = <<-RUBY.strip_indent #{variable} = if foo 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense assigning any variable type to if elsif else' do source = <<-RUBY.strip_indent #{variable} = if foo 1 elsif baz 2 else 3 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense assigning any variable type to if else' \ 'with multiple assignment' do source = <<-RUBY.strip_indent #{variable}, #{variable} = if foo something else something_else end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'allows assigning any variable type inside if else' \ 'with multiple assignment' do source = <<-RUBY.strip_indent if foo #{variable}, #{variable} = something else #{variable}, #{variable} = something_else end RUBY inspect_source(source) expect(cop.messages.empty?).to be(true) end it 'allows assigning any variable type inside if else' do source = <<-RUBY.strip_indent if foo #{variable} = 1 else #{variable} = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment to if without else' do source = <<-RUBY.strip_indent #{variable} = if foo 1 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'registers an offense assigning any variable type to unless else' do source = <<-RUBY.strip_indent #{variable} = unless foo 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'allows assigning any variable type inside unless else' do source = <<-RUBY.strip_indent unless foo #{variable} = 1 else #{variable} = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'registers an offense for assigning any variable type to case when' do source = <<-RUBY.strip_indent #{variable} = case foo when "a" 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'allows assigning any variable type inside case when' do source = <<-RUBY.strip_indent case foo when "a" #{variable} = 1 else #{variable} = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'does not crash for rescue assignment' do source = <<-RUBY.strip_indent begin foo rescue => #{variable} bar end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'auto-correct' do it 'corrects assigning any variable type to ternary' do new_source = autocorrect_source("#{variable} = foo? ? 1 : 2") expect(new_source).to eq("foo? ? #{variable} = 1 : #{variable} = 2") end it 'corrects assigning any variable type to if elsif else' do source = <<-RUBY.strip_indent #{variable} = if foo 1 elsif baz 2 else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo #{variable} = 1 elsif baz #{variable} = 2 else #{variable} = 3 end RUBY end it 'corrects assigning any variable type to unless else' do source = <<-RUBY.strip_indent #{variable} = unless foo 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) unless foo #{variable} = 1 else #{variable} = 2 end RUBY end it 'corrects assigning any variable type to case when' do source = <<-RUBY.strip_indent #{variable} = case foo when "a" 1 when "b" 2 else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when "a" #{variable} = 1 when "b" #{variable} = 2 else #{variable} = 3 end RUBY end end end shared_examples 'all assignment types' do |assignment| it 'registers an offense for any assignment to ternary' do inspect_source("bar #{assignment} (foo? ? 1 : 2)") expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense any assignment to if else' do source = <<-RUBY.strip_indent bar #{assignment} if foo 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'allows any assignment to if without else' do source = <<-RUBY.strip_indent bar #{assignment} if foo 1 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'registers an offense for any assignment to unless else' do source = <<-RUBY.strip_indent bar #{assignment} unless foo 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense any assignment to case when' do source = <<-RUBY.strip_indent bar #{assignment} case foo when "a" 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end context 'auto-correct' do it 'corrects any assignment to ternary' do new_source = autocorrect_source("bar #{assignment} (foo? ? 1 : 2)") expect(new_source) .to eq("foo? ? bar #{assignment} 1 : bar #{assignment} 2") end it 'corrects any assignment to if else' do source = <<-RUBY.strip_indent bar #{assignment} if foo 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo bar #{assignment} 1 else bar #{assignment} 2 end RUBY end it 'corrects any assignment to unless else' do source = <<-RUBY.strip_indent bar #{assignment} unless foo 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) unless foo bar #{assignment} 1 else bar #{assignment} 2 end RUBY end it 'corrects any assignment to case when' do source = <<-RUBY.strip_indent bar #{assignment} case foo when "a" 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when "a" bar #{assignment} 1 else bar #{assignment} 2 end RUBY end end end shared_examples 'multiline all variable types' do |variable, expected| it 'assigning any variable type to a multiline if else' do source = <<-RUBY.strip_indent #{variable} = if foo something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'assigning any variable type to an if else with multiline ' \ 'in one branch' do source = <<-RUBY.strip_indent #{variable} = if foo 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'assigning any variable type to a multiline if elsif else' do source = <<-RUBY.strip_indent #{variable} = if foo something 1 elsif something_other 2 elsif something_other_again 3 else something_else 4 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'assigning any variable type to a multiline unless else' do source = <<-RUBY.strip_indent #{variable} = unless foo something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'assigning any variable type to a multiline case when' do source = <<-RUBY.strip_indent #{variable} = case foo when "a" something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end end shared_examples 'multiline all assignment types' do |assignment, expected| it 'any assignment to a multiline if else' do source = <<-RUBY.strip_indent bar #{assignment} if foo something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'any assignment to a multiline unless else' do source = <<-RUBY.strip_indent bar #{assignment} unless foo something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end it 'any assignment to a multiline case when' do source = <<-RUBY.strip_indent bar #{assignment} case foo when "a" something 1 else something_else 2 end RUBY inspect_source(source) expect(cop.messages).to eq(expected) end end shared_examples 'single line condition auto-correct' do it 'corrects assignment to an if else condition' do source = <<-RUBY.strip_indent bar = if foo 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo bar = 1 else bar = 2 end RUBY end it 'corrects assignment to an if elsif else condition' do source = <<-RUBY.strip_indent bar = if foo 1 elsif foobar 2 else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar bar = 2 else bar = 3 end RUBY end it 'corrects assignment to an if elsif else with multiple elsifs' do source = <<-RUBY.strip_indent bar = if foo 1 elsif foobar 2 elsif baz 3 else 4 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar bar = 2 elsif baz bar = 3 else bar = 4 end RUBY end it 'corrects assignment to an unless else condition' do source = <<-RUBY.strip_indent bar = unless foo 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) unless foo bar = 1 else bar = 2 end RUBY end it 'corrects assignment to a case when else condition' do source = <<-RUBY.strip_indent bar = case foo when foobar 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when foobar bar = 1 else bar = 2 end RUBY end it 'corrects assignment to a case when else with multiple whens' do source = <<-RUBY.strip_indent bar = case foo when foobar 1 when baz 2 else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when foobar bar = 1 when baz bar = 2 else bar = 3 end RUBY end it 'corrects assignment to a ternary operator' do new_source = autocorrect_source('bar = foo? ? 1 : 2') expect(new_source).to eq('foo? ? bar = 1 : bar = 2') end end context 'SingleLineConditionsOnly true' do let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => true, 'IncludeTernaryExpressions' => true, 'EnforcedStyle' => 'assign_inside_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'keyword', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end it_behaves_like('all variable types', 'bar') it_behaves_like('all variable types', 'BAR') it_behaves_like('all variable types', 'FOO::BAR') it_behaves_like('all variable types', '@bar') it_behaves_like('all variable types', '@@bar') it_behaves_like('all variable types', '$BAR') it_behaves_like('all variable types', 'foo.bar') it_behaves_like('multiline all variable types', 'bar', []) it_behaves_like('multiline all variable types', 'BAR', []) it_behaves_like('multiline all variable types', 'FOO::BAR', []) it_behaves_like('multiline all variable types', '@bar', []) it_behaves_like('multiline all variable types', '@@bar', []) it_behaves_like('multiline all variable types', '$BAR', []) it_behaves_like('multiline all variable types', 'foo.bar', []) it_behaves_like('all assignment types', '=') it_behaves_like('all assignment types', '==') it_behaves_like('all assignment types', '===') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '-=') it_behaves_like('all assignment types', '*=') it_behaves_like('all assignment types', '**=') it_behaves_like('all assignment types', '/=') it_behaves_like('all assignment types', '%=') it_behaves_like('all assignment types', '^=') it_behaves_like('all assignment types', '&=') it_behaves_like('all assignment types', '|=') it_behaves_like('all assignment types', '<=') it_behaves_like('all assignment types', '>=') it_behaves_like('all assignment types', '<<=') it_behaves_like('all assignment types', '>>=') it_behaves_like('all assignment types', '||=') it_behaves_like('all assignment types', '&&=') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '-=') it_behaves_like('all assignment types', '<<') it_behaves_like('multiline all assignment types', '=', []) it_behaves_like('multiline all assignment types', '==', []) it_behaves_like('multiline all assignment types', '===', []) it_behaves_like('multiline all assignment types', '+=', []) it_behaves_like('multiline all assignment types', '-=', []) it_behaves_like('multiline all assignment types', '*=', []) it_behaves_like('multiline all assignment types', '**=', []) it_behaves_like('multiline all assignment types', '/=', []) it_behaves_like('multiline all assignment types', '%=', []) it_behaves_like('multiline all assignment types', '^=', []) it_behaves_like('multiline all assignment types', '&=', []) it_behaves_like('multiline all assignment types', '|=', []) it_behaves_like('multiline all assignment types', '<=', []) it_behaves_like('multiline all assignment types', '>=', []) it_behaves_like('multiline all assignment types', '<<=', []) it_behaves_like('multiline all assignment types', '>>=', []) it_behaves_like('multiline all assignment types', '||=', []) it_behaves_like('multiline all assignment types', '&&=', []) it_behaves_like('multiline all assignment types', '+=', []) it_behaves_like('multiline all assignment types', '-=', []) it_behaves_like('multiline all assignment types', '<<', []) it 'allows a method call in the subject of a ternary operator' do expect_no_offenses('bar << foo? ? 1 : 2') end it 'registers an offense for assignment using a method that ends with ' \ 'an equal sign' do inspect_source('self.attributes = foo? ? 1 : 2') expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense for assignment using []=' do source = <<-RUBY.strip_indent foo[:a] = if bar? 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense for assignment to an if then else' do source = <<-RUBY.strip_indent bar = if foo then 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end it 'registers an offense for assignment to case when then else' do source = <<-RUBY.strip_indent baz = case foo when bar then 1 else 2 end RUBY inspect_source(source) expect(cop.messages).to eq([described_class::ASSIGN_TO_CONDITION_MSG]) end context 'for loop' do it 'ignores pseudo assignments in a for loop' do expect_no_offenses('for i in [1, 2, 3]; puts i; end') end end context 'auto-correct' do it_behaves_like('single line condition auto-correct') it 'corrects assignment to an if then else' do source = <<-RUBY.strip_indent bar = if foo then 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo then bar = 1 else bar = 2 end RUBY end it 'corrects assignment to case when then else' do source = <<-RUBY.strip_indent baz = case foo when bar then 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when bar then baz = 1 else baz = 2 end RUBY end it 'corrects assignment using a method that ends with an equal sign' do new_source = autocorrect_source('self.attributes = foo? ? 1 : 2') expect(new_source) .to eq('foo? ? self.attributes = 1 : self.attributes = 2') end it 'corrects assignment using []=' do source = <<-RUBY.strip_indent foo[:a] = if bar? 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if bar? foo[:a] = 1 else foo[:a] = 2 end RUBY end it 'corrects assignment to a namespaced constant' do source = <<-RUBY.strip_indent FOO::BAR = if baz? 1 else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if baz? FOO::BAR = 1 else FOO::BAR = 2 end RUBY end end end context 'SingleLineConditionsOnly false' do let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => false, 'IncludeTernaryExpressions' => true, 'EnforcedStyle' => 'assign_inside_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'keyword', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end it_behaves_like('all variable types', 'bar') it_behaves_like('all variable types', 'BAR') it_behaves_like('all variable types', 'FOO::BAR') it_behaves_like('all variable types', '@bar') it_behaves_like('all variable types', '@@bar') it_behaves_like('all variable types', '$BAR') it_behaves_like('all variable types', 'foo.bar') it_behaves_like('multiline all variable types', 'bar', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', 'BAR', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', 'FOO::BAR', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', '@bar', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', '@@bar', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', '$BAR', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all variable types', 'foo.bar', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('all assignment types', '=') it_behaves_like('all assignment types', '==') it_behaves_like('all assignment types', '===') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '-=') it_behaves_like('all assignment types', '*=') it_behaves_like('all assignment types', '**=') it_behaves_like('all assignment types', '/=') it_behaves_like('all assignment types', '%=') it_behaves_like('all assignment types', '^=') it_behaves_like('all assignment types', '&=') it_behaves_like('all assignment types', '|=') it_behaves_like('all assignment types', '<=') it_behaves_like('all assignment types', '>=') it_behaves_like('all assignment types', '<<=') it_behaves_like('all assignment types', '>>=') it_behaves_like('all assignment types', '||=') it_behaves_like('all assignment types', '&&=') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '-=') it_behaves_like('all assignment types', '<<') it_behaves_like('multiline all assignment types', '=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '==', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '===', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '+=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '-=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '*=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '**=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '/=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '%=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '^=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '&=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '|=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '<=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '>=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '<<=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '>>=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '||=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '&&=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '+=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '-=', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('multiline all assignment types', '<<', [described_class::ASSIGN_TO_CONDITION_MSG]) it_behaves_like('single line condition auto-correct') it 'corrects assignment to a multiline if else condition' do source = <<-RUBY.strip_indent bar = if foo something 1 else something_else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo something bar = 1 else something_else bar = 2 end RUBY end it 'corrects assignment to a multiline if elsif else condition' do source = <<-RUBY.strip_indent bar = if foo something 1 elsif foobar something_elsif 2 else something_else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo something bar = 1 elsif foobar something_elsif bar = 2 else something_else bar = 3 end RUBY end it 'corrects assignment to an if elsif else with multiple elsifs' do source = <<-RUBY.strip_indent bar = if foo something 1 elsif foobar something_elsif1 2 elsif baz something_elsif2 3 else something_else 4 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) if foo something bar = 1 elsif foobar something_elsif1 bar = 2 elsif baz something_elsif2 bar = 3 else something_else bar = 4 end RUBY end it 'corrects assignment to an unless else condition' do source = <<-RUBY.strip_indent bar = unless foo something 1 else something_else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) unless foo something bar = 1 else something_else bar = 2 end RUBY end it 'corrects assignment to a case when else condition' do source = <<-RUBY.strip_indent bar = case foo when foobar something 1 else something_else 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when foobar something bar = 1 else something_else bar = 2 end RUBY end it 'corrects assignment to a case when else with multiple whens' do source = <<-RUBY.strip_indent bar = case foo when foobar something 1 when baz something_other 2 else something_else 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) case foo when foobar something bar = 1 when baz something_other bar = 2 else something_else bar = 3 end RUBY end end context 'IncludeTernaryExpressions false' do let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => true, 'IncludeTernaryExpressions' => false, 'EnforcedStyle' => 'assign_inside_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'keyword', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end it 'allows assigning any variable type to ternary' do expect_no_offenses('bar = foo? ? 1 : 2') end end end rubocop-0.52.1/spec/rubocop/cop/style/conditional_assignment_assign_to_condition_spec.rb000066400000000000000000001526121322072016200320040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ConditionalAssignment do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => true, 'IncludeTernaryExpressions' => true, 'EnforcedStyle' => 'assign_to_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => end_alignment_align_with, 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end let(:end_alignment_align_with) { 'start_of_line' } let(:message) do 'Use the return of the conditional ' \ 'for variable assignment and comparison.' end it 'counts array assignment when determining multiple assignment' do expect_no_offenses(<<-RUBY.strip_indent) if foo array[1] = 1 a = 1 else array[1] = 2 a = 2 end RUBY end it 'allows method calls in conditionals' do expect_no_offenses(<<-RUBY.strip_indent) if line.is_a?(String) expect(actual[ix]).to eq(line) else expect(actual[ix]).to match(line) end RUBY end it 'allows if else without variable assignment' do expect_no_offenses(<<-RUBY.strip_indent) if foo 1 else 2 end RUBY end it 'allows assignment to the result of a ternary operation' do expect_no_offenses('bar = foo? ? "a" : "b"') end it 'registers an offense for assignment in ternary operation' do source = 'foo? ? bar = "a" : bar = "b"' inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows modifier if' do expect_no_offenses('return if a == 1') end it 'allows modifier if inside of if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo a unless b else c unless d end RUBY end it "doesn't crash when assignment statement uses chars which have " \ 'special meaning in a regex' do # regression test; see GH issue 2876 source = <<-RUBY.strip_indent if condition default['key-with-dash'] << a else default['key-with-dash'] << b end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end shared_examples 'comparison methods' do |method| it 'registers an offense for comparison methods in if else' do source = <<-RUBY.strip_indent if foo a #{method} b else a #{method} d end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for comparison methods in unless else' do source = <<-RUBY.strip_indent unless foo a #{method} b else a #{method} d end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for comparison methods in case when' do source = <<-RUBY.strip_indent case foo when bar a #{method} b else a #{method} d end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end end it_behaves_like('comparison methods', '==') it_behaves_like('comparison methods', '!=') it_behaves_like('comparison methods', '=~') it_behaves_like('comparison methods', '!~') it_behaves_like('comparison methods', '<=>') context 'empty branch' do it 'allows an empty if statement' do expect_no_offenses(<<-RUBY.strip_indent) if foo # comment else do_something end RUBY end it 'allows an empty elsif statement' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 elsif baz # empty else bar = 2 end RUBY end it 'allows if elsif without else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 'some string' elsif bar bar = 'another string' end RUBY end it 'allows assignment in if without an else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 end RUBY end it 'allows assignment in unless without an else' do expect_no_offenses(<<-RUBY.strip_indent) unless foo bar = 1 end RUBY end it 'allows assignment in case when without an else' do expect_no_offenses(<<-RUBY.strip_indent) case foo when "a" bar = 1 when "b" bar = 2 end RUBY end it 'allows an empty when branch with an else' do expect_no_offenses(<<-RUBY.strip_indent) case foo when "a" # empty when "b" bar = 2 else bar = 3 end RUBY end it 'allows case with an empty else' do expect_no_offenses(<<-RUBY.strip_indent) case foo when "b" bar = 2 else # empty end RUBY end end it 'allows assignment of different variables in if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 else baz = 1 end RUBY end it 'allows method calls in if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar else baz end RUBY end it 'allows if elsif else with the same assignment only in if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar baz = 2 else bar = 1 end RUBY end it 'allows if elsif else with the same assignment only in if elsif' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar bar = 2 else baz = 1 end RUBY end it 'allows if elsif else with the same assignment only in elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar baz = 2 else baz = 1 end RUBY end it 'allows assignment using different operators in if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 else bar << 2 end RUBY end it 'allows assignment using different (method) operators in if..else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar[index] = 1 else bar << 2 end RUBY end it 'allows aref assignment with different indices in if..else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar[1] = 1 else bar[2] = 2 end RUBY end it 'allows assignment using different operators in if elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if foo bar = 1 elsif foobar bar += 2 else bar << 3 end RUBY end it 'allows assignment of different variables in case when else' do expect_no_offenses(<<-RUBY.strip_indent) case foo when "a" bar = 1 else baz = 2 end RUBY end it 'registers an offense in an if else if the assignment is already ' \ 'at the line length limit' do source = <<-RUBY.strip_indent if foo bar = #{'a' * 72} else bar = #{'b' * 72} end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end context 'correction would exceed max line length' do it 'allows assignment to the same variable in if else if the correction ' \ 'would create a line longer than the configured LineLength' do source = <<-RUBY.strip_indent if foo #{'a' * 78} bar = 1 else bar = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment to the same variable in if else if the correction ' \ 'would cause the condition to exceed the configured LineLength' do source = <<-RUBY.strip_indent if #{'a' * 78} bar = 1 else bar = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment to the same variable in case when else if the ' \ 'correction would create a line longer than the configured LineLength' do source = <<-RUBY.strip_indent case foo when foobar #{'a' * 78} bar = 1 else bar = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end end shared_examples 'all variable types' do |variable| it 'registers an offense assigning any variable type in ternary' do inspect_source("foo? ? #{variable} = 1 : #{variable} = 2") expect(cop.messages).to eq([message]) end it 'registers an offense assigning any variable type in if else' do source = <<-RUBY.strip_indent if foo #{variable} = 1 else #{variable} = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense assigning any variable type in case when' do source = <<-RUBY.strip_indent case foo when "a" #{variable} = 1 else #{variable} = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows assignment to the return of if else' do source = <<-RUBY.strip_indent #{variable} = if foo 1 else 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment to the return of case when' do source = <<-RUBY.strip_indent #{variable} = case foo when bar 1 else 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment to the return of a ternary' do inspect_source("#{variable} = foo? ? 1 : 2") expect(cop.offenses.empty?).to be(true) end end it_behaves_like('all variable types', 'bar') it_behaves_like('all variable types', 'BAR') it_behaves_like('all variable types', 'FOO::BAR') it_behaves_like('all variable types', '@bar') it_behaves_like('all variable types', '@@bar') it_behaves_like('all variable types', '$BAR') it_behaves_like('all variable types', 'foo.bar') shared_examples 'all assignment types' do |assignment| let(:end_alignment_align_with) { 'keyword' } { 'local variable' => 'bar', 'constant' => 'CONST', 'class variable' => '@@cvar', 'instance variable' => '@ivar', 'global variable' => '$gvar' }.each do |type, name| context "for a #{type} lval" do it "registers an offense for assignment using #{assignment} " \ 'in ternary' do source = "foo? ? #{name} #{assignment} 1 : #{name} #{assignment} 2" inspect_source(source) expect(cop.messages).to eq([message]) end it "allows assignment using #{assignment} to ternary" do source = "#{name} #{assignment} foo? ? 1 : 2" inspect_source(source) expect(cop.offenses.empty?).to be(true) end it "registers an offense for assignment using #{assignment} in " \ 'if else' do source = <<-RUBY.strip_indent if foo #{name} #{assignment} 1 else #{name} #{assignment} 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it "registers an offense for assignment using #{assignment} in "\ ' case when' do source = <<-RUBY.strip_indent case foo when "a" #{name} #{assignment} 1 else #{name} #{assignment} 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it "autocorrects for assignment using #{assignment} in if else" do source = <<-RUBY.strip_indent if foo #{name} #{assignment} 1 else #{name} #{assignment} 2 end RUBY new_source = autocorrect_source(source) indent = ' ' * "#{name} #{assignment} ".length expect(new_source).to eq <<-RUBY.strip_indent #{name} #{assignment} if foo 1 else 2 #{indent}end RUBY end end end end it_behaves_like('all assignment types', '=') it_behaves_like('all assignment types', '==') it_behaves_like('all assignment types', '===') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '-=') it_behaves_like('all assignment types', '*=') it_behaves_like('all assignment types', '**=') it_behaves_like('all assignment types', '/=') it_behaves_like('all assignment types', '%=') it_behaves_like('all assignment types', '^=') it_behaves_like('all assignment types', '&=') it_behaves_like('all assignment types', '|=') it_behaves_like('all assignment types', '<=') it_behaves_like('all assignment types', '>=') it_behaves_like('all assignment types', '<<=') it_behaves_like('all assignment types', '>>=') it_behaves_like('all assignment types', '||=') it_behaves_like('all assignment types', '&&=') it_behaves_like('all assignment types', '+=') it_behaves_like('all assignment types', '<<') it_behaves_like('all assignment types', '-=') it 'registers an offense for assignment in if elsif else' do source = <<-RUBY.strip_indent if foo bar = 1 elsif baz bar = 2 else bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for assignment in if elsif elsif else' do source = <<-RUBY.strip_indent if foo bar = 1 elsif baz bar = 2 elsif foobar bar = 3 else bar = 4 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for assignment in if else when the assignment ' \ 'spans multiple lines' do source = <<-RUBY.strip_indent if foo foo = { a: 1, b: 2, c: 2, d: 2, e: 2, f: 2, g: 2, h: 2 } else foo = { } end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'autocorrects assignment in if else when the assignment ' \ 'spans multiple lines' do source = <<-RUBY.strip_indent if foo foo = { a: 1, b: 2, c: 2, d: 2, e: 2, f: 2, g: 2, h: 2 } else foo = { } end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) foo = if foo { a: 1, b: 2, c: 2, d: 2, e: 2, f: 2, g: 2, h: 2 } else { } end RUBY end context 'assignment as the last statement' do it 'allows more than variable assignment in if else' do expect_no_offenses(<<-RUBY.strip_indent) if foo method_call bar = 1 else method_call bar = 2 end RUBY end it 'allows more than variable assignment in if elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if foo method_call bar = 1 elsif foobar method_call bar = 2 else method_call bar = 3 end RUBY end it 'allows multiple assignment in if else' do expect_no_offenses(<<-RUBY.strip_indent) if baz foo = 1 bar = 1 else foo = 2 bar = 2 end RUBY end it 'allows multiple assignment in if elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if baz foo = 1 bar = 1 elsif foobar foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY end it 'allows multiple assignment in if elsif elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if baz foo = 1 bar = 1 elsif foobar foo = 2 bar = 2 elsif barfoo foo = 3 bar = 3 else foo = 4 bar = 4 end RUBY end it 'allows multiple assignment in if elsif else when the last ' \ 'assignment is the same and the earlier assignments do not appear in ' \ 'all branches' do source = <<-RUBY.strip_indent if baz foo = 1 bar = 1 elsif foobar baz = 2 bar = 2 else boo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows multiple assignment in case when else when the last ' \ 'assignment is the same and the earlier assignments do not appear ' \ 'in all branches' do source = <<-RUBY.strip_indent case foo when foobar baz = 1 bar = 1 when foobaz boo = 2 bar = 2 else faz = 3 bar = 3 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows out of order multiple assignment in if elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if baz bar = 1 foo = 1 elsif foobar foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY end it 'allows multiple assignment in unless else' do expect_no_offenses(<<-RUBY.strip_indent) unless baz foo = 1 bar = 1 else foo = 2 bar = 2 end RUBY end it 'allows multiple assignments in case when with only one when' do expect_no_offenses(<<-RUBY.strip_indent) case foo when foobar foo = 1 bar = 1 else foo = 3 bar = 3 end RUBY end it 'allows multiple assignments in case when with multiple whens' do expect_no_offenses(<<-RUBY.strip_indent) case foo when foobar foo = 1 bar = 1 when foobaz foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY end it 'allows multiple assignments in case when if there are uniq ' \ 'variables in the when branches' do source = <<-RUBY.strip_indent case foo when foobar foo = 1 baz = 1 bar = 1 when foobaz foo = 2 baz = 2 bar = 2 else foo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows multiple assignment in case statements when the last ' \ 'assignment is the same and the earlier assignments do not appear in ' \ 'all branches' do source = <<-RUBY.strip_indent case foo when foobar foo = 1 bar = 1 when foobaz baz = 2 bar = 2 else boo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows assignment in if elsif else with some branches only ' \ 'containing variable assignment and others containing more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent if foo bar = 1 elsif foobar method_call bar = 2 elsif baz bar = 3 else method_call bar = 4 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows variable assignment in unless else with more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent unless foo method_call bar = 1 else method_call bar = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'allows variable assignment in case when else with more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent case foo when foobar method_call bar = 1 else method_call bar = 2 end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'multiple assignment in only one branch' do it 'allows multiple assignment is in if' do expect_no_offenses(<<-RUBY.strip_indent) if foo baz = 1 bar = 1 elsif foobar method_call bar = 2 else other_method bar = 3 end RUBY end it 'allows multiple assignment is in elsif' do expect_no_offenses(<<-RUBY.strip_indent) if foo method_call bar = 1 elsif foobar baz = 2 bar = 2 else other_method bar = 3 end RUBY end it 'registers an offense when multiple assignment is in else' do expect_no_offenses(<<-RUBY.strip_indent) if foo method_call bar = 1 elsif foobar other_method bar = 2 else baz = 3 bar = 3 end RUBY end end end it 'registers an offense for assignment in if then else' do source = <<-RUBY.strip_indent if foo then bar = 1 else bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for assignment in unless else' do source = <<-RUBY.strip_indent unless foo bar = 1 else bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for assignment in case when then else' do source = <<-RUBY.strip_indent case foo when bar then baz = 1 else baz = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for assignment in case with when when else' do source = <<-RUBY.strip_indent case foo when foobar bar = 1 when baz bar = 2 else bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows different assignment types in case with when when else' do expect_no_offenses(<<-RUBY.strip_indent) case foo when foobar bar = 1 else bar << 2 end RUBY end it 'allows assignment in multiple branches when it is ' \ 'wrapped in a modifier' do source = <<-RUBY.strip_indent if foo bar << 1 else bar << 2 if foobar end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end context 'auto-correct' do shared_examples 'comparison correction' do |method| let(:end_alignment_align_with) { 'keyword' } it 'corrects comparison methods in if elsif else' do source = <<-RUBY.strip_indent if foo a #{method} b elsif bar a #{method} c else a #{method} d end RUBY new_source = autocorrect_source(source) indent = ' ' * "a #{method} ".length expect(new_source).to eq(<<-RUBY.strip_indent) a #{method} if foo b elsif bar c else d #{indent}end RUBY end it 'corrects comparison methods in unless else' do source = <<-RUBY.strip_indent unless foo a #{method} b else a #{method} d end RUBY new_source = autocorrect_source(source) indent = ' ' * "a #{method} ".length expect(new_source).to eq(<<-RUBY.strip_indent) a #{method} unless foo b else d #{indent}end RUBY end it 'corrects comparison methods in case when' do source = <<-RUBY.strip_indent case foo when bar a #{method} b else a #{method} d end RUBY new_source = autocorrect_source(source) indent = ' ' * "a #{method} ".length expect(new_source).to eq(<<-RUBY.strip_indent) a #{method} case foo when bar b else d #{indent}end RUBY end end it_behaves_like('comparison correction', '==') it_behaves_like('comparison correction', '!=') it_behaves_like('comparison correction', '=~') it_behaves_like('comparison correction', '!~') it_behaves_like('comparison correction', '<=>') it 'corrects assignment in ternary operations' do new_source = autocorrect_source('foo? ? bar = 1 : bar = 2') expect(new_source).to eq('bar = foo? ? 1 : 2') end it 'corrects assignment in ternary operations using strings' do new_source = autocorrect_source('foo? ? bar = "1" : bar = "2"') expect(new_source).to eq('bar = foo? ? "1" : "2"') end it 'corrects =~ in ternary operations' do new_source = autocorrect_source('foo? ? bar =~ /a/ : bar =~ /b/') expect(new_source).to eq('bar =~ (foo? ? /a/ : /b/)') end it 'corrects aref assignment in ternary operations' do new_source = autocorrect_source('foo? ? bar[1] = 1 : bar[1] = 2') expect(new_source).to eq('bar[1] = foo? ? 1 : 2') end it 'corrects << in ternary operations' do new_source = autocorrect_source('foo? ? bar << 1 : bar << 2') expect(new_source).to eq('bar << (foo? ? 1 : 2)') end it 'corrects assignment in if else' do source = <<-RUBY.strip_indent if foo bar = 1 else bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo 1 else 2 end RUBY end it 'corrects assignment to unbracketed array in if else' do source = <<-RUBY.strip_indent if foo bar = 1 else bar = 2, 5, 6 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo 1 else [2, 5, 6] end RUBY end it 'corrects assignment in if elsif else' do source = <<-RUBY.strip_indent if foo bar = 1 elsif baz bar = 2 else bar = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo 1 elsif baz 2 else 3 end RUBY end shared_examples '2 character assignment types' do |asgn| it "corrects assignment using #{asgn} in if elsif else" do source = <<-RUBY.strip_indent if foo bar #{asgn} 1 elsif baz bar #{asgn} 2 else bar #{asgn} 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar #{asgn} if foo 1 elsif baz 2 else 3 end RUBY end it "corrects assignment using #{asgn} in case when else" do source = <<-RUBY.strip_indent case foo when bar baz #{asgn} 1 else baz #{asgn} 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) baz #{asgn} case foo when bar 1 else 2 end RUBY end it "corrects assignment using #{asgn} in unless else" do source = <<-RUBY.strip_indent unless foo bar #{asgn} 1 else bar #{asgn} 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar #{asgn} unless foo 1 else 2 end RUBY end end it_behaves_like('2 character assignment types', '+=') it_behaves_like('2 character assignment types', '-=') it_behaves_like('2 character assignment types', '<<') shared_examples '3 character assignment types' do |asgn| it "corrects assignment using #{asgn} in if elsif else" do source = <<-RUBY.strip_indent if foo bar #{asgn} 1 elsif baz bar #{asgn} 2 else bar #{asgn} 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar #{asgn} if foo 1 elsif baz 2 else 3 end RUBY end it "corrects assignment using #{asgn} in case when else" do source = <<-RUBY.strip_indent case foo when bar baz #{asgn} 1 else baz #{asgn} 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) baz #{asgn} case foo when bar 1 else 2 end RUBY end it "corrects assignment using #{asgn} in unless else" do source = <<-RUBY.strip_indent unless foo bar #{asgn} 1 else bar #{asgn} 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar #{asgn} unless foo 1 else 2 end RUBY end end it_behaves_like('3 character assignment types', '&&=') it_behaves_like('3 character assignment types', '||=') it 'corrects assignment in if elsif else with multiple elsifs' do source = <<-RUBY.strip_indent if foo bar = 1 elsif baz bar = 2 elsif foobar bar = 3 else bar = 4 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo 1 elsif baz 2 elsif foobar 3 else 4 end RUBY end it 'corrects assignment in unless else' do source = <<-RUBY.strip_indent unless foo bar = 1 else bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = unless foo 1 else 2 end RUBY end it 'corrects assignment in case when else' do source = <<-RUBY.strip_indent case foo when bar baz = 1 else baz = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) baz = case foo when bar 1 else 2 end RUBY end it 'corrects assignment in case when else with multiple whens' do source = <<-RUBY.strip_indent case foo when bar baz = 1 when foobar baz = 2 else baz = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) baz = case foo when bar 1 when foobar 2 else 3 end RUBY end context 'assignment from a method' do it 'corrects if else' do source = <<-RUBY.strip_indent if foo?(scope.node) bar << foobar(var, all) else bar << baz(var, all) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar << if foo?(scope.node) foobar(var, all) else baz(var, all) end RUBY end it 'corrects unless else' do source = <<-RUBY.strip_indent unless foo?(scope.node) bar << foobar(var, all) else bar << baz(var, all) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar << unless foo?(scope.node) foobar(var, all) else baz(var, all) end RUBY end it 'corrects case when' do source = <<-RUBY.strip_indent case foo when foobar bar << foobar(var, all) else bar << baz(var, all) end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar << case foo when foobar foobar(var, all) else baz(var, all) end RUBY end end context 'then' do it 'corrects if then elsif then else' do source = <<-RUBY.strip_indent if cond then bar = 1 elsif cond then bar = 2 else bar = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if cond then 1 elsif cond then 2 else 3 end RUBY end it 'corrects case when then else' do source = <<-RUBY.strip_indent case foo when baz then bar = 1 else bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = case foo when baz then 1 else 2 end RUBY end end it 'preserves comments during correction in if else' do source = <<-RUBY.strip_indent if foo # comment in if bar = 1 else # comment in else bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo # comment in if 1 else # comment in else 2 end RUBY end it 'preserves comments during correction in case when else' do source = <<-RUBY.strip_indent case foo when foobar # comment in when bar = 1 else # comment in else bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = case foo when foobar # comment in when 1 else # comment in else 2 end RUBY end context 'aref assignment' do it 'corrects if..else' do new_source = autocorrect_source(<<-RUBY.strip_indent) if something array[1] = 1 else array[1] = 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) array[1] = if something 1 else 2 end RUBY end context 'with different indices' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) if something array[1, 2] = 1 else array[1, 3] = 2 end RUBY end end end context 'self.attribute= assignment' do it 'corrects if..else' do new_source = autocorrect_source(<<-RUBY.strip_indent) if something self.attribute = 1 else self.attribute = 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) self.attribute = if something 1 else 2 end RUBY end context 'with different receivers' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) if something obj1.attribute = 1 else obj2.attribute = 2 end RUBY end end end context 'multiple assignment' do it 'does not register an offense in if else' do expect_no_offenses(<<-RUBY.strip_indent) if something a, b = 1, 2 else a, b = 2, 1 end RUBY end it 'does not register an offense in case when' do expect_no_offenses(<<-RUBY.strip_indent) case foo when bar a, b = 1, 2 else a, b = 2, 1 end RUBY end end end context 'configured to check conditions with multiple statements' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => false, 'IncludeTernaryExpressions' => true, 'EnforcedStyle' => 'assign_to_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'keyword', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end context 'assignment as the last statement' do it 'registers an offense in if else with more than variable assignment' do source = <<-RUBY.strip_indent if foo method_call bar = 1 else method_call bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense in if elsif else with more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent if foo method_call bar = 1 elsif foobar method_call bar = 2 else method_call bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'register an offense for multiple assignment in if else' do source = <<-RUBY.strip_indent if baz foo = 1 bar = 1 else foo = 2 bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense for multiple assignment in if elsif else' do source = <<-RUBY.strip_indent if baz foo = 1 bar = 1 elsif foobar foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows multiple assignment in if elsif elsif else' do source = <<-RUBY.strip_indent if baz foo = 1 bar = 1 elsif foobar foo = 2 bar = 2 elsif barfoo foo = 3 bar = 3 else foo = 4 bar = 4 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows out of order multiple assignment in if elsif else' do expect_no_offenses(<<-RUBY.strip_indent) if baz bar = 1 foo = 1 elsif foobar foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY end it 'allows multiple assignment in unless else' do source = <<-RUBY.strip_indent unless baz foo = 1 bar = 1 else foo = 2 bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows multiple assignments in case when with only one when' do source = <<-RUBY.strip_indent case foo when foobar foo = 1 bar = 1 else foo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'allows multiple assignments in case when with multiple whens' do source = <<-RUBY.strip_indent case foo when foobar foo = 1 bar = 1 when foobaz foo = 2 bar = 2 else foo = 3 bar = 3 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense in if elsif else with some branches only ' \ 'containing variable assignment and others containing more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent if foo bar = 1 elsif foobar method_call bar = 2 elsif baz bar = 3 else method_call bar = 4 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense in unless else with more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent unless foo method_call bar = 1 else method_call bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end it 'registers an offense in case when else with more than ' \ 'variable assignment' do source = <<-RUBY.strip_indent case foo when foobar method_call bar = 1 else method_call bar = 2 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end context 'multiple assignment in only one branch' do it 'registers an offense when multiple assignment is in if' do source = <<-RUBY.strip_indent if foo baz = 1 bar = 1 elsif foobar method_call bar = 2 else other_method bar = 3 end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'registers an offense when multiple assignment is in elsif' do source = <<-RUBY.strip_indent if foo method_call bar = 1 elsif foobar baz = 2 bar = 2 else other_method bar = 3 end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'registers an offense when multiple assignment is in else' do source = <<-RUBY.strip_indent if foo method_call bar = 1 elsif foobar other_method bar = 2 else baz = 3 bar = 3 end RUBY inspect_source(source) expect(cop.offenses.size).to eq(1) end end end it 'allows assignment in multiple branches when it is ' \ 'wrapped in a modifier' do source = <<-RUBY.strip_indent if foo bar << 1 bar << 2 else bar << 3 bar << 4 if foobar end RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'registers an offense for multiple assignment when an earlier ' \ 'assignment is is protected by a modifier' do source = <<-RUBY.strip_indent if foo bar << 1 bar << 2 else bar << 3 if foobar bar << 4 end RUBY inspect_source(source) expect(cop.messages).to eq([message]) end context 'auto-correct' do it 'corrects multiple assignment in if else' do source = <<-RUBY.strip_indent if foo baz = 1 bar = 1 else baz = 3 bar = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo baz = 1 1 else baz = 3 3 end RUBY end it 'corrects multiple assignment in if elsif else' do source = <<-RUBY.strip_indent if foo baz = 1 bar = 1 elsif foobar baz = 2 bar = 2 else baz = 3 bar = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo baz = 1 1 elsif foobar baz = 2 2 else baz = 3 3 end RUBY end it 'corrects multiple assignment in if elsif else with multiple elsifs' do source = <<-RUBY.strip_indent if foo baz = 1 bar = 1 elsif foobar baz = 2 bar = 2 elsif foobaz baz = 3 bar = 3 else baz = 4 bar = 4 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = if foo baz = 1 1 elsif foobar baz = 2 2 elsif foobaz baz = 3 3 else baz = 4 4 end RUBY end it 'corrects multiple assignment in case when' do source = <<-RUBY.strip_indent case foo when foobar baz = 1 bar = 1 else baz = 2 bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = case foo when foobar baz = 1 1 else baz = 2 2 end RUBY end it 'corrects multiple assignment in case when with multiple whens' do source = <<-RUBY.strip_indent case foo when foobar baz = 1 bar = 1 when foobaz baz = 2 bar = 2 else baz = 3 bar = 3 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = case foo when foobar baz = 1 1 when foobaz baz = 2 2 else baz = 3 3 end RUBY end it 'corrects multiple assignment in unless else' do source = <<-RUBY.strip_indent unless foo baz = 1 bar = 1 else baz = 2 bar = 2 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) bar = unless foo baz = 1 1 else baz = 2 2 end RUBY end it 'corrects assignment in an if statement that is nested ' \ 'in unless else' do source = <<-RUBY.strip_indent unless foo if foobar baz = 1 elsif qux baz = 2 else baz = 3 end else baz = 4 end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) unless foo baz = if foobar 1 elsif qux 2 else 3 end else baz = 4 end RUBY end end end context 'EndAlignment configured to start_of_line' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => false, 'IncludeTernaryExpressions' => true }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'start_of_line', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) context 'auto-correct' do it 'uses proper end alignment in if' do source = <<-RUBY.strip_indent if foo a = b elsif bar a = c else a = d end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) a = if foo b elsif bar c else d end RUBY end it 'uses proper end alignment in unless' do source = <<-RUBY.strip_indent unless foo a = b else a = d end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) a = unless foo b else d end RUBY end it 'uses proper end alignment in case' do source = <<-RUBY.strip_indent case foo when bar a = b when baz a = c else a = d end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) a = case foo when bar b when baz c else d end RUBY end end end end context 'IncludeTernaryExpressions false' do let(:config) do RuboCop::Config.new('Style/ConditionalAssignment' => { 'Enabled' => true, 'SingleLineConditionsOnly' => true, 'IncludeTernaryExpressions' => false, 'EnforcedStyle' => 'assign_to_condition', 'SupportedStyles' => %w[assign_to_condition assign_inside_condition] }, 'Lint/EndAlignment' => { 'EnforcedStyleAlignWith' => 'keyword', 'Enabled' => true }, 'Metrics/LineLength' => { 'Max' => 80, 'Enabled' => true }) end it 'allows assignment in ternary operation' do expect_no_offenses('foo? ? bar = "a" : bar = "b"') end end end rubocop-0.52.1/spec/rubocop/cop/style/copyright_spec.rb000066400000000000000000000122411322072016200231360ustar00rootroot00000000000000# frozen_string_literal: true def expect_copyright_offense(cop, source) inspect_source(source) expect(cop.offenses.size).to eq(1) end RSpec.describe RuboCop::Cop::Style::Copyright, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'Notice' => 'Copyright (\(c\) )?2015 Acme Inc' } } it 'does not register an offense when the notice is present' do expect_no_offenses(<<-RUBY.strip_indent) # Copyright 2015 Acme Inc. # test2 names = Array.new names << 'James' RUBY end it 'does not register an offense when the notice is not the first comment' do expect_no_offenses(<<-RUBY.strip_indent) # test2 # Copyright 2015 Acme Inc. names = Array.new names << 'James' RUBY end it 'does not register an offense when the notice is in a block comment' do expect_no_offenses(<<-RUBY.strip_indent) =begin blah, blah, blah Copyright 2015 Acme Inc. =end names = Array.new names << 'James' RUBY end context 'when the copyright notice is missing' do let(:source) { <<-RUBY.strip_indent } # test # test2 names = Array.new names << 'James' RUBY it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)).to eq(<<-RUBY.strip_indent) # Copyright (c) 2015 Acme Inc. # test # test2 names = Array.new names << 'James' RUBY end it 'fails to autocorrect when the AutocorrectNotice does ' \ 'not match the Notice pattern' do cop_config['AutocorrectNotice'] = '# Copyleft (c) 2015 Acme Inc.' expect do autocorrect_source(source) end.to raise_error(RuboCop::Warning) end it 'fails to autocorrect if no AutocorrectNotice is given' do # cop_config['AutocorrectNotice'] = '# Copyleft (c) 2015 Acme Inc.' expect do autocorrect_source(source) end.to raise_error(RuboCop::Warning) end end context 'when the copyright notice comes after any code' do let(:source) { <<-RUBY.strip_indent } # test2 names = Array.new # Copyright (c) 2015 Acme Inc. names << 'James' RUBY it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)).to eq(<<-RUBY.strip_indent) # Copyright (c) 2015 Acme Inc. # test2 names = Array.new # Copyright (c) 2015 Acme Inc. names << 'James' RUBY end end context 'when the source code file is empty' do let(:source) { '' } it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)) .to eq("# Copyright (c) 2015 Acme Inc.\n") end end context 'when the copyright notice is missing and ' \ 'the source code file starts with a shebang' do let(:source) { <<-RUBY.strip_indent } #!/usr/bin/env ruby names = Array.new names << 'James' RUBY it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # Copyright (c) 2015 Acme Inc. names = Array.new names << 'James' RUBY end end context 'when the copyright notice is missing and ' \ 'the source code file starts with an encoding comment' do let(:source) { <<-RUBY.strip_indent } # encoding: utf-8 names = Array.new names << 'James' RUBY it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)).to eq(<<-RUBY.strip_indent) # encoding: utf-8 # Copyright (c) 2015 Acme Inc. names = Array.new names << 'James' RUBY end end context 'when the copyright notice is missing and ' \ 'the source code file starts with shebang and ' \ 'an encoding comment' do let(:source) { <<-RUBY.strip_indent } #!/usr/bin/env ruby # encoding: utf-8 names = Array.new names << 'James' RUBY it 'adds an offense' do expect_copyright_offense(cop, source) end it 'correctly autocorrects the source code' do cop_config['AutocorrectNotice'] = '# Copyright (c) 2015 Acme Inc.' expect(autocorrect_source(source)).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # Copyright (c) 2015 Acme Inc. names = Array.new names << 'James' RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/date_time_spec.rb000066400000000000000000000024421322072016200230630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::DateTime do subject(:cop) { described_class.new } it 'registers an offense when using DateTime for current time' do expect_offense(<<-RUBY.strip_indent) DateTime.now ^^^^^^^^^^^^ Prefer Date or Time over DateTime. RUBY end it 'registers an offense when using ::DateTime for current time' do expect_offense(<<-RUBY.strip_indent) ::DateTime.now ^^^^^^^^^^^^^^ Prefer Date or Time over DateTime. RUBY end it 'registers an offense when using DateTime for modern date' do expect_offense(<<-RUBY.strip_indent) DateTime.iso8601('2016-06-29') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer Date or Time over DateTime. RUBY end it 'does not register an offense when using Time for current time' do expect_no_offenses('Time.now') end it 'does not register an offense when using Date for modern date' do expect_no_offenses("Date.iso8601('2016-06-29')") end it 'does not register an offense when using DateTime for historic date' do expect_no_offenses("DateTime.iso8601('2016-06-29', Date::ENGLAND)") end it 'does not register an offense when using DateTime in another namespace' do expect_no_offenses('Icalendar::Values::DateTime.new(start_at)') end end rubocop-0.52.1/spec/rubocop/cop/style/def_with_parentheses_spec.rb000066400000000000000000000020011322072016200253110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::DefWithParentheses do subject(:cop) { described_class.new } it 'reports an offense for def with empty parens' do src = <<-RUBY.strip_indent def func() end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for class def with empty parens' do src = <<-RUBY.strip_indent def Test.func() end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts def with arg and parens' do expect_no_offenses(<<-RUBY.strip_indent) def func(a) end RUBY end it 'accepts empty parentheses in one liners' do expect_no_offenses("def to_s() join '/' end") end it 'auto-removes unneeded parens' do new_source = autocorrect_source(<<-RUBY.strip_indent) def test(); something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def test; something end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/dir_spec.rb000066400000000000000000000021751322072016200217110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Dir, :config do subject(:cop) { described_class.new(config) } shared_examples 'auto-correct' do |original, expected| it 'auto-corrects' do new_source = autocorrect_source(original) expect(new_source).to eq(expected) end end it 'registers an offense when using `#expand_path` and `#dirname`' do expect_offense(<<-RUBY.strip_indent) File.expand_path(File.dirname(__FILE__)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `__dir__` to get an absolute path to the current file's directory. RUBY end it_behaves_like 'auto-correct', 'File.expand_path(File.dirname(__FILE__))', '__dir__' it 'registers an offense when using `#dirname` and `#realpath`' do expect_offense(<<-RUBY.strip_indent) File.dirname(File.realpath(__FILE__)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `__dir__` to get an absolute path to the current file's directory. RUBY end it_behaves_like 'auto-correct', 'File.dirname(File.realpath(__FILE__))', '__dir__' end rubocop-0.52.1/spec/rubocop/cop/style/documentation_method_spec.rb000066400000000000000000000477721322072016200253600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::DocumentationMethod, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end let(:require_for_non_public_methods) { false } let(:config) do RuboCop::Config.new( 'Style/CommentAnnotation' => { 'Keywords' => %w[TODO FIXME OPTIMIZE HACK REVIEW] }, 'Style/DocumentationMethod' => { 'RequireForNonPublicMethods' => require_for_non_public_methods } ) end let(:message) { 'Missing method documentation comment.' } context 'when declaring methods outside a class' do context 'without documentation comment' do context 'when method is public' do it_behaves_like 'code with offense', <<-CODE def foo puts 'bar' end CODE it_behaves_like 'code with offense', 'def method; end' end context 'when method is private' do it_behaves_like 'code without offense', <<-CODE private def foo puts 'bar' end CODE it_behaves_like 'code without offense', <<-CODE private def foo; end CODE it_behaves_like 'code without offense', <<-CODE private def foo puts 'bar' end CODE it_behaves_like 'code without offense', 'private def method; end' context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE private def foo puts 'bar' end CODE it_behaves_like 'code with offense', <<-CODE private def foo; end CODE it_behaves_like 'code with offense', <<-CODE private def foo puts 'bar' end CODE it_behaves_like 'code with offense', 'private def method; end' end end context 'when method is protected' do it_behaves_like 'code without offense', <<-CODE protected def foo puts 'bar' end CODE it_behaves_like 'code without offense', <<-CODE protected def foo puts 'bar' end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE protected def foo puts 'bar' end CODE it_behaves_like 'code with offense', <<-CODE protected def foo puts 'bar' end CODE end end end context 'with documentation comment' do it_behaves_like 'code without offense', <<-CODE # Documentation def foo puts 'bar' end CODE it_behaves_like 'code without offense', <<-CODE # Documentation def foo; end CODE end context 'with both public and private methods' do it_behaves_like 'code with offense', <<-CODE def foo puts 'bar' end private def baz puts 'bar' end CODE it_behaves_like 'code without offense', <<-CODE # Documentation def foo puts 'bar' end private def baz puts 'bar' end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE # Documentation def foo puts 'bar' end private def baz puts 'bar' end CODE end end context 'when declaring methods in a class' do context 'without documentation comment' do context 'wheh method is public' do it_behaves_like 'code with offense', <<-CODE class Foo def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE class Foo def method; end end CODE end context 'when method is private' do it_behaves_like 'code without offense', <<-CODE class Foo private def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE class Foo private def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE class Foo private def bar; end end CODE it_behaves_like 'code without offense', <<-CODE class Foo private def bar; end end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE class Foo private def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE class Foo private def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE class Foo private def bar; end end CODE it_behaves_like 'code with offense', <<-CODE class Foo private def bar; end end CODE end end end context 'with documentation comment' do context 'when method is public' do it_behaves_like 'code without offense', <<-CODE class Foo # Documentation def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE class Foo # Documentation def bar; end end CODE end end context 'with annotation comment' do it_behaves_like 'code with offense', <<-CODE class Foo # FIXME: offense def bar puts 'baz' end end CODE end context 'with directive comment' do it_behaves_like 'code with offense', <<-CODE class Foo # rubocop:disable Style/For def bar puts 'baz' end end CODE end context 'with both public and private methods' do it_behaves_like 'code with offense', <<-CODE class Foo def bar puts 'baz' end private def baz puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE class Foo # Documentation def bar puts 'baz' end private def baz puts 'baz' end end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE class Foo # Documentation def bar puts 'baz' end private def baz puts 'baz' end end CODE end end end context 'when declaring methods in a module' do context 'without documentation comment' do context 'wheh method is public' do it_behaves_like 'code with offense', <<-CODE module Foo def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE module Foo def method; end end CODE end context 'when method is private' do it_behaves_like 'code without offense', <<-CODE module Foo private def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE module Foo private def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE module Foo private def bar; end end CODE it_behaves_like 'code without offense', <<-CODE module Foo private def bar; end end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE module Foo private def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE module Foo private def bar puts 'baz' end end CODE it_behaves_like 'code with offense', <<-CODE module Foo private def bar; end end CODE it_behaves_like 'code with offense', <<-CODE module Foo private def bar; end end CODE end end end context 'with documentation comment' do context 'when method is public' do it_behaves_like 'code without offense', <<-CODE module Foo # Documentation def bar puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE module Foo # Documentation def bar; end end CODE end end context 'with both public and private methods' do it_behaves_like 'code with offense', <<-CODE module Foo def bar puts 'baz' end private def baz puts 'baz' end end CODE it_behaves_like 'code without offense', <<-CODE module Foo # Documentation def bar puts 'baz' end private def baz puts 'baz' end end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE module Foo # Documentation def bar puts 'baz' end private def baz puts 'baz' end end CODE end end end context 'when declaring methods for class instance' do context 'without documentation comment' do it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new def foo.bar puts 'baz' end CODE it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new def foo.bar; end CODE end context 'with documentation comment' do it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new # Documentation def foo.bar puts 'baz' end CODE it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new # Documentation def foo.bar; end CODE context 'when method is private' do it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.bar private def foo.bar; end CODE it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar puts 'baz' end CODE it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar; end CODE it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar puts 'baz' end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.bar private def foo.bar; end CODE it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar puts 'baz' end CODE it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar; end CODE it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new private def foo.bar puts 'baz' end CODE end end context 'with both public and private methods' do it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new def foo.bar puts 'baz' end private def foo.baz puts 'baz' end CODE it_behaves_like 'code without offense', <<-CODE class Foo; end foo = Foo.new # Documentation def foo.bar puts 'baz' end private def foo.baz puts 'baz' end CODE context 'when required for non-public methods' do let(:require_for_non_public_methods) { true } it_behaves_like 'code with offense', <<-CODE class Foo; end foo = Foo.new # Documentation def foo.bar puts 'baz' end private def foo.baz puts 'baz' end CODE end end end end end end rubocop-0.52.1/spec/rubocop/cop/style/documentation_spec.rb000066400000000000000000000175041322072016200240060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Documentation do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/CommentAnnotation' => { 'Keywords' => %w[TODO FIXME OPTIMIZE HACK REVIEW] }) end it 'registers an offense for non-empty class' do expect_offense(<<-RUBY.strip_indent) class My_Class ^^^^^ Missing top-level class documentation comment. def method end end RUBY end it 'does not consider comment followed by empty line to be class ' \ 'documentation' do inspect_source(<<-RUBY.strip_indent) # Copyright 2014 # Some company class My_Class def method end end RUBY expect(cop.offenses.size).to eq(1) end it 'registers an offense for non-namespace' do expect_offense(<<-RUBY.strip_indent) module My_Class ^^^^^^ Missing top-level module documentation comment. def method end end RUBY end it 'registers an offense for empty module without documentation' do # Because why would you have an empty module? It requires some # explanation. expect_offense(<<-RUBY.strip_indent) module Test ^^^^^^ Missing top-level module documentation comment. end RUBY end it 'accepts non-empty class with documentation' do expect_no_offenses(<<-RUBY.strip_indent) # class comment class My_Class def method end end RUBY end it 'registers an offense for non-empty class with annotation comment' do expect_offense(<<-RUBY.strip_indent) # OPTIMIZE: Make this faster. class My_Class ^^^^^ Missing top-level class documentation comment. def method end end RUBY end it 'registers an offense for non-empty class with directive comment' do expect_offense(<<-RUBY.strip_indent) # rubocop:disable Style/For class My_Class ^^^^^ Missing top-level class documentation comment. def method end end RUBY end it 'registers offense for non-empty class with frozen string comment' do expect_offense(<<-RUBY.strip_indent) # frozen_string_literal: true class My_Class ^^^^^ Missing top-level class documentation comment. def method end end RUBY end it 'registers an offense for non-empty class with encoding comment' do expect_offense(<<-RUBY.strip_indent) # encoding: ascii-8bit class My_Class ^^^^^ Missing top-level class documentation comment. def method end end RUBY end it 'accepts non-empty class with annotation comment followed by other ' \ 'comment' do inspect_source(<<-RUBY.strip_indent) # OPTIMIZE: Make this faster. # Class comment. class My_Class def method end end RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts non-empty class with comment that ends with an annotation' do expect_no_offenses(<<-RUBY.strip_indent) # Does fooing. # FIXME: Not yet implemented. class Foo def initialize end end RUBY end it 'accepts non-empty module with documentation' do expect_no_offenses(<<-RUBY.strip_indent) # class comment module My_Class def method end end RUBY end it 'accepts empty class without documentation' do expect_no_offenses(<<-RUBY.strip_indent) class My_Class end RUBY end it 'accepts namespace module without documentation' do expect_no_offenses(<<-RUBY.strip_indent) module Test class A; end class B; end end RUBY end it 'accepts namespace class without documentation' do expect_no_offenses(<<-RUBY.strip_indent) class Test class A; end class B; end end RUBY end it 'accepts namespace class which defines constants' do expect_no_offenses(<<-RUBY.strip_indent) class Test A = Class.new B = Class.new(A) C = Class.new { call_method } D = 1 end RUBY end it 'accepts namespace module which defines constants' do expect_no_offenses(<<-RUBY.strip_indent) module Test A = Class.new B = Class.new(A) C = Class.new { call_method } D = 1 end RUBY end it 'does not raise an error for an implicit match conditional' do expect do inspect_source(<<-RUBY.strip_indent) class Test if // end end RUBY end.not_to raise_error end it 'registers an offense if the comment line contains code' do expect_offense(<<-RUBY.strip_indent) module A # The A Module class B ^^^^^ Missing top-level class documentation comment. C = 1 def method end end end RUBY end context 'sparse and trailing comments' do %w[class module].each do |keyword| it "ignores comments after #{keyword} node end" do inspect_source(<<-RUBY.strip_indent) module TestModule # documentation comment #{keyword} Test def method end end # decorating comment end RUBY expect(cop.offenses.empty?).to be(true) end it "ignores sparse comments inside #{keyword} node" do inspect_source(<<-RUBY.strip_indent) module TestModule #{keyword} Test def method end # sparse comment end end RUBY expect(cop.offenses.size).to eq(1) end end end context 'with # :nodoc:' do %w[class module].each do |keyword| it "accepts non-namespace #{keyword} without documentation" do inspect_source(<<-RUBY.strip_indent) #{keyword} Test #:nodoc: def method end end RUBY expect(cop.offenses.empty?).to be(true) end it "registers an offense for nested #{keyword} without documentation" do inspect_source(<<-RUBY.strip_indent) module TestModule #:nodoc: TEST = 20 #{keyword} Test def method end end end RUBY expect(cop.offenses.size).to eq(1) end context 'with `all` modifier' do it "accepts nested #{keyword} without documentation" do inspect_source(<<-RUBY.strip_indent) module A #:nodoc: all module B TEST = 20 #{keyword} Test TEST = 20 end end end RUBY expect(cop.offenses.empty?).to be(true) end end end context 'on a subclass' do it 'accepts non-namespace subclass without documentation' do expect_no_offenses(<<-RUBY.strip_indent) class Test < Parent #:nodoc: def method end end RUBY end it 'registers an offense for nested subclass without documentation' do expect_offense(<<-RUBY.strip_indent) module TestModule #:nodoc: TEST = 20 class Test < Parent ^^^^^ Missing top-level class documentation comment. def method end end end RUBY end context 'with `all` modifier' do it 'accepts nested subclass without documentation' do expect_no_offenses(<<-RUBY.strip_indent) module A #:nodoc: all module B TEST = 20 class Test < Parent TEST = 20 end end end RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/style/double_negation_spec.rb000066400000000000000000000007611322072016200242700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::DoubleNegation do subject(:cop) { described_class.new } it 'registers an offense for !!' do expect_offense(<<-RUBY.strip_indent) !!test.something ^ Avoid the use of double negation (`!!`). RUBY end it 'does not register an offense for !' do expect_no_offenses('!test.something') end it 'does not register an offense for not not' do expect_no_offenses('not not test.something') end end rubocop-0.52.1/spec/rubocop/cop/style/each_for_simple_loop_spec.rb000066400000000000000000000074521322072016200253060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EachForSimpleLoop do subject(:cop) { described_class.new } OFFENSE_MSG = 'Use `Integer#times` for a simple loop ' \ 'which iterates a fixed number of times.'.freeze it 'registers offense for inclusive end range' do expect_offense(<<-RUBY.strip_indent) (0..10).each {} ^^^^^^^^^^^^ Use `Integer#times` for a simple loop which iterates a fixed number of times. RUBY end it 'registers offense for exclusive end range' do expect_offense(<<-RUBY.strip_indent) (0...10).each {} ^^^^^^^^^^^^^ Use `Integer#times` for a simple loop which iterates a fixed number of times. RUBY end it 'registers offense for exclusive end range with do ... end syntax' do expect_offense(<<-RUBY.strip_indent) (0...10).each do ^^^^^^^^^^^^^ Use `Integer#times` for a simple loop which iterates a fixed number of times. end RUBY end it 'registers an offense for range not starting with zero' do expect_offense(<<-RUBY.strip_indent) (3..7).each do ^^^^^^^^^^^ Use `Integer#times` for a simple loop which iterates a fixed number of times. end RUBY end it 'does not register offense if range startpoint is not constant' do expect_no_offenses('(a..10).each {}') end it 'does not register offense if range endpoint is not constant' do expect_no_offenses('(0..b).each {}') end it 'does not register offense for inline block with parameters' do expect_no_offenses('(0..10).each { |n| puts n }') end it 'does not register offense for multiline block with parameters' do expect_no_offenses(<<-RUBY.strip_indent) (0..10).each do |n| end RUBY end it 'does not register offense for character range' do expect_no_offenses("('a'..'b').each {}") end context 'when using an inclusive range' do it 'autocorrects the source with inline block' do corrected = autocorrect_source('(0..10).each {}') expect(corrected).to eq '11.times {}' end it 'autocorrects the source with multiline block' do corrected = autocorrect_source(<<-RUBY.strip_indent) (0..10).each do end RUBY expect(corrected).to eq <<-RUBY.strip_indent 11.times do end RUBY end it 'autocorrects the range not starting with zero' do corrected = autocorrect_source(<<-RUBY.strip_indent) (3..7).each do end RUBY expect(corrected).to eq <<-RUBY.strip_indent 5.times do end RUBY end it 'does not autocorrect range not starting with zero and using param' do source = <<-RUBY.strip_indent (3..7).each do |n| end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(source) end end context 'when using an exclusive range' do it 'autocorrects the source with inline block' do corrected = autocorrect_source('(0...10).each {}') expect(corrected).to eq '10.times {}' end it 'autocorrects the source with multiline block' do corrected = autocorrect_source(<<-RUBY.strip_indent) (0...10).each do end RUBY expect(corrected).to eq <<-RUBY.strip_indent 10.times do end RUBY end it 'autocorrects the range not starting with zero' do corrected = autocorrect_source(<<-RUBY.strip_indent) (3...7).each do end RUBY expect(corrected).to eq <<-RUBY.strip_indent 4.times do end RUBY end it 'does not autocorrect range not starting with zero and using param' do source = <<-RUBY.strip_indent (3...7).each do |n| end RUBY corrected = autocorrect_source(source) expect(corrected).to eq(source) end end end rubocop-0.52.1/spec/rubocop/cop/style/each_with_object_spec.rb000066400000000000000000000051701322072016200244120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EachWithObject do subject(:cop) { described_class.new } it 'finds inject and reduce with passed in and returned hash' do expect_offense(<<-RUBY.strip_indent) [].inject({}) { |a, e| a } ^^^^^^ Use `each_with_object` instead of `inject`. [].reduce({}) do |a, e| ^^^^^^ Use `each_with_object` instead of `reduce`. a[e] = 1 a[e] = 1 a end RUBY end it 'correctly autocorrects' do corrected = autocorrect_source(<<-RUBY.strip_indent) [1, 2, 3].inject({}) do |h, i| h[i] = i h end RUBY expect(corrected).to eq(['[1, 2, 3].each_with_object({}) do |i, h|', ' h[i] = i', ' ', 'end', ''].join("\n")) end it 'correctly autocorrects with return value only' do corrected = autocorrect_source(<<-RUBY.strip_indent) [1, 2, 3].inject({}) do |h, i| h end RUBY expect(corrected).to eq(['[1, 2, 3].each_with_object({}) do |i, h|', ' ', 'end', ''].join("\n")) end it 'ignores inject and reduce with passed in, but not returned hash' do expect_no_offenses(<<-RUBY.strip_indent) [].inject({}) do |a, e| a + e end [].reduce({}) do |a, e| my_method e, a end RUBY end it 'ignores inject and reduce with empty body' do expect_no_offenses(<<-RUBY.strip_indent) [].inject({}) do |a, e| end [].reduce({}) { |a, e| } RUBY end it 'ignores inject and reduce with condition as body' do expect_no_offenses(<<-RUBY.strip_indent) [].inject({}) do |a, e| a = e if e end [].inject({}) do |a, e| if e a = e end end [].reduce({}) do |a, e| a = e ? e : 2 end RUBY end it 'ignores inject and reduce passed in symbol' do expect_no_offenses('[].inject(:+)') end it 'does not blow up for reduce with no arguments' do expect_no_offenses('[1, 2, 3].inject { |a, e| a + e }') end it 'ignores inject/reduce with assignment to accumulator param in block' do expect_no_offenses(<<-RUBY.strip_indent) r = [1, 2, 3].reduce({}) do |memo, item| memo += item > 2 ? item : 0 memo end RUBY end context 'when a simple literal is passed as initial value' do it 'ignores inject/reduce' do expect_no_offenses('array.reduce(0) { |a, e| a }') end end end rubocop-0.52.1/spec/rubocop/cop/style/empty_block_parameter_spec.rb000066400000000000000000000043141322072016200255000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyBlockParameter do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense for an empty block parameter with do-end wtyle' do expect_offense(<<-RUBY.strip_indent) a do || ^^ Omit pipes for the empty block parameters. end RUBY end it 'registers an offense for an empty block parameter with {} style' do expect_offense(<<-RUBY.strip_indent) a { || do_something } ^^ Omit pipes for the empty block parameters. RUBY end it 'registers an offense for an empty block parameter with super' do expect_offense(<<-RUBY) def foo super { || do_something } ^^ Omit pipes for the empty block parameters. end RUBY end it 'auto-corrects for do-end style' do new_source = autocorrect_source(<<-RUBY.strip_indent) a do || end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a do end RUBY end it 'auto-corrects for {} style' do new_source = autocorrect_source(<<-RUBY.strip_indent) a { || do_something } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a { do_something } RUBY end it 'auto-corrects for a keyword lambda' do new_source = autocorrect_source(<<-RUBY.strip_indent) lambda { || do_something } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) lambda { do_something } RUBY end it 'accepts a block that is do-end style without parameter' do expect_no_offenses(<<-RUBY.strip_indent) a do end RUBY end it 'accepts a block that is {} style without parameter' do expect_no_offenses(<<-RUBY.strip_indent) a { } RUBY end it 'accepts a non-empty block parameter with do-end style' do expect_no_offenses(<<-RUBY.strip_indent) a do |x| end RUBY end it 'accepts a non-empty block parameter with {} style' do expect_no_offenses(<<-RUBY.strip_indent) a { |x| } RUBY end it 'accepts an empty block parameter with a lambda' do expect_no_offenses(<<-RUBY.strip_indent) -> () { do_something } RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/empty_case_condition_spec.rb000066400000000000000000000105361322072016200253320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyCaseCondition do subject(:cop) { described_class.new } let(:message) do 'Do not use empty `case` condition, instead use an `if` expression.' end shared_examples 'detect/correct empty case, accept non-empty case' do it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq [message] end it 'correctly autocorrects' do expect(autocorrect_source(source)).to eq corrected_source end let(:source_with_case) { source.sub(/case/, 'case :a') } it 'accepts the source with case' do inspect_source(source_with_case) expect(cop.messages.empty?).to be(true) end end context 'given a case statement with an empty case' do context 'with multiple when branches and an else' do let(:source) do <<-RUBY.strip_indent case when 1 == 2 foo when 1 == 1 bar else baz end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if 1 == 2 foo elsif 1 == 1 bar else baz end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with multiple when branches and no else' do let(:source) do <<-RUBY.strip_indent case when 1 == 2 foo when 1 == 1 bar end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if 1 == 2 foo elsif 1 == 1 bar end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with a single when branch and an else' do let(:source) do <<-RUBY.strip_indent case when 1 == 2 foo else bar end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if 1 == 2 foo else bar end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with a single when branch and no else' do let(:source) do <<-RUBY.strip_indent case when 1 == 2 foo end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if 1 == 2 foo end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with a when branch including comma-delimited alternatives' do let(:source) do <<-RUBY.strip_indent case when false foo when nil, false, 1 bar when false, 1 baz end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if false foo elsif nil || false || 1 bar elsif false || 1 baz end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with when branches using then' do let(:source) do <<-RUBY.strip_indent case when false then foo when nil, false, 1 then bar when false, 1 then baz end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if false then foo elsif nil || false || 1 then bar elsif false || 1 then baz end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end context 'with first when branch including comma-delimited alternatives' do let(:source) do <<-RUBY.strip_indent case when my.foo?, my.bar? something when my.baz? something_else end RUBY end let(:corrected_source) do <<-RUBY.strip_indent if my.foo? || my.bar? something elsif my.baz? something_else end RUBY end it_behaves_like 'detect/correct empty case, accept non-empty case' end end end rubocop-0.52.1/spec/rubocop/cop/style/empty_else_spec.rb000066400000000000000000000350321322072016200232770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyElse do subject(:cop) { described_class.new(config) } let(:missing_else_config) { {} } shared_examples 'auto-correct' do |keyword| context 'MissingElse is disabled' do it 'does auto-correction' do expect(autocorrect_source(source)).to eq(corrected_source) end end %w[both if case].each do |missing_else_style| context "MissingElse is #{missing_else_style}" do let(:missing_else_config) do { 'Enabled' => true, 'EnforcedStyle' => missing_else_style } end if ['both', keyword].include? missing_else_style it 'does not auto-correct' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end else it 'does auto-correction' do expect(autocorrect_source(source)).to eq(corrected_source) end end end end end shared_examples_for 'offense registration' do it 'registers an offense with correct message' do inspect_source(source) expect(cop.messages).to eq(['Redundant `else`-clause.']) end it 'registers an offense with correct location' do inspect_source(source) expect(cop.highlights).to eq(['else']) end end context 'configured to warn on empty else' do let(:config) do RuboCop::Config.new('Style/EmptyElse' => { 'EnforcedStyle' => 'empty', 'SupportedStyles' => %w[empty nil both] }, 'Style/MissingElse' => missing_else_config) end context 'given an if-statement' do context 'with a completely empty else-clause' do context 'using semicolons' do let(:source) { 'if a; foo else end' } let(:corrected_source) { 'if a; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'not using semicolons' do let(:source) do ['if a', ' foo', 'else', 'end'].join("\n") end let(:corrected_source) do ['if a', ' foo', 'end'].join("\n") end it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('if cond; foo end') end end context 'in an if-statement' do let(:source) { <<-RUBY.strip_indent } if cond if cond2 something else end end RUBY let(:corrected_source) { <<-RUBY.strip_indent } if cond if cond2 something end end RUBY it_behaves_like 'auto-correct', 'if' it_behaves_like 'offense registration' end context 'with an empty comment' do let(:source) { <<-RUBY.strip_indent } if cond something else # TODO end RUBY let(:corrected_source) { <<-RUBY.strip_indent } if cond something else # TODO end RUBY it_behaves_like 'auto-correct', 'if' it_behaves_like 'offense registration' end end context 'given an unless-statement' do context 'with a completely empty else-clause' do let(:source) { 'unless cond; foo else end' } let(:corrected_source) { 'unless cond; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo end') end end end context 'given a case statement' do context 'with a completely empty else-clause' do let(:source) { 'case v; when a; foo else end' } let(:corrected_source) { 'case v; when a; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'case' end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; end') end end end end context 'configured to warn on nil in else' do let(:config) do RuboCop::Config.new('Style/EmptyElse' => { 'EnforcedStyle' => 'nil', 'SupportedStyles' => %w[empty nil both] }, 'Style/MissingElse' => missing_else_config) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do context 'when standalone' do let(:source) do ['if a', ' foo', 'elsif b', ' bar', 'else', ' nil', 'end'].join("\n") end let(:corrected_source) do ['if a', ' foo', 'elsif b', ' bar', 'end'].join("\n") end it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'when the result is assigned to a variable' do let(:source) do ['foobar = if a', ' foo', ' elsif b', ' bar', ' else', ' nil', ' end'].join("\n") end let(:corrected_source) do ['foobar = if a', ' foo', ' elsif b', ' bar', ' end'].join("\n") end it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end end context 'with an else-clause containing only the literal nil ' \ 'using semicolons' do context 'with one elsif' do let(:source) { 'if a; foo elsif b; bar else nil end' } let(:corrected_source) { 'if a; foo elsif b; bar end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with multiple elsifs' do let(:source) { 'if a; foo elsif b; bar; elsif c; bar else nil end' } let(:corrected_source) { 'if a; foo elsif b; bar; elsif c; bar end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('if cond; foo end') end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do let(:source) { 'unless cond; foo else nil end' } let(:corrected_source) { 'unless cond; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo end') end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do context 'using semicolons' do let(:source) { 'case v; when a; foo; when b; bar; else nil end' } let(:corrected_source) { 'case v; when a; foo; when b; bar; end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'case' end context 'when the result is assigned to a variable' do let(:source) do ['foobar = case v', ' when a', ' foo', ' when b', ' bar', ' else', ' nil', ' end'].join("\n") end let(:corrected_source) do ['foobar = case v', ' when a', ' foo', ' when b', ' bar', ' end'].join("\n") end it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'case' end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; end') end end end end context 'configured to warn on empty else and nil in else' do let(:config) do RuboCop::Config.new('Style/EmptyElse' => { 'EnforcedStyle' => 'both', 'SupportedStyles' => %w[empty nil both] }, 'Style/MissingElse' => missing_else_config) end context 'given an if-statement' do context 'with a completely empty else-clause' do let(:source) { 'if a; foo else end' } let(:corrected_source) { 'if a; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with an else-clause containing only the literal nil' do context 'with one elsif' do let(:source) { 'if a; foo elsif b; bar else nil end' } let(:corrected_source) { 'if a; foo elsif b; bar end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with multiple elsifs' do let(:source) { 'if a; foo elsif b; bar; elsif c; bar else nil end' } let(:corrected_source) { 'if a; foo elsif b; bar; elsif c; bar end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('if cond; foo end') end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do let(:source) { 'unless cond; foo else end' } let(:corrected_source) { 'unless cond; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with an else-clause containing only the literal nil' do let(:source) { 'unless cond; foo else nil end' } let(:corrected_source) { 'unless cond; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'if' end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo end') end end end context 'given a case statement' do context 'with a completely empty else-clause' do let(:source) { 'case v; when a; foo else end' } let(:corrected_source) { 'case v; when a; foo end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'case' end context 'with an else-clause containing only the literal nil' do let(:source) { 'case v; when a; foo; when b; bar; else nil end' } let(:corrected_source) { 'case v; when a; foo; when b; bar; end' } it_behaves_like 'offense registration' it_behaves_like 'auto-correct', 'case' end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; end') end end end end end rubocop-0.52.1/spec/rubocop/cop/style/empty_lambda_parameter_spec.rb000066400000000000000000000015721322072016200256310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyLambdaParameter do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense for an empty block parameter with a lambda' do expect_offense(<<-RUBY.strip_indent) -> () { do_something } ^^ Omit parentheses for the empty lambda parameters. RUBY end it 'auto-corrects for a lambda' do new_source = autocorrect_source(<<-RUBY.strip_indent) -> () { do_something } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) -> { do_something } RUBY end it 'accepts a keyword lambda' do expect_no_offenses(<<-RUBY) lambda { || do_something } RUBY end it 'does not crash on a super' do expect_no_offenses(<<-RUBY) def foo super { || do_something } end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/empty_literal_spec.rb000066400000000000000000000117001322072016200237770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyLiteral do subject(:cop) { described_class.new } describe 'Empty Array' do it 'registers an offense for Array.new()' do expect_offense(<<-RUBY.strip_indent) test = Array.new() ^^^^^^^^^^^ Use array literal `[]` instead of `Array.new`. RUBY end it 'registers an offense for Array.new' do expect_offense(<<-RUBY.strip_indent) test = Array.new ^^^^^^^^^ Use array literal `[]` instead of `Array.new`. RUBY end it 'does not register an offense for Array.new(3)' do expect_no_offenses('test = Array.new(3)') end it 'auto-corrects Array.new to []' do new_source = autocorrect_source('test = Array.new') expect(new_source).to eq('test = []') end it 'auto-corrects Array.new in block in block' do source = 'puts { Array.new }' new_source = autocorrect_source(source) expect(new_source).to eq 'puts { [] }' end it 'does not registers an offense Array.new with block' do expect_no_offenses('test = Array.new { 1 }') end it 'does not register Array.new with block in other block' do expect_no_offenses('puts { Array.new { 1 } }') end end describe 'Empty Hash' do it 'registers an offense for Hash.new()' do expect_offense(<<-RUBY.strip_indent) test = Hash.new() ^^^^^^^^^^ Use hash literal `{}` instead of `Hash.new`. RUBY end it 'registers an offense for Hash.new' do expect_offense(<<-RUBY.strip_indent) test = Hash.new ^^^^^^^^ Use hash literal `{}` instead of `Hash.new`. RUBY end it 'does not register an offense for Hash.new(3)' do expect_no_offenses('test = Hash.new(3)') end it 'does not register an offense for Hash.new { block }' do expect_no_offenses('test = Hash.new { block }') end it 'auto-corrects Hash.new to {}' do new_source = autocorrect_source('Hash.new') expect(new_source).to eq('{}') end it 'auto-corrects Hash.new in block ' do source = 'puts { Hash.new }' new_source = autocorrect_source(source) expect(new_source).to eq 'puts { {} }' end it 'auto-corrects Hash.new to {} in various contexts' do new_source = autocorrect_source(<<-RUBY.strip_indent) test = Hash.new Hash.new.merge("a" => 3) yadayada.map { a }.reduce(Hash.new, :merge) RUBY expect(new_source) .to eq(<<-RUBY.strip_indent) test = {} {}.merge("a" => 3) yadayada.map { a }.reduce({}, :merge) RUBY end it 'auto-correct Hash.new to {} as the only parameter to a method' do source = 'yadayada.map { a }.reduce Hash.new' new_source = autocorrect_source(source) expect(new_source).to eq('yadayada.map { a }.reduce({})') end it 'auto-correct Hash.new to {} as the first parameter to a method' do source = 'yadayada.map { a }.reduce Hash.new, :merge' new_source = autocorrect_source(source) expect(new_source).to eq('yadayada.map { a }.reduce({}, :merge)') end end describe 'Empty String' do it 'registers an offense for String.new()' do expect_offense(<<-RUBY.strip_indent) test = String.new() ^^^^^^^^^^^^ Use string literal `''` instead of `String.new`. RUBY end it 'registers an offense for String.new' do expect_offense(<<-RUBY.strip_indent) test = String.new ^^^^^^^^^^ Use string literal `''` instead of `String.new`. RUBY end it 'does not register an offense for String.new("top")' do expect_no_offenses('test = String.new("top")') end it 'auto-corrects String.new to empty string literal' do new_source = autocorrect_source('test = String.new') expect(new_source).to eq("test = ''") end context 'when double-quoted string literals are preferred' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( 'Style/StringLiterals' => { 'EnforcedStyle' => 'double_quotes' } ) end it 'registers an offense for String.new' do expect_offense(<<-RUBY.strip_indent) test = String.new ^^^^^^^^^^ Use string literal `""` instead of `String.new`. RUBY end it 'auto-corrects String.new to a double-quoted empty string literal' do new_source = autocorrect_source('test = String.new') expect(new_source).to eq('test = ""') end end context 'when frozen string literals is enabled' do let(:ruby_version) { 2.3 } it 'does not register an offense for String.new' do expect_no_offenses(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true test = String.new RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/empty_method_spec.rb000066400000000000000000000133231322072016200236260ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EmptyMethod, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'when configured with compact style' do let(:cop_config) { { 'EnforcedStyle' => 'compact' } } let(:message) { 'Put empty method definitions on a single line.' } context 'with an empty instance method definition' do it_behaves_like 'code with offense', ['def foo', 'end'].join("\n"), 'def foo; end' it_behaves_like 'code with offense', ['def foo(bar, baz)', 'end'].join("\n"), 'def foo(bar, baz); end' it_behaves_like 'code with offense', ['def foo', '', 'end'].join("\n"), 'def foo; end' it_behaves_like 'code without offense', 'def foo; end' end context 'with a non-empty instance method definition' do it_behaves_like 'code without offense', ['def foo', ' bar', 'end'] it_behaves_like 'code without offense', 'def foo; bar; end' it_behaves_like 'code without offense', ['def foo', ' # bar', 'end'] end context 'with an empty class method definition' do it_behaves_like 'code with offense', ['def self.foo', 'end'].join("\n"), 'def self.foo; end' it_behaves_like 'code with offense', ['def self.foo(bar, baz)', 'end'].join("\n"), 'def self.foo(bar, baz); end' it_behaves_like 'code with offense', ['def self.foo', '', 'end'].join("\n"), 'def self.foo; end' it_behaves_like 'code without offense', 'def self.foo; end' end context 'with a non-empty class method definition' do it_behaves_like 'code without offense', ['def self.foo', ' bar', 'end'] it_behaves_like 'code without offense', 'def self.foo; bar; end' it_behaves_like 'code without offense', ['def self.foo', ' # bar', 'end'] end end context 'when configured with expanded style' do let(:cop_config) { { 'EnforcedStyle' => 'expanded' } } let(:message) do 'Put the `end` of empty method definitions on the next line.' end context 'with an empty instance method definition' do it_behaves_like 'code without offense', ['def foo', 'end'].join("\n") it_behaves_like 'code without offense', ['def foo', '', 'end'].join("\n") it_behaves_like 'code with offense', 'def foo; end', ['def foo', 'end'].join("\n") end context 'with a non-empty instance method definition' do it_behaves_like 'code without offense', ['def foo', ' bar', 'end'] it_behaves_like 'code without offense', 'def foo; bar; end' it_behaves_like 'code without offense', ['def foo', ' # bar', 'end'] end context 'with an empty class method definition' do it_behaves_like 'code without offense', ['def self.foo', 'end'].join("\n") it_behaves_like 'code without offense', ['def self.foo', '', 'end'].join("\n") it_behaves_like 'code with offense', 'def self.foo; end', ['def self.foo', 'end'].join("\n") end context 'with a non-empty class method definition' do it_behaves_like 'code without offense', ['def self.foo', ' bar', 'end'] it_behaves_like 'code without offense', 'def self.foo; bar; end' it_behaves_like 'code without offense', ['def self.foo', ' # bar', 'end'] end context 'when method is nested in class scope' do it_behaves_like 'code with offense', ['class Foo', ' def bar; end', 'end'].join("\n"), ['class Foo', ' def bar', ' end', 'end'].join("\n") end end end rubocop-0.52.1/spec/rubocop/cop/style/encoding_spec.rb000066400000000000000000000041521322072016200227160ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Encoding, :config do subject(:cop) { described_class.new(config) } it 'registers no offense when no encoding present' do inspect_source('def foo() end') expect(cop.offenses.empty?).to be(true) end it 'registers no offense when encoding present but not UTF-8' do inspect_source(<<-RUBY.strip_indent) # encoding: us-ascii def foo() end RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense when encoding present and UTF-8' do inspect_source(<<-RUBY.strip_indent) # encoding: utf-8 def foo() end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Unnecessary utf-8 encoding comment.'] ) end it 'registers an offense when encoding present on 2nd line after shebang' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 def foo() end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Unnecessary utf-8 encoding comment.'] ) end it 'registers an offense for vim-style encoding comments' do inspect_source(<<-RUBY.strip_indent) # vim:filetype=ruby, fileencoding=utf-8 def foo() end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Unnecessary utf-8 encoding comment.'] ) end it 'registers no offense when encoding is in the wrong place' do inspect_source(<<-RUBY.strip_indent) def foo() end # encoding: utf-8 RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for encoding inserted by magic_encoding gem' do inspect_source(<<-RUBY.strip_indent) # -*- encoding : utf-8 -*- def foo() 'ä' end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq( ['Unnecessary utf-8 encoding comment.'] ) end context 'auto-correct' do it 'removes encoding comment on first line' do new_source = autocorrect_source("# encoding: utf-8\nblah") expect(new_source).to eq('blah') end end end rubocop-0.52.1/spec/rubocop/cop/style/end_block_spec.rb000066400000000000000000000004101322072016200230410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EndBlock do subject(:cop) { described_class.new } it 'reports an offense for an END block' do src = 'END { test }' inspect_source(src) expect(cop.offenses.size).to eq(1) end end rubocop-0.52.1/spec/rubocop/cop/style/eval_with_location_spec.rb000066400000000000000000000100151322072016200247750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EvalWithLocation do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using `#eval` without any arguments' do expect_offense(<<-RUBY.strip_indent) eval <<-CODE ^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#eval` with `binding` only' do expect_offense(<<-RUBY.strip_indent) eval <<-CODE, binding ^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#eval` without lineno' do expect_offense(<<-RUBY.strip_indent) eval <<-CODE, binding, __FILE__ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#eval` with an incorrect line number' do expect_offense(<<-RUBY.strip_indent) eval 'do_something', binding, __FILE__, __LINE__ + 1 ^^^^^^^^^^^^ Use `__LINE__` instead of `__LINE__ + 1`, as they are used by backtraces. RUBY end it 'registers an offense when using `#eval` with a heredoc and ' \ 'an incorrect line number' do expect_offense(<<-RUBY.strip_indent) eval <<-CODE, binding, __FILE__, __LINE__ + 2 ^^^^^^^^^^^^ Use `__LINE__ + 1` instead of `__LINE__ + 2`, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#eval` with a string on a new line ' do expect_offense(<<-RUBY.strip_indent) eval('puts 42', binding, __FILE__, __LINE__) ^^^^^^^^ Use `__LINE__ - 3` instead of `__LINE__`, as they are used by backtraces. RUBY end it 'registers an offense when using `#class_eval` without any arguments' do expect_offense(<<-RUBY.strip_indent) C.class_eval <<-CODE ^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#module_eval` without any arguments' do expect_offense(<<-RUBY.strip_indent) M.module_eval <<-CODE ^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#instance_eval` without any arguments' do expect_offense(<<-RUBY.strip_indent) foo.instance_eval <<-CODE ^^^^^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces. do_something CODE RUBY end it 'registers an offense when using `#class_eval` with an incorrect lineno' do expect_offense(<<-RUBY.strip_indent) C.class_eval <<-CODE, __FILE__, __LINE__ ^^^^^^^^ Use `__LINE__ + 1` instead of `__LINE__`, as they are used by backtraces. do_something CODE RUBY end it 'accepts `eval` with a heredoc, a filename and `__LINE__ + 1`' do expect_no_offenses(<<-RUBY.strip_indent) eval <<-CODE, binding, __FILE__, __LINE__ + 1 do_something CODE RUBY end it 'accepts `eval` with a code that is a variable' do expect_no_offenses(<<-RUBY.strip_indent) code = something eval code RUBY end it 'accepts `eval` with a string, a filename and `__LINE__`' do expect_no_offenses(<<-RUBY.strip_indent) eval 'do_something', binding, __FILE__, __LINE__ RUBY end it 'accepts `eval` with a string, a filename and `__LINE__` on a new line' do expect_no_offenses(<<-RUBY.strip_indent) eval 'do_something', binding, __FILE__, __LINE__ - 1 RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/even_odd_spec.rb000066400000000000000000000104201322072016200227060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::EvenOdd do subject(:cop) { described_class.new } it 'registers an offense for x % 2 == 0' do expect_offense(<<-RUBY.strip_indent) x % 2 == 0 ^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'registers an offense for x % 2 != 0' do expect_offense(<<-RUBY.strip_indent) x % 2 != 0 ^^^^^^^^^^ Replace with `Integer#odd?`. RUBY end it 'registers an offense for (x % 2) == 0' do expect_offense(<<-RUBY.strip_indent) (x % 2) == 0 ^^^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'registers an offense for (x % 2) != 0' do expect_offense(<<-RUBY.strip_indent) (x % 2) != 0 ^^^^^^^^^^^^ Replace with `Integer#odd?`. RUBY end it 'registers an offense for x % 2 == 1' do expect_offense(<<-RUBY.strip_indent) x % 2 == 1 ^^^^^^^^^^ Replace with `Integer#odd?`. RUBY end it 'registers an offense for x % 2 != 1' do expect_offense(<<-RUBY.strip_indent) x % 2 != 1 ^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'registers an offense for (x % 2) == 1' do expect_offense(<<-RUBY.strip_indent) (x % 2) == 1 ^^^^^^^^^^^^ Replace with `Integer#odd?`. RUBY end it 'registers an offense for (x % 2) != 1' do expect_offense(<<-RUBY.strip_indent) (x % 2) != 1 ^^^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'registers an offense for (x.y % 2) != 1' do expect_offense(<<-RUBY.strip_indent) (x.y % 2) != 1 ^^^^^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'registers an offense for (x(y) % 2) != 1' do expect_offense(<<-RUBY.strip_indent) (x(y) % 2) != 1 ^^^^^^^^^^^^^^^ Replace with `Integer#even?`. RUBY end it 'accepts x % 3 == 0' do expect_no_offenses('x % 3 == 0') end it 'accepts x % 3 != 0' do expect_no_offenses('x % 3 != 0') end it 'converts x % 2 == 0 to #even?' do corrected = autocorrect_source('x % 2 == 0') expect(corrected).to eq('x.even?') end it 'converts x % 2 != 0 to #odd?' do corrected = autocorrect_source('x % 2 != 0') expect(corrected).to eq('x.odd?') end it 'converts (x % 2) == 0 to #even?' do corrected = autocorrect_source('(x % 2) == 0') expect(corrected).to eq('x.even?') end it 'converts (x % 2) != 0 to #odd?' do corrected = autocorrect_source('(x % 2) != 0') expect(corrected).to eq('x.odd?') end it 'converts x % 2 == 1 to odd?' do corrected = autocorrect_source('x % 2 == 1') expect(corrected).to eq('x.odd?') end it 'converts x % 2 != 1 to even?' do corrected = autocorrect_source('x % 2 != 1') expect(corrected).to eq('x.even?') end it 'converts (x % 2) == 1 to odd?' do corrected = autocorrect_source('(x % 2) == 1') expect(corrected).to eq('x.odd?') end it 'converts (y % 2) != 1 to even?' do corrected = autocorrect_source('(y % 2) != 1') expect(corrected).to eq('y.even?') end it 'converts (x.y % 2) != 1 to even?' do corrected = autocorrect_source('(x.y % 2) != 1') expect(corrected).to eq('x.y.even?') end it 'converts (x(y) % 2) != 1 to even?' do corrected = autocorrect_source('(x(y) % 2) != 1') expect(corrected).to eq('x(y).even?') end it 'converts (x._(y) % 2) != 1 to even?' do corrected = autocorrect_source('(x._(y) % 2) != 1') expect(corrected).to eq('x._(y).even?') end it 'converts (x._(y)) % 2 != 1 to even?' do corrected = autocorrect_source('(x._(y)) % 2 != 1') expect(corrected).to eq('(x._(y)).even?') end it 'converts x._(y) % 2 != 1 to even?' do corrected = autocorrect_source('x._(y) % 2 != 1') expect(corrected).to eq('x._(y).even?') end it 'converts 1 % 2 != 1 to even?' do corrected = autocorrect_source('1 % 2 != 1') expect(corrected).to eq('1.even?') end it 'converts complex examples' do corrected = autocorrect_source(<<-RUBY.strip_indent) if (y % 2) != 1 method == :== ? :even : :odd elsif x % 2 == 1 method == :== ? :odd : :even end RUBY expect(corrected).to eq(<<-RUBY.strip_indent) if y.even? method == :== ? :even : :odd elsif x.odd? method == :== ? :odd : :even end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/flip_flop_spec.rb000066400000000000000000000013311322072016200230760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::FlipFlop do subject(:cop) { described_class.new } it 'registers an offense for inclusive flip flops' do expect_offense(<<-RUBY.strip_indent) DATA.each_line do |line| print line if (line =~ /begin/)..(line =~ /end/) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid the use of flip flop operators. end RUBY end it 'registers an offense for exclusive flip flops' do expect_offense(<<-RUBY.strip_indent) DATA.each_line do |line| print line if (line =~ /begin/)...(line =~ /end/) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid the use of flip flop operators. end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/for_spec.rb000066400000000000000000000056031322072016200217200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::For, :config do subject(:cop) { described_class.new(config) } context 'when each is the enforced style' do let(:cop_config) { { 'EnforcedStyle' => 'each' } } it 'registers an offense for for' do inspect_source(<<-RUBY.strip_indent) def func for n in [1, 2, 3] do puts n end end RUBY expect(cop.messages).to eq(['Prefer `each` over `for`.']) expect(cop.highlights).to eq(['for']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'for') end it 'registers an offense for opposite + correct style' do inspect_source(<<-RUBY.strip_indent) def func for n in [1, 2, 3] do puts n end [1, 2, 3].each do |n| puts n end end RUBY expect(cop.messages).to eq(['Prefer `each` over `for`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts multiline each' do expect_no_offenses(<<-RUBY.strip_indent) def func [1, 2, 3].each do |n| puts n end end RUBY end it 'accepts :for' do expect_no_offenses('[:for, :ala, :bala]') end it 'accepts def for' do expect_no_offenses('def for; end') end end context 'when for is the enforced style' do let(:cop_config) { { 'EnforcedStyle' => 'for' } } it 'accepts for' do expect_no_offenses(<<-RUBY.strip_indent) def func for n in [1, 2, 3] do puts n end end RUBY end it 'registers an offense for multiline each' do inspect_source(<<-RUBY.strip_indent) def func [1, 2, 3].each do |n| puts n end end RUBY expect(cop.messages).to eq(['Prefer `for` over `each`.']) expect(cop.highlights).to eq(['each']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'each') end it 'registers an offense for correct + opposite style' do inspect_source(<<-RUBY.strip_indent) def func for n in [1, 2, 3] do puts n end [1, 2, 3].each do |n| puts n end end RUBY expect(cop.messages).to eq(['Prefer `for` over `each`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts single line each' do expect_no_offenses(<<-RUBY.strip_indent) def func [1, 2, 3].each { |n| puts n } end RUBY end context 'when using safe navigation operator' do let(:ruby_version) { 2.3 } it 'does not break' do expect_no_offenses(<<-RUBY.strip_indent) def func [1, 2, 3]&.each { |n| puts n } end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/format_string_spec.rb000066400000000000000000000150361322072016200240110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::FormatString, :config do subject(:cop) { described_class.new(config) } context 'when enforced style is sprintf' do let(:cop_config) { { 'EnforcedStyle' => 'sprintf' } } it 'registers an offense for a string followed by something' do expect_offense(<<-RUBY.strip_indent) puts "%d" % 10 ^ Favor `sprintf` over `String#%`. RUBY end it 'registers an offense for something followed by an array' do expect_offense(<<-RUBY.strip_indent) puts x % [10, 11] ^ Favor `sprintf` over `String#%`. RUBY end it 'does not register an offense for numbers' do expect_no_offenses('puts 10 % 4') end it 'does not register an offense for ambiguous cases' do expect_no_offenses('puts x % Y') end it 'works if the first operand contains embedded expressions' do expect_offense(<<-'RUBY'.strip_indent) puts "#{x * 5} %d #{@test}" % 10 ^ Favor `sprintf` over `String#%`. RUBY end it 'registers an offense for format' do expect_offense(<<-RUBY.strip_indent) format(something, a, b) ^^^^^^ Favor `sprintf` over `format`. RUBY end it 'registers an offense for format with 2 arguments' do expect_offense(<<-RUBY.strip_indent) format("%X", 123) ^^^^^^ Favor `sprintf` over `format`. RUBY end it 'auto-corrects format' do corrected = autocorrect_source('format(something, a, b)') expect(corrected).to eq 'sprintf(something, a, b)' end it 'auto-corrects String#%' do corrected = autocorrect_source('puts "%d" % 10') expect(corrected).to eq 'puts sprintf("%d", 10)' end it 'auto-corrects String#% with an array argument' do corrected = autocorrect_source('puts x % [10, 11]') expect(corrected).to eq 'puts sprintf(x, 10, 11)' end it 'auto-corrects String#% with a hash argument' do corrected = autocorrect_source('puts x % { a: 10, b: 11 }') expect(corrected).to eq 'puts sprintf(x, a: 10, b: 11)' end end context 'when enforced style is format' do let(:cop_config) { { 'EnforcedStyle' => 'format' } } it 'registers an offense for a string followed by something' do expect_offense(<<-RUBY.strip_indent) puts "%d" % 10 ^ Favor `format` over `String#%`. RUBY end it 'registers an offense for something followed by an array' do expect_offense(<<-RUBY.strip_indent) puts x % [10, 11] ^ Favor `format` over `String#%`. RUBY end it 'registers an offense for something followed by a hash' do expect_offense(<<-RUBY.strip_indent) puts x % { a: 10, b: 11 } ^ Favor `format` over `String#%`. RUBY end it 'does not register an offense for numbers' do expect_no_offenses('puts 10 % 4') end it 'does not register an offense for ambiguous cases' do expect_no_offenses('puts x % Y') end it 'works if the first operand contains embedded expressions' do expect_offense(<<-'RUBY'.strip_indent) puts "#{x * 5} %d #{@test}" % 10 ^ Favor `format` over `String#%`. RUBY end it 'registers an offense for sprintf' do expect_offense(<<-RUBY.strip_indent) sprintf(something, a, b) ^^^^^^^ Favor `format` over `sprintf`. RUBY end it 'registers an offense for sprintf with 2 arguments' do expect_offense(<<-RUBY.strip_indent) sprintf('%020d', 123) ^^^^^^^ Favor `format` over `sprintf`. RUBY end it 'auto-corrects sprintf' do corrected = autocorrect_source('sprintf(something, a, b)') expect(corrected).to eq 'format(something, a, b)' end it 'auto-corrects String#%' do corrected = autocorrect_source('puts "%d" % 10') expect(corrected).to eq 'puts format("%d", 10)' end it 'auto-corrects String#% with an array argument' do corrected = autocorrect_source('puts x % [10, 11]') expect(corrected).to eq 'puts format(x, 10, 11)' end it 'auto-corrects String#% with a hash argument' do corrected = autocorrect_source('puts x % { a: 10, b: 11 }') expect(corrected).to eq 'puts format(x, a: 10, b: 11)' end end context 'when enforced style is percent' do let(:cop_config) { { 'EnforcedStyle' => 'percent' } } it 'registers an offense for format' do expect_offense(<<-RUBY.strip_indent) format(something, a, b) ^^^^^^ Favor `String#%` over `format`. RUBY end it 'registers an offense for sprintf' do expect_offense(<<-RUBY.strip_indent) sprintf(something, a, b) ^^^^^^^ Favor `String#%` over `sprintf`. RUBY end it 'registers an offense for sprintf with 3 arguments' do expect_offense(<<-RUBY.strip_indent) format("%d %04x", 123, 123) ^^^^^^ Favor `String#%` over `format`. RUBY end it 'accepts format with 1 argument' do expect_no_offenses('format :xml') end it 'accepts sprintf with 1 argument' do expect_no_offenses('sprintf :xml') end it 'accepts format without arguments' do expect_no_offenses('format') end it 'accepts sprintf without arguments' do expect_no_offenses('sprintf') end it 'accepts String#%' do expect_no_offenses('puts "%d" % 10') end it 'auto-corrects format with 2 arguments' do corrected = autocorrect_source('format(something, a)') expect(corrected).to eq 'something % a' end it 'auto-corrects format with 3 arguments' do corrected = autocorrect_source('format(something, a, b)') expect(corrected).to eq 'something % [a, b]' end it 'auto-corrects format with a hash argument' do corrected = autocorrect_source('format(something, a: 10, b: 11)') expect(corrected).to eq 'something % { a: 10, b: 11 }' end it 'auto-corrects sprintf with 2 arguments' do corrected = autocorrect_source('sprintf(something, a)') expect(corrected).to eq 'something % a' end it 'auto-corrects sprintf with 3 arguments' do corrected = autocorrect_source('sprintf(something, a, b)') expect(corrected).to eq 'something % [a, b]' end it 'auto-corrects sprintf with a hash argument' do corrected = autocorrect_source('sprintf(something, a: 10, b: 11)') expect(corrected).to eq 'something % { a: 10, b: 11 }' end end end rubocop-0.52.1/spec/rubocop/cop/style/format_string_token_spec.rb000066400000000000000000000116651322072016200252150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::FormatStringToken, :config do subject(:cop) { described_class.new(config) } let(:enforced_style) { :annotated } let(:cop_config) do { 'EnforcedStyle' => enforced_style, 'SupportedStyles' => %i[annotated template unannotated] } end shared_examples 'format string token style' do |name, good, bad| bad_style1 = bad context "when enforced style is #{name}" do let(:enforced_style) { name } it "registers offenses for #{bad_style1}" do inspect_source([ '<<-HEREDOC', "foo #{good} + bar #{bad_style1}", 'HEREDOC' ]) expect(cop.highlights).to eql([bad_style1]) end it 'supports dynamic string with interpolation' do inspect_source( %("a\#{b}#{good} c\#{d}#{bad_style1} e\#{f}") ) expect(cop.highlights).to eql([bad_style1]) end it 'sets the enforced style to annotated after inspecting "%s"' do inspect_source('"%s"') expect(cop.config_to_allow_offenses).to eq( 'EnforcedStyle' => 'annotated' ) end it 'configures the enforced style to template after inspecting "%{a}"' do inspect_source('"%{a}"') expect(cop.config_to_allow_offenses).to eq( 'EnforcedStyle' => 'template' ) end end end shared_examples 'enforced styles for format string tokens' do |token| template = '%{template}' annotated = "%#{token}" include_examples 'format string token style', :annotated, annotated, template include_examples 'format string token style', :template, template, annotated end shared_examples 'offense message' do |enforced_style, source, message| context "when enforced style is #{enforced_style}" do let(:enforced_style) { enforced_style } it 'gives a helpful error message' do inspect_source(source) expect(cop.messages.first).to eql(message) end end end it 'ignores xstr' do expect_no_offenses('`echo "%s %s %{template}"`') end it 'ignores regexp' do expect_no_offenses('/foo bar %u/') end it 'ignores `%r` regexp' do expect_no_offenses('%r{foo bar %u}') end %i[strptime strftime].each do |method_name| it "ignores time format (when used as argument to #{method_name})" do expect_no_offenses(<<-RUBY.strip_indent) Time.#{method_name}('2017-12-13', '%Y-%m-%d') RUBY end end it 'ignores time format when it is stored in a variable' do expect_no_offenses(<<-RUBY.strip_indent) time_format = '%Y-%m-%d' Time.strftime('2017-12-13', time_format) RUBY end it 'handles dstrs' do inspect_source('"c#{b}%{template}"') expect(cop.highlights).to eql(['%{template}']) end it 'ignores http links' do expect_no_offenses(<<-RUBY.strip_indent) 'https://ru.wikipedia.org/wiki/%D0%90_'\ '(%D0%BA%D0%B8%D1%80%D0%B8%D0%BB%D0%BB%D0%B8%D1%86%D0%B0)' RUBY end it 'handles __FILE__' do expect_no_offenses('__FILE__') end it_behaves_like 'enforced styles for format string tokens', 'A' it_behaves_like 'enforced styles for format string tokens', 'B' it_behaves_like 'enforced styles for format string tokens', 'E' it_behaves_like 'enforced styles for format string tokens', 'G' it_behaves_like 'enforced styles for format string tokens', 'X' it_behaves_like 'enforced styles for format string tokens', 'a' it_behaves_like 'enforced styles for format string tokens', 'b' it_behaves_like 'enforced styles for format string tokens', 'c' it_behaves_like 'enforced styles for format string tokens', 'd' it_behaves_like 'enforced styles for format string tokens', 'e' it_behaves_like 'enforced styles for format string tokens', 'f' it_behaves_like 'enforced styles for format string tokens', 'g' it_behaves_like 'enforced styles for format string tokens', 'i' it_behaves_like 'enforced styles for format string tokens', 'o' it_behaves_like 'enforced styles for format string tokens', 'p' it_behaves_like 'enforced styles for format string tokens', 's' it_behaves_like 'enforced styles for format string tokens', 'u' it_behaves_like 'enforced styles for format string tokens', 'x' include_examples( 'offense message', :annotated, '"%{foo}"', 'Prefer annotated tokens (like `%s`) ' \ 'over template tokens (like `%{foo}`).' ) include_examples( 'offense message', :template, '"%d"', 'Prefer template tokens (like `%{foo}`) ' \ 'over annotated tokens (like `%s`).' ) include_examples( 'offense message', :unannotated, '"%{foo}"', 'Prefer unannotated tokens (like `%s`) ' \ 'over template tokens (like `%{foo}`).' ) end rubocop-0.52.1/spec/rubocop/cop/style/frozen_string_literal_comment_spec.rb000066400000000000000000000460131322072016200272610ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::FrozenStringLiteralComment, :config do subject(:cop) { described_class.new(config) } context 'always' do let(:cop_config) do { 'Enabled' => true, 'EnforcedStyle' => 'always' } end it 'accepts an empty source' do expect_no_offenses('') end it 'accepts a source with no tokens' do expect_no_offenses(' ') end it 'accepts a frozen string literal on the top line' do expect_no_offenses(<<-RUBY.strip_indent) # frozen_string_literal: true puts 1 RUBY end it 'accepts a disabled frozen string literal on the top line' do expect_no_offenses(<<-RUBY.strip_indent) # frozen_string_literal: false puts 1 RUBY end it 'registers an offense for not having a frozen string literal comment ' \ 'on the top line' do inspect_source('puts 1') expect(cop.messages) .to eq(['Missing magic comment `# frozen_string_literal: true`.']) end it 'registers an offense for not having a frozen string literal comment ' \ 'under a shebang' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby puts 1 RUBY expect(cop.messages) .to eq(['Missing magic comment `# frozen_string_literal: true`.']) end it 'accepts a frozen string literal below a shebang comment' do expect_no_offenses(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true puts 1 RUBY end it 'accepts a disabled frozen string literal below a shebang comment' do expect_no_offenses(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false puts 1 RUBY end it 'registers an offense for not having a frozen string literal comment ' \ 'under an encoding comment' do inspect_source(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY expect(cop.messages) .to eq(['Missing magic comment `# frozen_string_literal: true`.']) end it 'accepts a frozen string literal below an encoding comment' do expect_no_offenses(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY end it 'accepts a dsabled frozen string literal below an encoding comment' do expect_no_offenses(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY end it 'registers an offense for not having a frozen string literal comment ' \ 'under a shebang and an encoding comment' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY expect(cop.messages) .to eq(['Missing magic comment `# frozen_string_literal: true`.']) end it 'accepts a frozen string literal comment below shebang and encoding ' \ 'comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a disabled frozen string literal comment below shebang and ' \ 'encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a frozen string literal comment below shebang above an ' \ 'encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true # encoding: utf-8 puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a disabled frozen string literal comment below shebang above ' \ 'an encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false # encoding: utf-8 puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts an emacs style combined magic comment' do expect_no_offenses(<<-RUBY.strip_indent) #!/usr/bin/env ruby # -*- encoding: UTF-8; frozen_string_literal: true -*- # encoding: utf-8 puts 1 RUBY end context 'auto-correct' do it 'adds a frozen string literal comment to the first line if one is ' \ 'missing' do new_source = autocorrect_source(<<-RUBY.strip_indent) puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # frozen_string_literal: true puts 1 RUBY end it 'adds a frozen string literal comment after a shebang' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true puts 1 RUBY end it 'adds a frozen string literal comment after an encoding comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY end it 'adds a frozen string literal comment after a shebang and encoding ' \ 'comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY end it 'adds a frozen string literal comment after a shebang and encoding ' \ 'comment when there is an empty line before the code' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY end it 'adds a frozen string literal comment after an encoding comment ' \ 'when there is an empty line before the code' do new_source = autocorrect_source(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY end end end context 'when_needed' do let(:cop_config) do { 'Enabled' => true, 'EnforcedStyle' => 'when_needed' } end it 'accepts an empty source' do expect_no_offenses('') end if RUBY_VERSION >= '2.3.0' context 'ruby >= 2.3' do context 'no frozen string literal comment' do it 'accepts not modifing a string' do expect_no_offenses('puts "x"') end it 'accepts calling + on a string' do expect_no_offenses('"x" + "y"') end it 'accepts calling freeze on a variable' do expect_no_offenses(<<-RUBY.strip_indent) foo = "x" foo.freeze RUBY end it 'accepts calling shovel on a variable' do expect_no_offenses(<<-RUBY.strip_indent) foo = "x" foo << "y" RUBY end it 'accepts freezing a string' do expect_no_offenses('"x".freeze') end it 'accepts when << is called on a string literal' do expect_no_offenses('"x" << "y"') end end it 'accepts freezing a string when there is a frozen string literal ' \ 'comment' do inspect_source(<<-RUBY.strip_indent) # frozen_string_literal: true "x".freeze RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts shoveling into a string when there is a frozen string ' \ 'literal comment' do inspect_source(<<-RUBY.strip_indent) # frozen_string_literal: true "x" << "y" RUBY expect(cop.offenses.empty?).to be(true) end end end context 'target_ruby_version < 2.3', :ruby22 do it 'accepts freezing a string' do expect_no_offenses('"x".freeze') end it 'accepts calling << on a string' do expect_no_offenses('"x" << "y"') end it 'accepts freezing a string with interpolation' do expect_no_offenses('"#{foo}bar".freeze') end it 'accepts calling << on a string with interpolation' do expect_no_offenses('"#{foo}bar" << "baz"') end end context 'target_ruby_version 2.3+', :ruby23 do it 'accepts freezing a string' do expect_offense(<<-RUBY.strip_indent) "x".freeze ^ Missing magic comment `# frozen_string_literal: true`. RUBY end it 'accepts calling << on a string' do expect_offense(<<-RUBY.strip_indent) "x" << "y" ^ Missing magic comment `# frozen_string_literal: true`. RUBY end it 'accepts freezing a string with interpolation' do expect_offense(<<-'RUBY'.strip_indent) "#{foo}bar".freeze ^ Missing magic comment `# frozen_string_literal: true`. RUBY end it 'accepts calling << on a string with interpolation' do expect_offense(<<-'RUBY'.strip_indent) "#{foo}bar" << "baz" ^ Missing magic comment `# frozen_string_literal: true`. RUBY end end end context 'never' do let(:cop_config) do { 'Enabled' => true, 'EnforcedStyle' => 'never' } end it 'accepts an empty source' do expect_no_offenses('') end it 'accepts a source with no tokens' do expect_no_offenses(' ') end it 'registers an offense for a frozen string literal comment ' \ 'on the top line' do inspect_source(<<-RUBY.strip_indent) # frozen_string_literal: true puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: true']) end it 'registers an offense for a disabled frozen string literal comment ' \ 'on the top line' do inspect_source(<<-RUBY.strip_indent) # frozen_string_literal: false puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: false']) end it 'accepts not having a frozen string literal comment on the top line' do expect_no_offenses('puts 1') end it 'accepts not having not having a frozen string literal comment ' \ 'under a shebang' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for a frozen string literal comment ' \ 'below a shebang comment' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: true']) end it 'registers an offense for a disabled frozen string literal ' \ 'below a shebang comment' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: false']) end it 'allows not having a frozen string literal comment ' \ 'under an encoding comment' do inspect_source(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for a frozen string literal comment below ' \ 'an encoding comment' do inspect_source(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: true']) end it 'registers an offense for a dsabled frozen string literal below ' \ 'an encoding comment' do inspect_source(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: false']) end it 'allows not having a frozen string literal comment ' \ 'under a shebang and an encoding comment' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY expect(cop.offenses.empty?).to be(true) end it 'registers an offense for a frozen string literal comment ' \ 'below shebang and encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: true']) end it 'registers an offense for a disabled frozen string literal comment ' \ 'below shebang and encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: false']) end it 'registers an offense for a frozen string literal comment ' \ 'below shebang above an encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true # encoding: utf-8 puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: true']) end it 'registers an offense for a disabled frozen string literal comment ' \ 'below shebang above an encoding comments' do inspect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false # encoding: utf-8 puts 1 RUBY expect(cop.messages).to eq(['Unnecessary frozen string literal comment.']) expect(cop.highlights).to eq(['# frozen_string_literal: false']) end context 'auto-correct' do it 'removes the frozen string literal comment from the top line' do new_source = autocorrect_source(<<-RUBY.strip_indent) # frozen_string_literal: true puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) puts 1 RUBY end it 'removes a disabled frozen string literal comment on the top line' do new_source = autocorrect_source(<<-RUBY.strip_indent) # frozen_string_literal: false puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) puts 1 RUBY end it 'removes a frozen string literal comment below a shebang comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby puts 1 RUBY end it 'removes a disabled frozen string literal below a shebang comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby puts 1 RUBY end it 'removes a frozen string literal comment below an encoding comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY end it 'removes a dsabled frozen string literal below an encoding comment' do new_source = autocorrect_source(<<-RUBY.strip_indent) # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # encoding: utf-8 puts 1 RUBY end it 'removes a frozen string literal comment ' \ 'below shebang and encoding comments' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: true puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY end it 'removes a disabled frozen string literal comment from ' \ 'below shebang and encoding comments' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 # frozen_string_literal: false puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY end it 'removes a frozen string literal comment ' \ 'below shebang above an encoding comments' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: true # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY end it 'removes a disabled frozen string literal comment ' \ 'below shebang above an encoding comments' do new_source = autocorrect_source(<<-RUBY.strip_indent) #!/usr/bin/env ruby # frozen_string_literal: false # encoding: utf-8 puts 1 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #!/usr/bin/env ruby # encoding: utf-8 puts 1 RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/global_vars_spec.rb000066400000000000000000000014611322072016200234230ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::GlobalVars, :config do cop_config = { 'AllowedVariables' => ['$allowed'] } subject(:cop) { described_class.new(config) } let(:cop_config) { cop_config } it 'registers an offense for $custom' do expect_offense(<<-RUBY.strip_indent) puts $custom ^^^^^^^ Do not introduce global variables. RUBY end it 'allows user whitelisted variables' do expect_no_offenses('puts $allowed') end described_class::BUILT_IN_VARS.each do |var| it "does not register an offense for built-in variable #{var}" do inspect_source("puts #{var}") expect(cop.offenses.empty?).to be(true) end end it 'does not register an offense for backrefs like $1' do expect_no_offenses('puts $1') end end rubocop-0.52.1/spec/rubocop/cop/style/guard_clause_spec.rb000066400000000000000000000173341322072016200235740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::GuardClause, :config do let(:cop) { described_class.new(config) } let(:cop_config) { {} } shared_examples 'reports offense' do |body| it 'reports an offense if method body is if / unless without else' do inspect_source(<<-RUBY.strip_indent) def func if something #{body} end end def func unless something #{body} end end RUBY expect(cop.offenses.size).to eq(2) expect(cop.offenses.map(&:line).sort).to eq([2, 8]) expect(cop.messages) .to eq(['Use a guard clause instead of wrapping ' \ 'the code inside a conditional expression.'] * 2) expect(cop.highlights).to eq(%w[if unless]) end it 'reports an offense if method body ends with if / unless without else' do inspect_source(<<-RUBY.strip_indent) def func test if something #{body} end end def func test unless something #{body} end end RUBY expect(cop.offenses.size).to eq(2) expect(cop.offenses.map(&:line).sort).to eq([3, 10]) expect(cop.messages) .to eq(['Use a guard clause instead of wrapping ' \ 'the code inside a conditional expression.'] * 2) expect(cop.highlights).to eq(%w[if unless]) end end it_behaves_like('reports offense', 'work') it_behaves_like('reports offense', '# TODO') it 'does not report an offense if body is if..elsif..end' do expect_no_offenses(<<-RUBY.strip_indent) def func if something a elsif something_else b end end RUBY end it "doesn't report an offense if condition has multiple lines" do expect_no_offenses(<<-RUBY.strip_indent) def func if something && something_else work end end def func unless something && something_else work end end RUBY end it 'accepts a method which body is if / unless with else' do expect_no_offenses(<<-RUBY.strip_indent) def func if something work else test end end def func unless something work else test end end RUBY end it 'accepts a method which body does not end with if / unless' do expect_no_offenses(<<-RUBY.strip_indent) def func if something work end test end def func unless something work end test end RUBY end it 'accepts a method whose body is a modifier if / unless' do expect_no_offenses(<<-RUBY.strip_indent) def func work if something end def func work if something end RUBY end context 'MinBodyLength: 1' do let(:cop_config) do { 'MinBodyLength' => 1 } end it 'reports an offense for if whose body has 1 line' do expect_offense(<<-RUBY.strip_indent) def func if something ^^ Use a guard clause instead of wrapping the code inside a conditional expression. work end end def func unless something ^^^^^^ Use a guard clause instead of wrapping the code inside a conditional expression. work end end RUBY end end context 'MinBodyLength: 4' do let(:cop_config) do { 'MinBodyLength' => 4 } end it 'accepts a method whose body has 3 lines' do expect_no_offenses(<<-RUBY.strip_indent) def func if something work work work end end def func unless something work work work end end RUBY end end context 'Invalid MinBodyLength' do let(:cop_config) do { 'MinBodyLength' => -2 } end it 'fails with an error' do source = <<-RUBY.strip_indent def func if something work end end RUBY expect { inspect_source(source) } .to raise_error('MinBodyLength needs to be a positive integer!') end end shared_examples 'on if nodes which exit current scope' do |kw| it "registers an error with #{kw} in the if branch" do inspect_source(<<-RUBY.strip_indent) if something #{kw} else puts "hello" end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use a guard clause instead of wrapping ' \ 'the code inside a conditional expression.']) end it "registers an error with #{kw} in the else branch" do inspect_source(<<-RUBY.strip_indent) if something puts "hello" else #{kw} end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use a guard clause instead of wrapping ' \ 'the code inside a conditional expression.']) end it "doesn't register an error if condition has multiple lines" do expect_no_offenses(<<-RUBY.strip_indent) if something && something_else #{kw} else puts "hello" end RUBY end it "does not report an offense if #{kw} is inside elsif" do inspect_source(<<-RUBY.strip_indent) if something a elsif something_else #{kw} end RUBY expect(cop.offenses.empty?).to be(true) end it "does not report an offense if #{kw} is inside if..elsif..else..end" do inspect_source(<<-RUBY.strip_indent) if something a elsif something_else b else #{kw} end RUBY expect(cop.offenses.empty?).to be(true) end it "doesn't register an error if control flow expr has multiple lines" do inspect_source(['if something', " #{kw} 'blah blah blah' \\", " 'blah blah blah'", 'else', ' puts "hello"', 'end']) expect(cop.offenses.empty?).to be(true) end it 'registers an error if non-control-flow branch has multiple lines' do inspect_source(['if something', " #{kw}", 'else', ' puts "hello" \\', ' "blah blah blah"', 'end']) expect(cop.offenses.size).to eq(1) end end include_examples('on if nodes which exit current scope', 'return') include_examples('on if nodes which exit current scope', 'next') include_examples('on if nodes which exit current scope', 'break') include_examples('on if nodes which exit current scope', 'raise "error"') context 'method in module' do it 'registers an offense for instance method' do expect_offense(<<-RUBY.strip_indent) module CopTest def test if something ^^ Use a guard clause instead of wrapping the code inside a conditional expression. work end end end RUBY end it 'registers an offense for singleton methods' do expect_offense(<<-RUBY.strip_indent) module CopTest def self.test if something ^^ Use a guard clause instead of wrapping the code inside a conditional expression. work end end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/hash_syntax_spec.rb000066400000000000000000000561031322072016200234640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::HashSyntax, :config do subject(:cop) { described_class.new(config) } context 'configured to enforce ruby19 style' do context 'with SpaceAroundOperators enabled' do let(:config) do RuboCop::Config.new('AllCops' => { 'TargetRubyVersion' => ruby_version }, 'Style/HashSyntax' => cop_config, 'Layout/SpaceAroundOperators' => { 'Enabled' => true }) end let(:cop_config) do { 'EnforcedStyle' => 'ruby19', 'SupportedStyles' => %w[ruby19 hash_rockets], 'UseHashRocketsWithSymbolValues' => false, 'PreferHashRocketsForNonAlnumEndingSymbols' => false }.merge(cop_config_overrides) end let(:cop_config_overrides) { {} } it 'registers offense for hash rocket syntax when new is possible' do inspect_source('x = { :a => 0 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'hash_rockets') end it 'registers an offense for mixed syntax when new is possible' do inspect_source('x = { :a => 0, b: 1 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for hash rockets in method calls' do expect_offense(<<-RUBY.strip_indent) func(3, :a => 0) ^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'accepts hash rockets when keys have different types' do expect_no_offenses('x = { :a => 0, "b" => 1 }') end it 'accepts an empty hash' do expect_no_offenses('{}') end context 'ruby < 2.2', :ruby21 do it 'accepts hash rockets when symbol keys have string in them' do expect_no_offenses('x = { :"string" => 0 }') end end context 'ruby >= 2.2', :ruby22 do it 'registers an offense when symbol keys have strings in them' do expect_offense(<<-RUBY.strip_indent) x = { :"string" => 0 } ^^^^^^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'preserves quotes during autocorrection' do new_source = autocorrect_source("{ :'&&' => foo }") expect(new_source).to eq("{ '&&': foo }") end end context 'if PreferHashRocketsForNonAlnumEndingSymbols is false' do it 'registers an offense for hash rockets when symbols end with ?' do expect_offense(<<-RUBY.strip_indent) x = { :a? => 0 } ^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'registers an offense for hash rockets when symbols end with !' do expect_offense(<<-RUBY.strip_indent) x = { :a! => 0 } ^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end end context 'if PreferHashRocketsForNonAlnumEndingSymbols is true' do let(:cop_config_overrides) do { 'PreferHashRocketsForNonAlnumEndingSymbols' => true } end it 'accepts hash rockets when symbols end with ?' do expect_no_offenses('x = { :a? => 0 }') end it 'accepts hash rockets when symbols end with !' do expect_no_offenses('x = { :a! => 0 }') end end it 'accepts hash rockets when symbol keys end with =' do expect_no_offenses('x = { :a= => 0 }') end it 'accepts hash rockets when symbol characters are not supported' do expect_no_offenses('x = { :[] => 0 }') end it 'registers offense when keys start with an uppercase letter' do expect_offense(<<-RUBY.strip_indent) x = { :A => 0 } ^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'accepts new syntax in a hash literal' do expect_no_offenses('x = { a: 0, b: 1 }') end it 'accepts new syntax in method calls' do expect_no_offenses('func(3, a: 0)') end it 'auto-corrects old to new style' do new_source = autocorrect_source('{ :a => 1, :b => 2}') expect(new_source).to eq('{ a: 1, b: 2}') end it 'auto-corrects even if it interferes with SpaceAroundOperators' do # Clobbering caused by two cops changing in the same range is dealt with # by the auto-correct loop, so there's no reason to avoid a change. new_source = autocorrect_source('{ :a=>1, :b=>2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end # Bug: https://github.com/bbatsov/rubocop/issues/5019 it 'auto-corrects a missing space when hash is used as argument' do new_source = autocorrect_source('foo:bar => 1') expect(new_source).to eq('foo bar: 1') end end context 'with SpaceAroundOperators disabled' do let(:config) do RuboCop::Config.new('AllCops' => { 'TargetRubyVersion' => ruby_version }, 'Style/HashSyntax' => { 'EnforcedStyle' => 'ruby19', 'SupportedStyles' => %w[ruby19 hash_rockets], 'UseHashRocketsWithSymbolValues' => false }, 'Layout/SpaceAroundOperators' => { 'Enabled' => false }) end it 'auto-corrects even if there is no space around =>' do new_source = autocorrect_source('{ :a=>1, :b=>2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end end context 'configured to use hash rockets when symbol values are found' do let(:config) do RuboCop::Config.new('Style/HashSyntax' => { 'EnforcedStyle' => 'ruby19', 'SupportedStyles' => %w[ruby19 hash_rockets], 'UseHashRocketsWithSymbolValues' => true }) end it 'accepts ruby19 syntax when no elements have symbol values' do expect_no_offenses('x = { a: 1, b: 2 }') end it 'accepts ruby19 syntax when no elements have symbol values ' \ 'in method calls' do inspect_source('func(3, a: 0)') expect(cop.messages.empty?).to be(true) end it 'accepts new syntax in method calls' do expect_no_offenses('func(3, a: 0)') end it 'accepts an empty hash' do expect_no_offenses('{}') end it 'registers an offense when any element uses a symbol for the value' do expect_offense(<<-RUBY.strip_indent) x = { a: 1, b: :c } ^^ Use hash rockets syntax. ^^ Use hash rockets syntax. RUBY end it 'registers an offense when any element has a symbol value ' \ 'in method calls' do inspect_source('func(3, b: :c)') expect(cop.messages).to eq(['Use hash rockets syntax.']) end it 'registers an offense when using hash rockets ' \ 'and no elements have a symbol value' do inspect_source('x = { :a => 1, :b => 2 }') expect(cop.messages) .to eq(['Use the new Ruby 1.9 hash syntax.', 'Use the new Ruby 1.9 hash syntax.']) end it 'registers an offense for hashes with elements on multiple lines' do expect_offense(<<-RUBY.strip_indent) x = { a: :b, ^^ Use hash rockets syntax. c: :d } ^^ Use hash rockets syntax. RUBY end it 'auto-corrects to ruby19 style when there are no symbol values' do new_source = autocorrect_source('{ :a => 1, :b => 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end it 'auto-corrects to hash rockets ' \ 'when there is an element with a symbol value' do new_source = autocorrect_source('{ a: 1, :b => :c }') expect(new_source).to eq('{ :a => 1, :b => :c }') end it 'auto-corrects to hash rockets ' \ 'when all elements have symbol value' do new_source = autocorrect_source('{ a: :b, c: :d }') expect(new_source).to eq('{ :a => :b, :c => :d }') end it 'auto-correct does not change anything when the hash ' \ 'is already ruby19 style and there are no symbol values' do new_source = autocorrect_source('{ a: 1, b: 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end end end context 'configured to enforce hash rockets style' do let(:cop_config) do { 'EnforcedStyle' => 'hash_rockets', 'SupportedStyles' => %w[ruby19 hash_rockets], 'UseHashRocketsWithSymbolValues' => false } end it 'registers offense for Ruby 1.9 style' do inspect_source('x = { a: 0 }') expect(cop.messages).to eq(['Use hash rockets syntax.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'ruby19') end it 'registers an offense for mixed syntax' do inspect_source('x = { :a => 0, b: 1 }') expect(cop.messages).to eq(['Use hash rockets syntax.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers an offense for 1.9 style in method calls' do expect_offense(<<-RUBY.strip_indent) func(3, a: 0) ^^ Use hash rockets syntax. RUBY end it 'accepts hash rockets in a hash literal' do expect_no_offenses('x = { :a => 0, :b => 1 }') end it 'accepts hash rockets in method calls' do expect_no_offenses('func(3, :a => 0)') end it 'accepts an empty hash' do expect_no_offenses('{}') end it 'auto-corrects new style to hash rockets' do new_source = autocorrect_source('{ a: 1, b: 2}') expect(new_source).to eq('{ :a => 1, :b => 2}') end context 'UseHashRocketsWithSymbolValues has no impact' do let(:cop_config) do { 'EnforcedStyle' => 'hash_rockets', 'SupportedStyles' => %w[ruby19 hash_rockets], 'UseHashRocketsWithSymbolValues' => true } end it 'does not register an offense when there is a symbol value' do expect_no_offenses('{ :a => :b, :c => :d }') end end end context 'configured to enforce ruby 1.9 style with no mixed keys' do context 'UseHashRocketsWithSymbolValues disabled' do let(:cop_config) do { 'EnforcedStyle' => 'ruby19_no_mixed_keys', 'UseHashRocketsWithSymbolValues' => false } end it 'accepts new syntax in a hash literal' do expect_no_offenses('x = { a: 0, b: 1 }') end it 'registers offense for hash rocket syntax when new is possible' do inspect_source('x = { :a => 0 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'hash_rockets') end it 'registers an offense for mixed syntax when new is possible' do inspect_source('x = { :a => 0, b: 1 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new syntax in method calls' do expect_no_offenses('func(3, a: 0)') end it 'registers an offense for hash rockets in method calls' do expect_offense(<<-RUBY.strip_indent) func(3, :a => 0) ^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'accepts hash rockets when keys have different types' do expect_no_offenses('x = { :a => 0, "b" => 1 }') end it 'accepts an empty hash' do expect_no_offenses('{}') end it 'registers an offense when keys have different types and styles' do inspect_source('x = { a: 0, "b" => 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end context 'ruby < 2.2', :ruby21 do it 'accepts hash rockets when keys have whitespaces in them' do expect_no_offenses('x = { :"t o" => 0, :b => 1 }') end it 'registers an offense when keys have whitespaces and mix styles' do inspect_source('x = { :"t o" => 0, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys have special symbols in them' do expect_no_offenses('x = { :"\\tab" => 1, :b => 1 }') end it 'registers an offense when keys have special symbols and '\ 'mix styles' do inspect_source('x = { :"\tab" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys start with a digit' do expect_no_offenses('x = { :"1" => 1, :b => 1 }') end it 'registers an offense when keys start with a digit and mix styles' do inspect_source('x = { :"1" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'ruby >= 2.2', :ruby22 do it 'registers an offense when keys have whitespaces in them' do expect_offense(<<-RUBY.strip_indent) x = { :"t o" => 0 } ^^^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'registers an offense when keys have special symbols in them' do expect_offense(<<-'RUBY'.strip_indent) x = { :"\tab" => 1 } ^^^^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'registers an offense when keys start with a digit' do expect_offense(<<-RUBY.strip_indent) x = { :"1" => 1 } ^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end end it 'auto-corrects old to new style' do new_source = autocorrect_source('{ :a => 1, :b => 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end it 'auto-corrects to hash rockets when new style cannot be used ' \ 'for all' do new_source = autocorrect_source('{ a: 1, "b" => 2 }') expect(new_source).to eq('{ :a => 1, "b" => 2 }') end end context 'UseHashRocketsWithSymbolValues enabled' do let(:cop_config) do { 'EnforcedStyle' => 'ruby19_no_mixed_keys', 'UseHashRocketsWithSymbolValues' => true } end it 'registers an offense when any element uses a symbol for the value' do expect_offense(<<-RUBY.strip_indent) x = { a: 1, b: :c } ^^ Use hash rockets syntax. ^^ Use hash rockets syntax. RUBY end it 'registers an offense when any element has a symbol value ' \ 'in method calls' do inspect_source('func(3, b: :c)') expect(cop.messages).to eq(['Use hash rockets syntax.']) end it 'auto-corrects to hash rockets ' \ 'when there is an element with a symbol value' do new_source = autocorrect_source('{ a: 1, :b => :c }') expect(new_source).to eq('{ :a => 1, :b => :c }') end it 'auto-corrects to hash rockets ' \ 'when all elements have symbol value' do new_source = autocorrect_source('{ a: :b, c: :d }') expect(new_source).to eq('{ :a => :b, :c => :d }') end it 'accepts new syntax in a hash literal' do expect_no_offenses('x = { a: 0, b: 1 }') end it 'registers offense for hash rocket syntax when new is possible' do inspect_source('x = { :a => 0 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'hash_rockets') end it 'registers an offense for mixed syntax when new is possible' do inspect_source('x = { :a => 0, b: 1 }') expect(cop.messages).to eq(['Use the new Ruby 1.9 hash syntax.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new syntax in method calls' do expect_no_offenses('func(3, a: 0)') end it 'registers an offense for hash rockets in method calls' do expect_offense(<<-RUBY.strip_indent) func(3, :a => 0) ^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'accepts hash rockets when keys have different types' do expect_no_offenses('x = { :a => 0, "b" => 1 }') end it 'accepts an empty hash' do expect_no_offenses('{}') end it 'registers an offense when keys have different types and styles' do inspect_source('x = { a: 0, "b" => 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end context 'ruby < 2.2', :ruby21 do it 'accepts hash rockets when keys have whitespaces in them' do expect_no_offenses('x = { :"t o" => 0, :b => 1 }') end it 'registers an offense when keys have whitespaces and mix styles' do inspect_source('x = { :"t o" => 0, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys have special symbols in them' do expect_no_offenses('x = { :"\\tab" => 1, :b => 1 }') end it 'registers an offense when keys have special symbols and ' \ 'mix styles' do inspect_source('x = { :"\tab" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys start with a digit' do expect_no_offenses('x = { :"1" => 1, :b => 1 }') end it 'registers an offense when keys start with a digit and mix styles' do inspect_source('x = { :"1" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'ruby >= 2.2', :ruby22 do it 'registers an offense when keys have whitespaces in them' do expect_offense(<<-RUBY.strip_indent) x = { :"t o" => 0 } ^^^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'registers an offense when keys have special symbols in them' do expect_offense(<<-'RUBY'.strip_indent) x = { :"\tab" => 1 } ^^^^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end it 'registers an offense when keys start with a digit' do expect_offense(<<-RUBY.strip_indent) x = { :"1" => 1 } ^^^^^^^ Use the new Ruby 1.9 hash syntax. RUBY end end it 'auto-corrects old to new style' do new_source = autocorrect_source('{ :a => 1, :b => 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end it 'auto-corrects to hash rockets when new style cannot be used ' \ 'for all' do new_source = autocorrect_source('{ a: 1, "b" => 2 }') expect(new_source).to eq('{ :a => 1, "b" => 2 }') end end end context 'configured to enforce no mixed keys' do let(:cop_config) do { 'EnforcedStyle' => 'no_mixed_keys' } end it 'accepts new syntax in a hash literal' do expect_no_offenses('x = { a: 0, b: 1 }') end it 'accepts the hash rocket syntax when new is possible' do expect_no_offenses('x = { :a => 0 }') end it 'registers an offense for mixed syntax when new is possible' do inspect_source('x = { :a => 0, b: 1 }') expect(cop.messages).to eq(['Don\'t mix styles in the same hash.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts new syntax in method calls' do expect_no_offenses('func(3, a: 0)') end it 'accepts hash rockets in method calls' do expect_no_offenses('func(3, :a => 0)') end it 'accepts hash rockets when keys have different types' do expect_no_offenses('x = { :a => 0, "b" => 1 }') end it 'accepts an empty hash' do expect_no_offenses('{}') end it 'registers an offense when keys have different types and styles' do inspect_source('x = { a: 0, "b" => 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys have whitespaces in them' do expect_no_offenses('x = { :"t o" => 0, :b => 1 }') end it 'registers an offense when keys have whitespaces and mix styles' do inspect_source('x = { :"t o" => 0, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys have special symbols in them' do expect_no_offenses('x = { :"\\tab" => 1, :b => 1 }') end it 'registers an offense when keys have special symbols and '\ 'mix styles' do inspect_source('x = { :"\tab" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts hash rockets when keys start with a digit' do expect_no_offenses('x = { :"1" => 1, :b => 1 }') end it 'registers an offense when keys start with a digit and mix styles' do inspect_source('x = { :"1" => 1, b: 1 }') expect(cop.messages).to eq(["Don't mix styles in the same hash."]) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'does not auto-correct old to new style' do new_source = autocorrect_source('{ :a => 1, :b => 2 }') expect(new_source).to eq('{ :a => 1, :b => 2 }') end it 'does not auto-correct new to hash rockets style' do new_source = autocorrect_source('{ a: 1, b: 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end it 'auto-corrects mixed key hashes' do new_source = autocorrect_source('{ a: 1, :b => 2 }') expect(new_source).to eq('{ a: 1, b: 2 }') end it 'auto-corrects to hash rockets when new style cannot be used ' \ 'for all' do new_source = autocorrect_source('{ a: 1, "b" => 2 }') expect(new_source).to eq('{ :a => 1, "b" => 2 }') end end end rubocop-0.52.1/spec/rubocop/cop/style/identical_conditional_branches_spec.rb000066400000000000000000000101201322072016200273040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::IdenticalConditionalBranches do subject(:cop) { described_class.new } context 'on if..else with identical bodies' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if something do_x ^^^^ Move `do_x` out of the conditional. else do_x ^^^^ Move `do_x` out of the conditional. end RUBY end end context 'on if..else with identical trailing lines' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if something method_call_here(1, 2, 3) do_x ^^^^ Move `do_x` out of the conditional. else 1 + 2 + 3 do_x ^^^^ Move `do_x` out of the conditional. end RUBY end end context 'on if..else with identical leading lines' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if something do_x ^^^^ Move `do_x` out of the conditional. method_call_here(1, 2, 3) else do_x ^^^^ Move `do_x` out of the conditional. 1 + 2 + 3 end RUBY end end context 'on if..elsif with no else' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) if something do_x elsif something_else do_x end RUBY end end context 'on if..else with slightly different trailing lines' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) if something do_x(1) else do_x(2) end RUBY end end context 'on case with identical bodies' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case something when :a do_x ^^^^ Move `do_x` out of the conditional. when :b do_x ^^^^ Move `do_x` out of the conditional. else do_x ^^^^ Move `do_x` out of the conditional. end RUBY end end # Regression: https://github.com/bbatsov/rubocop/issues/3868 context 'when one of the case branches is empty' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) case value when cond1 else if cond2 else end end RUBY end end context 'on case with identical trailing lines' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case something when :a x1 do_x ^^^^ Move `do_x` out of the conditional. when :b x2 do_x ^^^^ Move `do_x` out of the conditional. else x3 do_x ^^^^ Move `do_x` out of the conditional. end RUBY end end context 'on case with identical leading lines' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case something when :a do_x ^^^^ Move `do_x` out of the conditional. x1 when :b do_x ^^^^ Move `do_x` out of the conditional. x2 else do_x ^^^^ Move `do_x` out of the conditional. x3 end RUBY end end context 'on case without else' do let(:source) do <<-RUBY.strip_indent case something when :a do_x when :b do_x end RUBY end it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) case something when :a do_x when :b do_x end RUBY end end context 'on case with empty when' do it "doesn't register an offense" do expect_no_offenses(<<-RUBY.strip_indent) case something when :a do_x do_y when :b else do_x do_z end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/if_inside_else_spec.rb000066400000000000000000000041351322072016200240720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::IfInsideElse do subject(:cop) { described_class.new } it 'catches an if node nested inside an else' do expect_offense(<<-RUBY.strip_indent) if a blah else if b ^^ Convert `if` nested inside `else` to `elsif`. foo end end RUBY end it 'catches an if..else nested inside an else' do expect_offense(<<-RUBY.strip_indent) if a blah else if b ^^ Convert `if` nested inside `else` to `elsif`. foo else bar end end RUBY end it 'catches a modifier if nested inside an else' do expect_offense(<<-RUBY.strip_indent) if a blah else foo if b ^^ Convert `if` nested inside `else` to `elsif`. end RUBY end it "isn't offended if there is a statement following the if node" do expect_no_offenses(<<-RUBY.strip_indent) if a blah else if b foo end bar end RUBY end it "isn't offended if there is a statement preceding the if node" do expect_no_offenses(<<-RUBY.strip_indent) if a blah else bar if b foo end end RUBY end it "isn't offended by if..elsif..else" do expect_no_offenses(<<-RUBY.strip_indent) if a blah elsif b blah else blah end RUBY end it 'ignores unless inside else' do expect_no_offenses(<<-RUBY.strip_indent) if a blah else unless b foo end end RUBY end it 'ignores if inside unless' do expect_no_offenses(<<-RUBY.strip_indent) unless a if b foo end end RUBY end it 'ignores nested ternary expressions' do expect_no_offenses('a ? b : c ? d : e') end it 'ignores ternary inside if..else' do expect_no_offenses(<<-RUBY.strip_indent) if a blah else a ? b : c end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/if_unless_modifier_of_if_unless_spec.rb000066400000000000000000000026441322072016200275340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::IfUnlessModifierOfIfUnless do include StatementModifierHelper subject(:cop) { described_class.new } it 'provides a good error message' do source = 'condition ? then_part : else_part unless external_condition' inspect_source(source) expect(cop.messages) .to eq(['Avoid modifier `unless` after another conditional.']) end context 'ternary with modifier' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) condition ? then_part : else_part unless external_condition ^^^^^^ Avoid modifier `unless` after another conditional. RUBY end end context 'conditional with modifier' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless condition then_part end if external_condition ^^ Avoid modifier `if` after another conditional. RUBY end end context 'conditional with modifier in body' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) if condition then_part if maybe? end RUBY end end context 'nested conditionals' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) if external_condition if condition then_part end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/if_unless_modifier_spec.rb000066400000000000000000000176641322072016200250110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::IfUnlessModifier do include StatementModifierHelper subject(:cop) { described_class.new(config) } let(:config) do hash = { 'Metrics/LineLength' => { 'Max' => 80 } } RuboCop::Config.new(hash) end context 'multiline if that fits on one line' do let(:source) do # Empty lines should make no difference. <<-RUBY.strip_indent if #{condition} #{body} end RUBY end let(:condition) { 'a' * 38 } let(:body) { 'b' * 38 } it 'registers an offense' do # This if statement fits exactly on one line if written as a # modifier. expect("#{body} if #{condition}".length).to eq(80) inspect_source(source) expect(cop.messages).to eq( ['Favor modifier `if` usage when having a single-line' \ ' body. Another good alternative is the usage of control flow' \ ' `&&`/`||`.'] ) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq "#{body} if #{condition}\n" end context 'and has two statements separated by semicolon' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) if condition do_this; do_that end RUBY end end end context 'multiline if that fits on one line with comment on first line' do let(:source) do <<-RUBY.strip_indent if a # comment b end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if a # comment ^^ Favor modifier `if` usage when having a single-line body. Another good alternative is the usage of control flow `&&`/`||`. b end RUBY end it 'does auto-correction and preserves comment' do corrected = autocorrect_source(source) expect(corrected).to eq "b if a # comment\n" end end context 'multiline if that fits on one line with comment near end' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) if a b end # comment if a b # comment end RUBY end end context 'short multiline if near an else etc' do let(:source) do <<-RUBY.strip_indent if x y elsif x1 y1 else z end n = a ? 0 : 1 m = 3 if m0 if a b end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if x y elsif x1 y1 else z end n = a ? 0 : 1 m = 3 if m0 if a ^^ Favor modifier `if` usage when having a single-line body. Another good alternative is the usage of control flow `&&`/`||`. b end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) if x y elsif x1 y1 else z end n = a ? 0 : 1 m = 3 if m0 b if a RUBY end end it "accepts multiline if that doesn't fit on one line" do check_too_long(cop, 'if') end it 'accepts multiline if whose body is more than one line' do check_short_multiline(cop, 'if') end context 'multiline unless that fits on one line' do let(:source) do <<-RUBY.strip_indent unless a b end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless a ^^^^^^ Favor modifier `unless` usage when having a single-line body. Another good alternative is the usage of control flow `&&`/`||`. b end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq "b unless a\n" end end it 'accepts code with EOL comment since user might want to keep it' do expect_no_offenses(<<-RUBY.strip_indent) unless a b # A comment end RUBY end it 'accepts if-else-end' do expect_no_offenses(<<-RUBY.strip_indent) if args.last.is_a? Hash then args.pop else Hash.new end RUBY end it 'accepts an empty condition' do check_empty(cop, 'if') check_empty(cop, 'unless') end it 'accepts if/elsif' do expect_no_offenses(<<-RUBY.strip_indent) if test something elsif test2 something_else end RUBY end context 'with implicit match conditional' do let(:source) do <<-RUBY.strip_margin('|') | if #{conditional} | #{body} | end RUBY end let(:body) { 'b' * 36 } context 'when a multiline if fits on one line' do let(:conditional) { "/#{'a' * 36}/" } it 'registers an offense' do expect(" #{body} if #{conditional}".length).to eq(80) inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq " #{body} if #{conditional}\n" end end context "when a multiline if doesn't fit on one line" do let(:conditional) { "/#{'a' * 37}/" } it 'accepts' do expect(" #{body} if #{conditional}".length).to eq(81) inspect_source(source) expect(cop.offenses.empty?).to be(true) end end end it 'accepts if-end followed by a chained call' do expect_no_offenses(<<-RUBY.strip_indent) if test something end.inspect RUBY end it "doesn't break if-end when used as RHS of local var assignment" do corrected = autocorrect_source(<<-RUBY.strip_indent) a = if b 1 end RUBY expect(corrected).to eq "a = (1 if b)\n" end it "doesn't break if-end when used as RHS of instance var assignment" do corrected = autocorrect_source(<<-RUBY.strip_indent) @a = if b 1 end RUBY expect(corrected).to eq "@a = (1 if b)\n" end it "doesn't break if-end when used as RHS of class var assignment" do corrected = autocorrect_source(<<-RUBY.strip_indent) @@a = if b 1 end RUBY expect(corrected).to eq "@@a = (1 if b)\n" end it "doesn't break if-end when used as RHS of constant assignment" do corrected = autocorrect_source(<<-RUBY.strip_indent) A = if b 1 end RUBY expect(corrected).to eq "A = (1 if b)\n" end it "doesn't break if-end when used as RHS of binary arithmetic" do corrected = autocorrect_source(<<-RUBY.strip_indent) a + if b 1 end RUBY expect(corrected).to eq "a + (1 if b)\n" end it 'accepts if-end when used as LHS of binary arithmetic' do expect_no_offenses(<<-RUBY.strip_indent) if test 1 end + 2 RUBY end context 'if-end is argument to a parenthesized method call' do it "doesn't add redundant parentheses" do corrected = autocorrect_source(<<-RUBY.strip_indent) puts("string", if a 1 end) RUBY expect(corrected).to eq "puts(\"string\", 1 if a)\n" end end context 'if-end is argument to a non-parenthesized method call' do it 'adds parentheses so as not to change meaning' do corrected = autocorrect_source(<<-RUBY.strip_indent) puts "string", if a 1 end RUBY expect(corrected).to eq "puts \"string\", (1 if a)\n" end end context 'if-end with conditional as body' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) if condition foo ? "bar" : "baz" end RUBY end end context 'unless-end with conditional as body' do it 'accepts' do expect_no_offenses(<<-RUBY.strip_indent) unless condition foo ? "bar" : "baz" end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/if_with_semicolon_spec.rb000066400000000000000000000011511322072016200246250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::IfWithSemicolon do subject(:cop) { described_class.new } it 'registers an offense for one line if/;/end' do expect_offense(<<-RUBY.strip_indent) if cond; run else dont end ^^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use if x; Use the ternary operator instead. RUBY end it 'accepts one line if/then/end' do expect_no_offenses('if cond then run else dont end') end it 'can handle modifier conditionals' do expect_no_offenses(<<-RUBY.strip_indent) class Hash end if RUBY_VERSION < "1.8.7" RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/implicit_runtime_error_spec.rb000066400000000000000000000025701322072016200257200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ImplicitRuntimeError do subject(:cop) { described_class.new } %w[raise fail].each do |method| it "registers an offense for #{method} 'message'" do inspect_source("#{method} 'message'") expect(cop.offenses.size).to eq 1 expect(cop.messages).to eq(["Use `#{method}` with an explicit " \ 'exception class and message, rather than ' \ 'just a message.']) expect(cop.highlights).to eq(["#{method} 'message'"]) end it "registers an offense for #{method} with a multiline string" do inspect_source(["#{method} 'message' \\", "'2nd line'"]) expect(cop.offenses.size).to eq 1 expect(cop.messages).to eq(["Use `#{method}` with an explicit " \ 'exception class and message, rather than ' \ 'just a message.']) expect(cop.highlights).to eq(["#{method} 'message' \\\n'2nd line'"]) end it "doesn't register an offense for #{method} StandardError, 'message'" do inspect_source("#{method} StandardError, 'message'") expect(cop.offenses.empty?).to be(true) end it "doesn't register an offense for #{method} with no arguments" do inspect_source(method) expect(cop.offenses.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/cop/style/infinite_loop_spec.rb000066400000000000000000000071631322072016200237730ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::InfiniteLoop do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end %w(1 2.0 [1] {}).each do |lit| it "registers an offense for a while loop with #{lit} as condition" do inspect_source(<<-RUBY.strip_indent) while #{lit} top end RUBY expect(cop.messages).to eq(['Use `Kernel#loop` for infinite loops.']) expect(cop.highlights).to eq(['while']) end end %w[false nil].each do |lit| it "registers an offense for a until loop with #{lit} as condition" do inspect_source(<<-RUBY.strip_indent) until #{lit} top end RUBY expect(cop.messages).to eq(['Use `Kernel#loop` for infinite loops.']) expect(cop.highlights).to eq(['until']) end end it 'accepts Kernel#loop' do expect_no_offenses('loop { break if something }') end shared_examples_for 'auto-corrector' do |keyword, lit| it "auto-corrects single line modifier #{keyword}" do new_source = autocorrect_source("something += 1 #{keyword} #{lit} # comment") expect(new_source).to eq('loop { something += 1 } # comment') end context 'with non-default indentation width' do let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 4 }) end it "auto-corrects multi-line modifier #{keyword} and indents correctly" do new_source = autocorrect_source(<<-RUBY.strip_indent) # comment something 1, # comment 1 # comment 2 2 #{keyword} #{lit} RUBY expect(new_source).to eq(<<-RUBY.strip_indent) # comment loop do something 1, # comment 1 # comment 2 2 end RUBY end end it "auto-corrects begin-end-#{keyword} with one statement" do new_source = autocorrect_source(<<-RUBY.strip_margin('|')) | begin # comment 1 | something += 1 # comment 2 | end #{keyword} #{lit} # comment 3 RUBY expect(new_source).to eq(<<-RUBY.strip_margin('|')) | loop do # comment 1 | something += 1 # comment 2 | end # comment 3 RUBY end it "auto-corrects begin-end-#{keyword} with two statements" do new_source = autocorrect_source(<<-RUBY.strip_margin('|')) | begin | something += 1 | something_else += 1 | end #{keyword} #{lit} RUBY expect(new_source).to eq(<<-RUBY.strip_margin('|')) | loop do | something += 1 | something_else += 1 | end RUBY end it "auto-corrects single line modifier #{keyword} with and" do new_source = autocorrect_source("something and something_else #{keyword} #{lit}") expect(new_source).to eq('loop { something and something_else }') end it "auto-corrects the usage of #{keyword} with do" do new_source = autocorrect_source(<<-RUBY.strip_indent) #{keyword} #{lit} do end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) loop do end RUBY end it "auto-corrects the usage of #{keyword} without do" do new_source = autocorrect_source(<<-RUBY.strip_indent) #{keyword} #{lit} end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) loop do end RUBY end end it_behaves_like 'auto-corrector', 'while', 'true' it_behaves_like 'auto-corrector', 'until', 'false' end rubocop-0.52.1/spec/rubocop/cop/style/inline_comment_spec.rb000066400000000000000000000007521322072016200241320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::InlineComment do subject(:cop) { described_class.new } it 'registers an offense for a trailing inline comment' do expect_offense(<<-RUBY.strip_indent) two = 1 + 1 # A trailing inline comment ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid trailing inline comments. RUBY end it 'does not register an offense for a standalone comment' do expect_no_offenses('# A standalone comment') end end rubocop-0.52.1/spec/rubocop/cop/style/inverse_methods_spec.rb000066400000000000000000000203451322072016200243300ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::InverseMethods do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( 'Style/InverseMethods' => { 'InverseMethods' => { any?: :none?, even?: :odd?, present?: :blank?, include?: :exclude?, :== => :!=, :=~ => :!~, :< => :>=, :> => :<= }, 'InverseBlocks' => { select: :reject, select!: :reject! } } ) end it 'registers an offense for calling !.none? with a symbol proc' do expect_offense(<<-RUBY.strip_indent) !foo.none?(&:even?) ^^^^^^^^^^^^^^^^^^^ Use `any?` instead of inverting `none?`. RUBY end it 'registers an offense for calling !.none? with a block' do expect_offense(<<-RUBY.strip_indent) !foo.none? { |f| f.even? } ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `any?` instead of inverting `none?`. RUBY end it 'allows a method call without a not' do expect_no_offenses('foo.none?') end it 'allows an inverse method when double negation is used' do expect_no_offenses('!!(string =~ /^\w+$/)') end it 'allows an inverse method with a block when double negation is used' do expect_no_offenses('!!foo.reject { |e| !e }') end context 'auto-correct' do it 'corrects !.none? with a symbol proc to any?' do new_source = autocorrect_source('!foo.none?(&:even?)') expect(new_source).to eq('foo.any?(&:even?)') end it 'corrects !.none? with a block to any?' do new_source = autocorrect_source('!foo.none? { |f| f.even? }') expect(new_source).to eq('foo.any? { |f| f.even? }') end end shared_examples :all_variable_types do |variable| it "registers an offense for calling !#{variable}.none?" do inspect_source("!#{variable}.none?") expect(cop.messages).to eq(['Use `any?` instead of inverting `none?`.']) expect(cop.highlights).to eq(["!#{variable}.none?"]) end it "registers an offense for calling not #{variable}.none?" do inspect_source("not #{variable}.none?") expect(cop.messages).to eq(['Use `any?` instead of inverting `none?`.']) expect(cop.highlights).to eq(["not #{variable}.none?"]) end it "corrects !#{variable}.none? to #{variable}.any?" do new_source = autocorrect_source("!#{variable}.none?") expect(new_source).to eq("#{variable}.any?") end it "corrects not #{variable}.none? to #{variable}.any?" do new_source = autocorrect_source("not #{variable}.none?") expect(new_source).to eq("#{variable}.any?") end end it_behaves_like :all_variable_types, 'foo' it_behaves_like :all_variable_types, '$foo' it_behaves_like :all_variable_types, '@foo' it_behaves_like :all_variable_types, '@@foo' it_behaves_like :all_variable_types, 'FOO' it_behaves_like :all_variable_types, 'FOO::BAR' it_behaves_like :all_variable_types, 'foo["bar"]' it_behaves_like :all_variable_types, 'foo.bar' { any?: :none?, even?: :odd?, present?: :blank?, include?: :exclude?, none?: :any?, odd?: :even?, blank?: :present?, exclude?: :include? }.each do |method, inverse| it "registers an offense for !foo.#{method}" do inspect_source("!foo.#{method}") expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it "corrects #{method} to #{inverse}" do new_source = autocorrect_source("!foo.#{method}") expect(new_source).to eq("foo.#{inverse}") end end { :== => :!=, :!= => :==, :=~ => :!~, :!~ => :=~, :< => :>=, :> => :<= }.each do |method, inverse| it "registers an offense for !(foo #{method} bar)" do inspect_source("!(foo #{method} bar)") expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it "registers an offense for not (foo #{method} bar)" do inspect_source("not (foo #{method} bar)") expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it "corrects #{method} to #{inverse}" do new_source = autocorrect_source("!(foo #{method} bar)") expect(new_source).to eq("foo #{inverse} bar") end end context 'inverse blocks' do { select: :reject, reject: :select, select!: :reject!, reject!: :select! }.each do |method, inverse| it "registers an offense for foo.#{method} { |e| !e }" do inspect_source("foo.#{method} { |e| !e }") expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it 'registers an offense for a multiline method call where the last ' \ 'method is inverted' do inspect_source(<<-RUBY.strip_indent) foo.#{method} do |e| something !e.bar end RUBY expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it 'registers an offense for an inverted equality block' do expect_offense(<<-RUBY.strip_indent) foo.select { |e| e != 2 } ^^^^^^^^^^^^^^^^^^^^^^^^^ Use `reject` instead of inverting `select`. RUBY end it 'registers an offense for a multiline inverted equality block' do inspect_source(<<-RUBY.strip_indent) foo.#{method} do |e| something something_else e != 2 end RUBY expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it 'registers a single offense for nested inverse method calls' do inspect_source(<<-RUBY.strip_indent) y.#{method} { |key, _value| !(key =~ /c\d/) } RUBY expect(cop.messages) .to eq(["Use `#{inverse}` instead of inverting `#{method}`."]) end it 'corrects nested inverse method calls' do new_source = autocorrect_source("y.#{method} { |key, _value| !(key =~ /c\d/) }") expect(new_source) .to eq("y.#{inverse} { |key, _value| (key =~ /c\d/) }") end it 'corrects a simple inverted block' do new_source = autocorrect_source("foo.#{method} { |e| !e }") expect(new_source).to eq("foo.#{inverse} { |e| e }") end it 'corrects an inverted method call' do new_source = autocorrect_source("foo.#{method} { |e| !e.bar? }") expect(new_source).to eq("foo.#{inverse} { |e| e.bar? }") end it 'corrects a complex inverted method call' do source = "puts 1 if !foo.#{method} { |e| !e.bar? }" new_source = autocorrect_source(source) expect(new_source).to eq("puts 1 if !foo.#{inverse} { |e| e.bar? }") end it 'corrects an inverted do end method call' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo.#{method} do |e| !e.bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) foo.#{inverse} do |e| e.bar end RUBY end it 'corrects a multiline method call where the last method is inverted' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo.#{method} do |e| something something_else !e.bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) foo.#{inverse} do |e| something something_else e.bar end RUBY end it 'corrects an offense for an inverted equality block' do new_source = autocorrect_source("foo.#{method} { |e| e != 2 }") expect(new_source).to eq("foo.#{inverse} { |e| e == 2 }") end it 'corrects an offense for a multiline inverted equality block' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo.#{method} do |e| something something_else e != 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) foo.#{inverse} do |e| something something_else e == 2 end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/lambda_call_spec.rb000066400000000000000000000041461322072016200233460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::LambdaCall, :config do subject(:cop) { described_class.new(config) } context 'when style is set to call' do let(:cop_config) { { 'EnforcedStyle' => 'call' } } it 'registers an offense for x.()' do inspect_source('x.(a, b)') expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'braces') end it 'registers an offense for correct + opposite' do inspect_source(<<-RUBY.strip_indent) x.call(a, b) x.(a, b) RUBY expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts x.call()' do expect_no_offenses('x.call(a, b)') end it 'auto-corrects x.() to x.call()' do new_source = autocorrect_source(['a.(x)']) expect(new_source).to eq('a.call(x)') end end context 'when style is set to braces' do let(:cop_config) { { 'EnforcedStyle' => 'braces' } } it 'registers an offense for x.call()' do inspect_source('x.call(a, b)') expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'call') end it 'registers an offense for opposite + correct' do inspect_source(<<-RUBY.strip_indent) x.call(a, b) x.(a, b) RUBY expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts x.()' do expect_no_offenses('x.(a, b)') end it 'accepts a call without receiver' do expect_no_offenses('call(a, b)') end it 'auto-corrects x.call() to x.()' do new_source = autocorrect_source(['a.call(x)']) expect(new_source).to eq('a.(x)') end it 'auto-corrects x.call to x.()' do new_source = autocorrect_source(['a.call']) expect(new_source).to eq('a.()') end it 'auto-corrects x.call asdf, x123 to x.(asdf, x123)' do new_source = autocorrect_source(['a.call asdf, x123']) expect(new_source).to eq('a.(asdf, x123)') end end end rubocop-0.52.1/spec/rubocop/cop/style/lambda_spec.rb000066400000000000000000000264471322072016200223630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Lambda, :config do subject(:cop) { described_class.new(config) } shared_examples 'registers an offense' do |message| it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end end shared_examples 'auto-correct' do |expected| it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq(expected) end end shared_examples 'does not auto-correct' do it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'with enforced `lambda` style' do let(:cop_config) { { 'EnforcedStyle' => 'lambda' } } context 'with a single line lambda literal' do context 'with arguments' do let(:source) { 'f = ->(x) { x }' } it_behaves_like 'registers an offense', 'Use the `lambda` method for all lambdas.' it_behaves_like 'auto-correct', 'f = lambda { |x| x }' end context 'without arguments' do let(:source) { 'f = -> { x }' } it_behaves_like 'registers an offense', 'Use the `lambda` method for all lambdas.' it_behaves_like 'auto-correct', 'f = lambda { x }' end end context 'with a multiline lambda literal' do context 'with arguments' do let(:source) do <<-RUBY.strip_indent f = ->(x) do x end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for all lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = lambda do |x| x end RUBY end context 'without arguments' do let(:source) do <<-RUBY.strip_indent f = -> do x end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for all lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = lambda do x end RUBY end end end context 'with enforced `literal` style' do let(:cop_config) { { 'EnforcedStyle' => 'literal' } } context 'with a single line lambda method call' do context 'with arguments' do let(:source) { 'f = lambda { |x| x }' } it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'all lambdas.' it_behaves_like 'auto-correct', 'f = ->(x) { x }' end context 'without arguments' do let(:source) { 'f = lambda { x }' } it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'all lambdas.' it_behaves_like 'auto-correct', 'f = -> { x }' end end context 'with a multiline lambda method call' do context 'with arguments' do let(:source) do <<-RUBY.strip_indent f = lambda do |x| x end RUBY end it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'all lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = ->(x) do x end RUBY end context 'without arguments' do let(:source) do <<-RUBY.strip_indent f = lambda do x end RUBY end it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'all lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = -> do x end RUBY end end end context 'with default `line_count_dependent` style' do let(:cop_config) { { 'EnforcedStyle' => 'line_count_dependent' } } context 'with a single line lambda method call' do context 'with arguments' do let(:source) { 'f = lambda { |x| x }' } it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'single line lambdas.' it_behaves_like 'auto-correct', 'f = ->(x) { x }' end context 'without arguments' do let(:source) { 'f = lambda { x }' } it_behaves_like 'registers an offense', 'Use the `-> { ... }` lambda literal syntax for ' \ 'single line lambdas.' it_behaves_like 'auto-correct', 'f = -> { x }' end end context 'with a multiline lambda method call' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) l = lambda do |x| x end RUBY end end context 'with a single line lambda literal' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) lambda = ->(x) { x } lambda.(1) RUBY end end context 'with a multiline lambda literal' do context 'with arguments' do let(:source) do <<-RUBY.strip_indent f = ->(x) do x end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = lambda do |x| x end RUBY end context 'without arguments' do let(:source) do <<-RUBY.strip_indent f = -> do x end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent f = lambda do x end RUBY end end context 'unusual lack of spacing' do # The lack of spacing shown here is valid ruby syntax, # and can be the result of previous autocorrects re-writing # a multi-line `->(x){ ... }` to `->(x)do ... end`. # See rubocop/cop/style/block_delimiters.rb. # Tests correction of an issue resulting in `lambdado` syntax errors. context 'without any spacing' do let(:source) do <<-RUBY.strip_indent ->(x)do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |x| x end RUBY end context 'without spacing after arguments' do let(:source) do <<-RUBY.strip_indent -> (x)do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |x| x end RUBY end context 'without spacing before arguments' do let(:source) do <<-RUBY.strip_indent ->(x) do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |x| x end RUBY end context 'with a multiline lambda literal' do context 'with empty arguments' do let(:source) do <<-RUBY.strip_indent ->()do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do x end RUBY end context 'with no arguments and bad spacing' do let(:source) do <<-RUBY.strip_indent -> ()do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do x end RUBY end context 'with no arguments and no spacing' do let(:source) do <<-RUBY.strip_indent ->do x end RUBY end it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do x end RUBY end context 'without parentheses' do let(:source) do <<-RUBY.strip_indent -> hello do puts hello end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |hello| puts hello end RUBY end context 'with no parentheses and bad spacing' do let(:source) do <<-RUBY.strip_indent -> hello do puts hello end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |hello| puts hello end RUBY end context 'with no parentheses and many args' do let(:source) do <<-RUBY.strip_indent -> hello, user do puts hello end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'auto-correct', <<-RUBY.strip_indent lambda do |hello, user| puts hello end RUBY end end end context 'when calling a lambda method without a block' do it 'does not register an offense' do expect_no_offenses('l = lambda.test') end end context 'with a multiline lambda literal as an argument' do let(:source) do <<-RUBY.strip_indent has_many :kittens, -> do where(cats: Cat.young.where_values_hash) end, source: cats RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'does not auto-correct' end context 'with a multiline lambda literal as a keyword argument' do let(:source) do <<-RUBY.strip_indent has_many opt: -> do where(cats: Cat.young.where_values_hash) end RUBY end it_behaves_like 'registers an offense', 'Use the `lambda` method for multiline lambdas.' it_behaves_like 'does not auto-correct' end end context 'when using safe navigation operator' do let(:ruby_version) { 2.3 } it 'does not break' do expect_no_offenses(<<-RUBY.strip_indent) foo&.bar do |_| baz end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/line_end_concatenation_spec.rb000066400000000000000000000137451322072016200256220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::LineEndConcatenation do subject(:cop) { described_class.new } it 'registers an offense for string concat at line end' do expect_offense(<<-RUBY.strip_indent) top = "test" + ^ Use `\\` instead of `+` or `<<` to concatenate those strings. "top" RUBY end it 'registers an offense for string concat with << at line end' do expect_offense(<<-RUBY.strip_indent) top = "test" << ^^ Use `\\` instead of `+` or `<<` to concatenate those strings. "top" RUBY end it 'registers an offense for string concat with << and \ at line ends' do expect_offense(<<-RUBY.strip_indent) top = "test " \\ "foo" << ^^ Use `\\` instead of `+` or `<<` to concatenate those strings. "bar" RUBY end it 'registers an offense for dynamic string concat at line end' do expect_offense(<<-'RUBY'.strip_indent) top = "test#{x}" + ^ Use `\` instead of `+` or `<<` to concatenate those strings. "top" RUBY end it 'registers an offense for dynamic string concat with << at line end' do expect_offense(<<-'RUBY'.strip_indent) top = "test#{x}" << ^^ Use `\` instead of `+` or `<<` to concatenate those strings. "top" RUBY end it 'registers multiple offenses when there are chained << methods' do expect_offense(<<-'RUBY'.strip_indent) top = "test#{x}" << ^^ Use `\` instead of `+` or `<<` to concatenate those strings. "top" << ^^ Use `\` instead of `+` or `<<` to concatenate those strings. "ubertop" RUBY end it 'registers multiple offenses when there are chained concatenations' do expect_offense(<<-'RUBY'.strip_indent) top = "test#{x}" + ^ Use `\` instead of `+` or `<<` to concatenate those strings. "top" + ^ Use `\` instead of `+` or `<<` to concatenate those strings. "foo" RUBY end it 'registers multiple offenses when there are chained concatenations' \ 'combined with << calls' do inspect_source(['top = "test#{x}" <<', '"top" +', '"foo" <<', '"bar"']) expect(cop.offenses.size).to eq(3) end it 'accepts string concat on the same line' do expect_no_offenses('top = "test" + "top"') end it 'accepts string concat with a return value of method on a string' do expect_no_offenses(<<-RUBY.strip_indent) content_and_three_spaces = "content" + " " * 3 a_thing = 'a ' + 'gniht'.reverse output = 'value: ' + '%d' % value 'letter: ' + 'abcdefghij'[ix] RUBY end it 'accepts string concat with a return value of method on an interpolated ' \ 'string' do source = <<-RUBY x3a = 'x' + "\#{'a' + "\#{3}"}".reverse RUBY inspect_source(source) expect(cop.offenses.empty?).to be(true) end it 'accepts string concat at line end when followed by comment' do expect_no_offenses(<<-RUBY.strip_indent) top = "test" + # something "top" RUBY end it 'accepts string concat at line end when followed by a comment line' do expect_no_offenses(<<-RUBY.strip_indent) top = "test" + # something "top" RUBY end it 'accepts string concat at line end when % literals are involved' do expect_no_offenses(<<-RUBY.strip_indent) top = %(test) + "top" RUBY end it 'accepts string concat at line end for special strings like __FILE__' do expect_no_offenses(<<-RUBY.strip_indent) top = __FILE__ + "top" RUBY end it 'registers offenses only for the appropriate lines in chained concats' do # only the last concatenation is an offense expect_offense(<<-'RUBY'.strip_indent) top = "test#{x}" + # comment "foo" + %(bar) + "baz" + ^ Use `\` instead of `+` or `<<` to concatenate those strings. "qux" RUBY end it 'autocorrects in the simple case by replacing + with \\' do corrected = autocorrect_source(['top = "test" +', '"top"']) expect(corrected).to eq ['top = "test" \\', '"top"'].join("\n") end # The "central auto-correction engine" can't handle intermediate states where # the code has syntax errors, so it's important to fix the trailing # whitespace in this cop. it 'autocorrects a + with trailing whitespace to \\' do corrected = autocorrect_source(['top = "test" + ', '"top"']) expect(corrected).to eq ['top = "test" \\', '"top"'].join("\n") end it 'autocorrects a + with \\ to just \\' do corrected = autocorrect_source(['top = "test" + \\', '"top"']) expect(corrected).to eq ['top = "test" \\', '"top"'].join("\n") end it 'autocorrects for chained concatenations and << calls' do corrected = autocorrect_source(['top = "test#{x}" <<', '"top" +', '"ubertop" <<', '"foo"']) expect(corrected).to eq ['top = "test#{x}" \\', '"top" \\', '"ubertop" \\', '"foo"'].join("\n") end it 'autocorrects only the lines that should be autocorrected' do corrected = autocorrect_source(['top = "test#{x}" <<', '"top" + # comment', '"foo" +', '"bar" +', '%(baz) +', '"qux"']) expect(corrected).to eq ['top = "test#{x}" \\', '"top" + # comment', '"foo" \\', '"bar" +', '%(baz) +', '"qux"'].join("\n") end end rubocop-0.52.1/spec/rubocop/cop/style/method_call_with_args_parentheses_spec.rb000066400000000000000000000066161322072016200300620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MethodCallWithArgsParentheses, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'IgnoredMethods' => %w[puts] } end it 'accepts no parens in method call without args' do expect_no_offenses('top.test') end it 'accepts parens in method call with args' do expect_no_offenses('top.test(a, b)') end it 'register an offense for method call without parens' do expect_offense(<<-RUBY.strip_indent) top.test a, b ^^^^^^^^^^^^^ Use parentheses for method calls with arguments. RUBY end it 'register an offense for non-receiver method call without parens' do expect_offense(<<-RUBY.strip_indent) def foo test a, b ^^^^^^^^^ Use parentheses for method calls with arguments. end RUBY end it 'register an offense for methods starting with a capital without parens' do expect_offense(<<-RUBY.strip_indent) def foo Test a, b ^^^^^^^^^ Use parentheses for method calls with arguments. end RUBY end it 'register an offense for superclass call without parens' do expect_offense(<<-RUBY.strip_indent) def foo super a ^^^^^^^ Use parentheses for method calls with arguments. end RUBY end it 'register no offense for superclass call without args' do expect_no_offenses('super') end it 'register no offense for yield without args' do expect_no_offenses('yield') end it 'register no offense for superclass call with parens' do expect_no_offenses('super(a)') end it 'register an offense for yield without parens' do expect_offense(<<-RUBY.strip_indent) def foo yield a ^^^^^^^ Use parentheses for method calls with arguments. end RUBY end it 'accepts no parens for operators' do expect_no_offenses('top.test + a') end it 'accepts no parens for setter methods' do expect_no_offenses('top.test = a') end it 'accepts no parens for unary operators' do expect_no_offenses('!test') end it 'auto-corrects call by adding needed braces' do new_source = autocorrect_source('top.test a') expect(new_source).to eq('top.test(a)') end it 'auto-corrects superclass call by adding needed braces' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo super a end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo super(a) end RUBY end it 'auto-corrects yield by adding needed braces' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo yield a end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo yield(a) end RUBY end it 'ignores method listed in IgnoredMethods' do expect_no_offenses('puts :test') end context 'when inspecting macro methods' do let(:cop_config) do { 'IgnoreMacros' => 'true' } end context 'in a class body' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) class Foo bar :baz end RUBY end end context 'in a module body' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) module Foo bar :baz end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/method_call_without_args_parentheses_spec.rb000066400000000000000000000064011322072016200306020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MethodCallWithoutArgsParentheses do subject(:cop) { described_class.new } it 'registers an offense for parens in method call without args' do expect_offense(<<-RUBY.strip_indent) top.test() ^ Do not use parentheses for method calls with no arguments. RUBY end it 'accepts parentheses for methods starting with an upcase letter' do expect_no_offenses('Test()') end it 'accepts no parens in method call without args' do expect_no_offenses('top.test') end it 'accepts parens in method call with args' do expect_no_offenses('top.test(a)') end it 'accepts special lambda call syntax' do # Style/LambdaCall checks for this syntax expect_no_offenses('thing.()') end it 'accepts parens after not' do expect_no_offenses('not(something)') end context 'assignment to a variable with the same name' do it 'accepts parens in local variable assignment ' do expect_no_offenses('test = test()') end it 'accepts parens in shorthand assignment' do expect_no_offenses('test ||= test()') end it 'accepts parens in parallel assignment' do expect_no_offenses('one, test = 1, test()') end it 'accepts parens in complex assignment' do expect_no_offenses(<<-RUBY.strip_indent) test = begin case a when b c = test() if d end end RUBY end end it 'registers an offense for `obj.method ||= func()`' do expect_offense(<<-RUBY.strip_indent) obj.method ||= func() ^ Do not use parentheses for method calls with no arguments. RUBY end it 'registers an offense for `obj.method &&= func()`' do expect_offense(<<-RUBY.strip_indent) obj.method &&= func() ^ Do not use parentheses for method calls with no arguments. RUBY end it 'registers an offense for `obj.method += func()`' do expect_offense(<<-RUBY.strip_indent) obj.method += func() ^ Do not use parentheses for method calls with no arguments. RUBY end it 'auto-corrects by removing unneeded braces' do new_source = autocorrect_source('test()') expect(new_source).to eq('test') end # These will be offenses for the EmptyLiteral cop. The autocorrect loop will # handle that. it 'auto-corrects calls that could be empty literals' do original = <<-RUBY.strip_indent Hash.new() Array.new() String.new() RUBY new_source = autocorrect_source(original) expect(new_source).to eq(<<-RUBY.strip_indent) Hash.new Array.new String.new RUBY end context 'method call as argument' do it 'accepts without parens' do expect_no_offenses('_a = c(d.e)') end it 'registers an offense with empty parens' do expect_offense(<<-RUBY.strip_indent) _a = c(d()) ^ Do not use parentheses for method calls with no arguments. RUBY end it 'registers an empty parens offense for multiple assignment' do expect_offense(<<-RUBY.strip_indent) _a, _b, _c = d(e()) ^ Do not use parentheses for method calls with no arguments. RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb000066400000000000000000000026251322072016200270750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MethodCalledOnDoEndBlock do subject(:cop) { described_class.new } context 'with a multi-line do..end block' do it 'registers an offense for a chained call' do expect_offense(<<-RUBY.strip_indent) a do b end.c ^^^^^ Avoid chaining a method call on a do...end block. RUBY end it 'accepts it if there is no chained call' do expect_no_offenses(<<-RUBY.strip_indent) a do b end RUBY end it 'accepts a chained block' do expect_no_offenses(<<-RUBY.strip_indent) a do b end.c do d end RUBY end end context 'with a single-line do..end block' do it 'registers an offense for a chained call' do expect_offense(<<-RUBY.strip_indent) a do b end.c ^^^^^ Avoid chaining a method call on a do...end block. RUBY end it 'accepts a single-line do..end block with a chained block' do expect_no_offenses('a do b end.c do d end') end end context 'with a {} block' do it 'accepts a multi-line block with a chained call' do expect_no_offenses(<<-RUBY.strip_indent) a { b }.c RUBY end it 'accepts a single-line block with a chained call' do expect_no_offenses('a { b }.c') end end end rubocop-0.52.1/spec/rubocop/cop/style/method_def_parentheses_spec.rb000066400000000000000000000124441322072016200256320ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MethodDefParentheses, :config do subject(:cop) { described_class.new(config) } context 'require_parentheses' do let(:cop_config) { { 'EnforcedStyle' => 'require_parentheses' } } it 'reports an offense for def with parameters but no parens' do src = <<-RUBY.strip_indent def func a, b end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'require_no_parentheses') end it 'reports an offense for correct + opposite' do src = <<-RUBY.strip_indent def func(a, b) end def func a, b end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'reports an offense for class def with parameters but no parens' do src = <<-RUBY.strip_indent def Test.func a, b end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts def with no args and no parens' do expect_no_offenses(<<-RUBY.strip_indent) def func end RUBY end it 'auto-adds required parens for a def' do new_source = autocorrect_source('def test param; end') expect(new_source).to eq('def test(param); end') end it 'auto-adds required parens for a defs' do new_source = autocorrect_source('def self.test param; end') expect(new_source).to eq('def self.test(param); end') end it 'auto-adds required parens to argument lists on multiple lines' do new_source = autocorrect_source(<<-RUBY.strip_indent) def test one, two end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def test(one, two) end RUBY end end shared_examples :no_parentheses do # common to require_no_parentheses and # require_no_parentheses_except_multiline it 'reports an offense for def with parameters with parens' do src = <<-RUBY.strip_indent def func(a, b) end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'require_parentheses') end it 'accepts a def with parameters but no parens' do src = <<-RUBY.strip_indent def func a, b end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'reports an offense for opposite + correct' do src = <<-RUBY.strip_indent def func(a, b) end def func a, b end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'reports an offense for class def with parameters with parens' do src = <<-RUBY.strip_indent def Test.func(a, b) end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts a class def with parameters with parens' do src = <<-RUBY.strip_indent def Test.func a, b end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'reports an offense for def with no args and parens' do src = <<-RUBY.strip_indent def func() end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts def with no args and no parens' do src = <<-RUBY.strip_indent def func end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end it 'auto-removes the parens' do new_source = autocorrect_source('def test(param); end') expect(new_source).to eq('def test param; end') end it 'auto-removes the parens for defs' do new_source = autocorrect_source('def self.test(param); end') expect(new_source).to eq('def self.test param; end') end end context 'require_no_parentheses' do let(:cop_config) { { 'EnforcedStyle' => 'require_no_parentheses' } } it_behaves_like :no_parentheses end context 'require_no_parentheses_except_multiline' do let(:cop_config) do { 'EnforcedStyle' => 'require_no_parentheses_except_multiline' } end context 'when args are all on a single line' do it_behaves_like :no_parentheses end context 'when args span multiple lines' do it 'reports an offense for correct + opposite' do src = <<-RUBY.strip_indent def func(a, b) end def func a, b end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-adds required parens to argument lists on multiple lines' do new_source = autocorrect_source(<<-RUBY.strip_indent) def test one, two end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def test(one, two) end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/method_missing_spec.rb000066400000000000000000000047521322072016200241470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MethodMissing do subject(:cop) { described_class.new } before do inspect_source(source) end shared_examples 'code with offense' do |code| let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end describe 'when not implementing #respond_to_missing? or calling #super' do let(:message) do 'When using `method_missing`, define `respond_to_missing?` and ' \ 'fall back on `super`.' end it_behaves_like 'code with offense', <<-RUBY.strip_indent class Test def method_missing; end end RUBY end describe 'when not implementing #respond_to_missing?' do let(:message) do 'When using `method_missing`, define `respond_to_missing?`.' end it_behaves_like 'code with offense', <<-RUBY.strip_indent class Test def method_missing super end end RUBY end describe 'when not calling #super' do let(:message) do 'When using `method_missing`, fall back on `super`.' end it_behaves_like 'code with offense', <<-RUBY.strip_indent class Test def respond_to_missing?; end def method_missing; end end RUBY end describe 'when implementing #respond_to_missing? and calling #super' do context 'when implemented as instance methods' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Test def respond_to_missing?; end def method_missing super end end RUBY end context 'when implemented as class methods' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Test def self.respond_to_missing?; end def self.method_missing super end end RUBY end context 'when implemented with different scopes' do let(:message) do 'When using `method_missing`, define `respond_to_missing?`.' end it_behaves_like 'code with offense', <<-RUBY.strip_indent class Test def respond_to_missing?; end def self.method_missing super end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/min_max_spec.rb000066400000000000000000000070041322072016200225570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MinMax, :config do subject(:cop) { described_class.new(config) } context 'with an array literal containing calls to `#min` and `#max`' do context 'when the expression stands alone' do it 'registers an offense if the receivers match' do expect_offense(<<-RUBY.strip_indent) [foo.min, foo.max] ^^^^^^^^^^^^^^^^^^ Use `foo.minmax` instead of `[foo.min, foo.max]`. RUBY end it 'does not register an offense if the receivers do not match' do expect_no_offenses(<<-RUBY.strip_indent) [foo.min, bar.max] RUBY end it 'does not register an offense if there are additional elements' do expect_no_offenses(<<-RUBY.strip_indent) [foo.min, foo.baz, foo.max] RUBY end it 'does not register an offense if the receiver is implicit' do expect_no_offenses(<<-RUBY.strip_indent) [min, max] RUBY end it 'auto-corrects an offense to use `#minmax`' do corrected = autocorrect_source(<<-RUBY.strip_indent) [foo.bar.min, foo.bar.max] RUBY expect(corrected).to eq(<<-RUBY.strip_indent) foo.bar.minmax RUBY end end context 'when the expression is used in a parallel assignment' do it 'registers an offense if the receivers match' do expect_offense(<<-RUBY.strip_indent) bar = foo.min, foo.max ^^^^^^^^^^^^^^^^ Use `foo.minmax` instead of `foo.min, foo.max`. RUBY end it 'does not register an offense if the receivers do not match' do expect_no_offenses(<<-RUBY.strip_indent) baz = foo.min, bar.max RUBY end it 'does not register an offense if there are additional elements' do expect_no_offenses(<<-RUBY.strip_indent) bar = foo.min, foo.baz, foo.max RUBY end it 'does not register an offense if the receiver is implicit' do expect_no_offenses(<<-RUBY.strip_indent) bar = min, max RUBY end it 'auto-corrects an offense to use `#minmax`' do corrected = autocorrect_source(<<-RUBY.strip_indent) baz = foo.bar.min, foo.bar.max RUBY expect(corrected).to eq(<<-RUBY.strip_indent) baz = foo.bar.minmax RUBY end end context 'when the expression is used as a return value' do it 'registers an offense if the receivers match' do expect_offense(<<-RUBY.strip_indent) return foo.min, foo.max ^^^^^^^^^^^^^^^^ Use `foo.minmax` instead of `foo.min, foo.max`. RUBY end it 'does not register an offense if the receivers do not match' do expect_no_offenses(<<-RUBY.strip_indent) return foo.min, bar.max RUBY end it 'does not register an offense if there are additional elements' do expect_no_offenses(<<-RUBY.strip_indent) return foo.min, foo.baz, foo.max RUBY end it 'does not register an offense if the receiver is implicit' do expect_no_offenses(<<-RUBY.strip_indent) return min, max RUBY end it 'auto-corrects an offense to use `#minmax`' do corrected = autocorrect_source(<<-RUBY.strip_indent) return foo.bar.min, foo.bar.max RUBY expect(corrected).to eq(<<-RUBY.strip_indent) return foo.bar.minmax RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/missing_else_spec.rb000066400000000000000000000464061322072016200236210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MissingElse do subject(:cop) { described_class.new(config) } context 'UnlessElse enabled' do let(:config) do RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'both', 'SupportedStyles' => %w[if case both] }, 'Style/UnlessElse' => { 'Enabled' => true }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if cond; foo end ^^^^^^^^^^^^^^^^ `if` condition requires an `else`-clause. RUBY end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo end') end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case v; when a; foo; when b; bar; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `case` condition requires an `else`-clause. RUBY end end end end context 'UnlessElse disabled' do let(:config) do RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'both', 'SupportedStyles' => %w[if case both] }, 'Style/UnlessElse' => { 'Enabled' => false }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if cond; foo end ^^^^^^^^^^^^^^^^ `if` condition requires an `else`-clause. RUBY end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless cond; foo end ^^^^^^^^^^^^^^^^^^^^ `if` condition requires an `else`-clause. RUBY end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case v; when a; foo; when b; bar; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `case` condition requires an `else`-clause. RUBY end end end end context 'EmptyElse enabled and set to warn on empty' do let(:config) do styles = %w[if case both] RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'both', 'SupportedStyles' => styles }, 'Style/UnlessElse' => { 'Enabled' => false }, 'Style/EmptyElse' => { 'Enabled' => true, 'EnforcedStyle' => 'empty', 'SupportedStyles' => %w[empty nil both] }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do inspect_source('if cond; foo end') msg = ['`if` condition requires an `else`-clause with `nil` in it.'] expect(cop.messages) .to eq(msg) end it 'highlights' do expect_offense(<<-RUBY.strip_indent) if cond; foo end ^^^^^^^^^^^^^^^^ `if` condition requires an `else`-clause with `nil` in it. RUBY end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do inspect_source('unless cond; foo end') msg = ['`if` condition requires an `else`-clause with `nil` in it.'] expect(cop.messages) .to eq(msg) end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it 'registers an offense' do inspect_source('case v; when a; foo; when b; bar; end') msg = ['`case` condition requires an `else`-clause with `nil` in it.'] expect(cop.messages) .to eq(msg) end end end end context 'EmptyElse enabled and set to warn on nil' do let(:config) do styles = %w[if case both] RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'both', 'SupportedStyles' => styles }, 'Style/UnlessElse' => { 'Enabled' => false }, 'Style/EmptyElse' => { 'Enabled' => true, 'EnforcedStyle' => 'nil', 'SupportedStyles' => %w[empty nil both] }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if cond; foo end ^^^^^^^^^^^^^^^^ `if` condition requires an empty `else`-clause. RUBY end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless cond; foo end ^^^^^^^^^^^^^^^^^^^^ `if` condition requires an empty `else`-clause. RUBY end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case v; when a; foo; when b; bar; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `case` condition requires an empty `else`-clause. RUBY end end end end context 'configured to warn only on empty if' do let(:config) do styles = %w[if case both] RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'if', 'SupportedStyles' => styles }, 'Style/UnlessElse' => { 'Enabled' => false }, 'Style/EmptyElse' => { 'Enabled' => true, 'EnforcedStyle' => 'nil', 'SupportedStyles' => %w[empty nil both] }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) if cond; foo end ^^^^^^^^^^^^^^^^ `if` condition requires an empty `else`-clause. RUBY end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) unless cond; foo end ^^^^^^^^^^^^^^^^^^^^ `if` condition requires an empty `else`-clause. RUBY end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; end') end end end end context 'configured to warn only on empty case' do let(:config) do styles = %w[if case both] RuboCop::Config.new('Style/MissingElse' => { 'Enabled' => true, 'EnforcedStyle' => 'case', 'SupportedStyles' => styles }, 'Style/UnlessElse' => { 'Enabled' => false }, 'Style/EmptyElse' => { 'Enabled' => true, 'EnforcedStyle' => 'nil', 'SupportedStyles' => %w[empty nil both] }) end context 'given an if-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('if a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('if a; foo elsif b; bar else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('if cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('if cond; foo end') end end end context 'given an unless-statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo else bar; nil end') end end context 'with no else-clause' do it "doesn't register an offense" do expect_no_offenses('unless cond; foo end') end end end context 'given a case statement' do context 'with a completely empty else-clause' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo else end') end end context 'with an else-clause containing only the literal nil' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; when b; bar; else nil end') end end context 'with an else-clause with side-effects' do it "doesn't register an offense" do expect_no_offenses('case v; when a; foo; else b; nil end') end end context 'with no else-clause' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) case v; when a; foo; when b; bar; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `case` condition requires an empty `else`-clause. RUBY end end end end end rubocop-0.52.1/spec/rubocop/cop/style/mixin_grouping_spec.rb000066400000000000000000000243671322072016200242000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MixinGrouping, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(offenses) expect(cop.messages).to eq([message] * offenses) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'when configured with separated style' do let(:cop_config) { { 'EnforcedStyle' => 'separated' } } let(:offenses) { 1 } context 'when using `include`' do let(:message) { 'Put `include` mixins in separate statements.' } context 'with several mixins in one call' do it_behaves_like 'code with offense', ['class Foo', ' include Bar, Qux', 'end'].join("\n"), ['class Foo', ' include Qux', ' include Bar', 'end'].join("\n") end context 'with single mixins in separate calls' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo include Bar include Qux end RUBY end context 'when include call is an argument to another method' do it_behaves_like 'code without offense', 'expect(foo).to include(bar, baz)' end context 'with several mixins in separate calls' do it_behaves_like 'code with offense', ['class Foo', ' include Bar, Baz', ' include Qux', 'end'].join("\n"), ['class Foo', ' include Baz', ' include Bar', ' include Qux', 'end'].join("\n") end end context 'when using `extend`' do let(:message) { 'Put `extend` mixins in separate statements.' } context 'with several mixins in one call' do it_behaves_like 'code with offense', ['class Foo', ' extend Bar, Qux', 'end'].join("\n"), ['class Foo', ' extend Qux', ' extend Bar', 'end'].join("\n") end context 'with single mixins in separate calls' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo extend Bar extend Qux end RUBY end end context 'when using `prepend`' do let(:message) { 'Put `prepend` mixins in separate statements.' } context 'with several mixins in one call' do it_behaves_like 'code with offense', ['class Foo', ' prepend Bar, Qux', 'end'].join("\n"), ['class Foo', ' prepend Qux', ' prepend Bar', 'end'].join("\n") end context 'with single mixins in separate calls' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo prepend Bar prepend Qux end RUBY end end context 'when using a mix of diffent methods' do context 'with some calls having several mixins' do let(:message) { 'Put `include` mixins in separate statements.' } it_behaves_like 'code with offense', ['class Foo', ' include Bar, Baz', ' extend Qux', 'end'].join("\n"), ['class Foo', ' include Baz', ' include Bar', ' extend Qux', 'end'].join("\n") end context 'with all calls having one mixin' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo include Bar prepend Baz extend Baz end RUBY end end end context 'when configured with grouped style' do let(:cop_config) { { 'EnforcedStyle' => 'grouped' } } context 'when using include' do context 'with single mixins in separate calls' do let(:offenses) { 3 } let(:message) { 'Put `include` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' include Bar', ' include Baz', ' include Qux', 'end'].join("\n"), ['class Foo', ' include Qux, Baz, Bar', 'end'].join("\n") end context 'with several mixins in one call' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo include Bar, Qux end RUBY end context 'when include has an explicit receiver' do it_behaves_like 'code without offense', <<-RUBY.strip_indent config.include Foo config.include Bar RUBY end context 'with several mixins in separate calls' do let(:offenses) { 3 } let(:message) { 'Put `include` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' include Bar, Baz', ' include FooBar, FooBaz', ' include Qux, FooBarBaz', 'end'].join("\n"), ['class Foo', ' include Qux, FooBarBaz, FooBar, FooBaz, Bar, Baz', 'end'].join("\n") end end context 'when using `extend`' do context 'with single mixins in separate calls' do let(:offenses) { 2 } let(:message) { 'Put `extend` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' extend Bar', ' extend Baz', 'end'].join("\n"), ['class Foo', ' extend Baz, Bar', 'end'].join("\n") end context 'with several mixins in one call' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo extend Bar, Qux end RUBY end end context 'when using `prepend`' do context 'with single mixins in separate calls' do let(:offenses) { 2 } let(:message) { 'Put `prepend` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' prepend Bar', ' prepend Baz', 'end'].join("\n"), ['class Foo', ' prepend Baz, Bar', 'end'].join("\n") end context 'with single mixins in separate calls, intersperced' do let(:offenses) { 3 } let(:message) { 'Put `prepend` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' prepend Bar', ' prepend Baz', ' do_something_else', ' prepend Qux', 'end'].join("\n"), ['class Foo', ' prepend Qux, Baz, Bar', ' do_something_else', ' ', # extra line left by prepend Qux 'end'].join("\n") end context 'with mixins with receivers' do let(:offenses) { 2 } let(:message) { 'Put `prepend` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' prepend Bar', ' Other.prepend Baz', ' do_something_else', ' prepend Qux', 'end'].join("\n"), ['class Foo', ' prepend Qux, Bar', ' Other.prepend Baz', ' do_something_else', ' ', # extra line left by prepend Qux 'end'].join("\n") end context 'with several mixins in one call' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo prepend Bar, Qux end RUBY end end context 'when using a mix of diffent methods' do context 'with some duplicated mixin methods' do let(:offenses) { 2 } let(:message) { 'Put `include` mixins in a single statement.' } it_behaves_like 'code with offense', ['class Foo', ' include Bar', ' include Baz', ' extend Baz', 'end'].join("\n"), ['class Foo', ' include Baz, Bar', ' extend Baz', 'end'].join("\n") end context 'with all different mixin methods' do it_behaves_like 'code without offense', <<-RUBY.strip_indent class Foo include Bar prepend Baz extend Baz end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/mixin_usage_spec.rb000066400000000000000000000102351322072016200234370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MixinUsage do subject(:cop) { described_class.new } context 'include' do it 'registers an offense when using outside class (used above)' do expect_offense(<<-RUBY.strip_indent) include M ^^^^^^^^^ `include` is used at the top level. Use inside `class` or `module`. class C end RUBY end it 'registers an offense when using outside class (used below)' do expect_offense(<<-RUBY.strip_indent) class C end include M ^^^^^^^^^ `include` is used at the top level. Use inside `class` or `module`. RUBY end it 'registers an offense when using only `include` statement' do expect_offense(<<-RUBY.strip_indent) include M ^^^^^^^^^ `include` is used at the top level. Use inside `class` or `module`. RUBY end it 'registers an offense when using `include` in method definition ' \ 'outside class or module' do expect_offense(<<-RUBY.strip_indent) def foo include M ^^^^^^^^^ `include` is used at the top level. Use inside `class` or `module`. end RUBY end it 'does not register an offense when using outside class' do expect_no_offenses(<<-RUBY.strip_indent) Foo.include M class C; end RUBY end it 'does not register an offense when using inside class' do expect_no_offenses(<<-RUBY.strip_indent) class C include M end RUBY end it 'does not register an offense when using inside block' do expect_no_offenses(<<-RUBY.strip_indent) Class.new do include M end RUBY end it "doesn't register an offense when `include` call is a method argument" do expect_no_offenses(<<-RUBY.strip_indent) do_something(include(M)) RUBY end it 'does not register an offense when using `include` in method ' \ 'definition inside class' do expect_no_offenses(<<-RUBY.strip_indent) class X def foo include M end end RUBY end it 'does not register an offense when using `include` in method ' \ 'definition inside module' do expect_no_offenses(<<-RUBY.strip_indent) module X def foo include M end end RUBY end context 'Multiple definition classes in one' do it 'does not register an offense when using inside class' do expect_no_offenses(<<-RUBY.strip_indent) class C1 include M end class C2 include M end RUBY end end context 'Nested module' do it 'registers an offense when using outside class' do expect_offense(<<-RUBY.strip_indent) include M1::M2::M3 ^^^^^^^^^^^^^^^^^^ `include` is used at the top level. Use inside `class` or `module`. class C end RUBY end end end context 'extend' do it 'registers an offense when using outside class' do expect_offense(<<-RUBY.strip_indent) extend M ^^^^^^^^ `extend` is used at the top level. Use inside `class` or `module`. class C end RUBY end it 'does not register an offense when using inside class' do expect_no_offenses(<<-RUBY.strip_indent) class C extend M end RUBY end end context 'prepend' do it 'registers an offense when using outside class' do expect_offense(<<-RUBY.strip_indent) prepend M ^^^^^^^^^ `prepend` is used at the top level. Use inside `class` or `module`. class C end RUBY end it 'does not register an offense when using inside class' do expect_no_offenses(<<-RUBY.strip_indent) class C prepend M end RUBY end end it 'does not register an offense when using inside nested module' do expect_no_offenses(<<-RUBY.strip_indent) module M1 include M2 class C include M3 end end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/module_function_spec.rb000066400000000000000000000024711322072016200243240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ModuleFunction, :config do subject(:cop) { described_class.new(config) } context 'when enforced style is `module_function`' do let(:cop_config) { { 'EnforcedStyle' => 'module_function' } } it 'registers an offense for `extend self` in a module' do expect_offense(<<-RUBY.strip_indent) module Test extend self ^^^^^^^^^^^ Use `module_function` instead of `extend self`. def test; end end RUBY end it 'accepts `extend self` in a class' do expect_no_offenses(<<-RUBY.strip_indent) class Test extend self end RUBY end end context 'when enforced style is `extend_self`' do let(:cop_config) { { 'EnforcedStyle' => 'extend_self' } } it 'registers an offense for `module_function` without an argument' do expect_offense(<<-RUBY.strip_indent) module Test module_function ^^^^^^^^^^^^^^^ Use `extend self` instead of `module_function`. def test; end end RUBY end it 'accepts module_function with an argument' do expect_no_offenses(<<-RUBY.strip_indent) module Test def test; end module_function :test end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/multiline_block_chain_spec.rb000066400000000000000000000037771322072016200254620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MultilineBlockChain do subject(:cop) { described_class.new } context 'with multi-line block chaining' do it 'registers an offense for a simple case' do expect_offense(<<-RUBY.strip_indent) a do b end.c do ^^^^^ Avoid multi-line chains of blocks. d end RUBY end it 'registers an offense for a slightly more complicated case' do expect_offense(<<-RUBY.strip_indent) a do b end.c1.c2 do ^^^^^^^^^ Avoid multi-line chains of blocks. d end RUBY end it 'registers two offenses for a chain of three blocks' do expect_offense(<<-RUBY.strip_indent) a do b end.c do ^^^^^ Avoid multi-line chains of blocks. d end.e do ^^^^^ Avoid multi-line chains of blocks. f end RUBY end it 'registers an offense for a chain where the second block is ' \ 'single-line' do inspect_source(<<-RUBY.strip_indent) Thread.list.find_all { |t| t.alive? }.map { |thread| thread.object_id } RUBY expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(['}.map']) end it 'accepts a chain where the first block is single-line' do expect_no_offenses(<<-RUBY.strip_indent) Thread.list.find_all { |t| t.alive? }.map { |t| t.object_id } RUBY end end it 'accepts a chain of blocks spanning one line' do expect_no_offenses(<<-RUBY.strip_indent) a { b }.c { d } w do x end.y do z end RUBY end it 'accepts a multi-line block chained with calls on one line' do expect_no_offenses(<<-RUBY.strip_indent) a do b end.c.d RUBY end it 'accepts a chain of calls followed by a multi-line block' do expect_no_offenses(<<-RUBY.strip_indent) a1.a2.a3 do b end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/multiline_if_modifier_spec.rb000066400000000000000000000054521322072016200254720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MultilineIfModifier do subject(:cop) { described_class.new } shared_examples 'offense' do |modifier| it 'registers an offense' do inspect_source(source) expect(cop.messages) .to eq(["Favor a normal #{modifier}-statement over a modifier" \ ' clause in a multiline statement.']) end end shared_examples 'no offense' do it 'does not register an offense' do inspect_source(source) expect(cop.messages.empty?).to be(true) end end shared_examples 'autocorrect' do |correct_code| it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq(correct_code) end end context 'if guard clause' do let(:source) do [ '{', ' result: run', '} if cond' ].join("\n") end include_examples 'offense', 'if' include_examples 'autocorrect', "if cond\n {\n result: run\n }\nend" context 'one liner' do let(:source) { 'run if cond' } include_examples 'no offense' end context 'multiline condition' do let(:source) { "run if cond &&\n cond2" } include_examples 'no offense' end context 'indented offense' do let(:source) do [ ' {', ' result: run', ' } if cond' ].join("\n") end include_examples 'autocorrect', " if cond\n" \ " {\n" \ " result: run\n" \ " }\n" \ ' end' end end context 'unless guard clause' do let(:source) do [ '{', ' result: run', '} unless cond' ].join("\n") end include_examples 'offense', 'unless' include_examples 'autocorrect', "unless cond\n" \ " {\n" \ " result: run\n" \ " }\n" \ 'end' context 'one liner' do let(:source) { 'run unless cond' } include_examples 'no offense' end context 'multiline condition' do let(:source) { "run unless cond &&\n cond2" } include_examples 'no offense' end context 'indented offense' do let(:source) do [ ' {', ' result: run', ' } unless cond' ].join("\n") end include_examples 'autocorrect', " unless cond\n" \ " {\n" \ " result: run\n" \ " }\n" \ ' end' end end end rubocop-0.52.1/spec/rubocop/cop/style/multiline_if_then_spec.rb000066400000000000000000000062661322072016200246360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MultilineIfThen do subject(:cop) { described_class.new } # if it 'does not get confused by empty elsif branch' do expect_no_offenses(<<-RUBY.strip_indent) if cond elsif cond end RUBY end it 'registers an offense for then in multiline if' do inspect_source(['if cond then', 'end', "if cond then\t", 'end', 'if cond then ', 'end', 'if cond', 'then', 'end', 'if cond then # bad', 'end']) expect(cop.offenses.map(&:line)).to eq([1, 3, 5, 8, 10]) expect(cop.highlights).to eq(['then'] * 5) expect(cop.messages).to eq(['Do not use `then` for multi-line `if`.'] * 5) end it 'registers an offense for then in multiline elsif' do expect_offense(<<-RUBY.strip_indent) if cond1 a elsif cond2 then ^^^^ Do not use `then` for multi-line `elsif`. b end RUBY end it 'accepts multiline if without then' do expect_no_offenses(<<-RUBY.strip_indent) if cond end RUBY end it 'accepts table style if/then/elsif/ends' do expect_no_offenses(<<-RUBY.strip_indent) if @io == $stdout then str << "$stdout" elsif @io == $stdin then str << "$stdin" elsif @io == $stderr then str << "$stderr" else str << @io.class.to_s end RUBY end it 'does not get confused by a then in a when' do expect_no_offenses(<<-RUBY.strip_indent) if a case b when c then end end RUBY end it 'does not get confused by a commented-out then' do expect_no_offenses(<<-RUBY.strip_indent) if a # then b end if c # then end RUBY end it 'does not raise an error for an implicit match if' do expect do inspect_source(<<-RUBY.strip_indent) if // end RUBY end.not_to raise_error end # unless it 'registers an offense for then in multiline unless' do expect_offense(<<-RUBY.strip_indent) unless cond then ^^^^ Do not use `then` for multi-line `unless`. end RUBY end it 'accepts multiline unless without then' do expect_no_offenses(<<-RUBY.strip_indent) unless cond end RUBY end it 'does not get confused by a postfix unless' do expect_no_offenses('two unless one') end it 'does not get confused by a nested postfix unless' do expect_no_offenses(<<-RUBY.strip_indent) if two puts 1 end unless two RUBY end it 'does not raise an error for an implicit match unless' do expect do inspect_source(<<-RUBY.strip_indent) unless // end RUBY end.not_to raise_error end it 'auto-corrects the usage of "then" in multiline if' do new_source = autocorrect_source(<<-RUBY.strip_indent) if cond then something end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if cond something end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/multiline_memoization_spec.rb000066400000000000000000000145161322072016200255520ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MultilineMemoization, :config do subject(:cop) { described_class.new(config) } let(:message) { 'Wrap multiline memoization blocks in `begin` and `end`.' } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected| let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end shared_examples 'with all enforced styles' do context 'with a single line memoization' do it_behaves_like 'code without offense', 'foo ||= bar' it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= bar RUBY end context 'with a multiline memoization' do context 'without a `begin` and `end` block' do context 'when there is another block on the first line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= bar.each do |b| b.baz bb.ax end RUBY end context 'when there is another block on the following line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= bar.each do |b| b.baz b.bax end RUBY end context 'when there is a conditional on the first line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= if bar baz else bax end RUBY end context 'when there is a conditional on the following line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= if bar baz else bax end RUBY end end end end context 'EnforcedStyle: keyword' do let(:cop_config) { { 'EnforcedStyle' => 'keyword' } } include_examples 'with all enforced styles' context 'with a multiline memoization' do context 'without a `begin` and `end` block' do context 'when the expression is wrapped in parentheses' do it_behaves_like 'code with offense', <<-RUBY.strip_indent, foo ||= ( bar baz ) RUBY <<-RUBY.strip_indent foo ||= begin bar baz end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent, foo ||= ( bar baz ) RUBY <<-RUBY.strip_indent foo ||= begin bar baz end RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent, foo ||= (bar || baz) RUBY <<-RUBY.strip_indent foo ||= begin bar || baz end RUBY end end context 'with a `begin` and `end` block on the first line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= begin bar baz end RUBY end context 'with a `begin` and `end` block on the following line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= begin bar baz end RUBY end end end context 'EnforcedStyle: braces' do let(:cop_config) { { 'EnforcedStyle' => 'braces' } } include_examples 'with all enforced styles' context 'with a multiline memoization' do context 'without braces' do context 'when the expression is wrapped in' \ ' `begin` and `end` keywords' do it_behaves_like 'code with offense', <<-RUBY.strip_indent, foo ||= begin bar baz end RUBY <<-RUBY.strip_indent foo ||= ( bar baz ) RUBY it_behaves_like 'code with offense', <<-RUBY.strip_indent, foo ||= begin bar baz end RUBY <<-RUBY.strip_indent foo ||= ( bar baz ) RUBY end end context 'with parentheses on the first line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= ( bar baz ) RUBY end context 'with parentheses block on the following line' do it_behaves_like 'code without offense', <<-RUBY.strip_indent foo ||= ( bar baz ) RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb000066400000000000000000000016151322072016200266120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MultilineTernaryOperator do subject(:cop) { described_class.new } it 'registers offense when the if branch and the else branch are ' \ 'on a separate line from the condition' do inspect_source(<<-RUBY.strip_indent) a = cond ? b : c RUBY expect(cop.offenses.size).to eq(1) end it 'registers an offense when the false branch is on a separate line' do inspect_source(<<-RUBY.strip_indent) a = cond ? b : c RUBY expect(cop.offenses.size).to eq(1) end it 'registers an offense when everything is on a separate line' do inspect_source(<<-RUBY.strip_indent) a = cond ? b : c RUBY expect(cop.offenses.size).to eq(1) end it 'accepts a single line ternary operator expression' do expect_no_offenses('a = cond ? b : c') end end rubocop-0.52.1/spec/rubocop/cop/style/multiple_comparison_spec.rb000066400000000000000000000065501322072016200252210ustar00rootroot00000000000000# frozen_string_literal: true require 'spec_helper' RSpec.describe RuboCop::Cop::Style::MultipleComparison do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'does not register an offense for comparing an lvar' do inspect_source(['a = "a"', 'if a == "a"', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end it 'registers an offense when `a` is compared twice' do inspect_source(['a = "a"', 'if a == "a" || a == "b"', ' print a', 'end']) expect(cop.offenses.size).to eq(1) end it 'registers an offense when `a` is compared three times' do inspect_source(['a = "a"', 'if a == "a" || a == "b" || a == "c"', ' print a', 'end']) expect(cop.offenses.size).to eq(1) end it 'registers an offense when `a` is compared three times on the right ' \ 'hand side' do inspect_source(['a = "a"', 'if "a" == a || "b" == a || "c" == a', ' print a', 'end']) expect(cop.offenses.size).to eq(1) end it 'registers an offense when `a` is compared three times, once on the ' \ 'righthand side' do inspect_source(['a = "a"', 'if a == "a" || "b" == a || a == "c"', ' print a', 'end']) expect(cop.offenses.size).to eq(1) end it 'does not register an offense for comparing multiple literal strings' do inspect_source(['if "a" == "a" || "a" == "c"', ' print "a"', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for comparing multiple int literals' do inspect_source(['if 1 == 1 || 1 == 2', ' print 1', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for comparing lvars' do inspect_source(['a = "a"', 'b = "b"', 'if a == "a" || b == "b"', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for comparing lvars when a string is ' \ 'on the lefthand side' do inspect_source(['a = "a"', 'b = "b"', 'if a == "a" || "b" == b', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for a == b || b == a' do inspect_source(['a = "a"', 'b = "b"', 'if a == b || b == a', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for a duplicated condition' do inspect_source(['a = "a"', 'b = "b"', 'if a == b || a == b', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end it 'does not register an offense for Array#include?' do inspect_source(['a = "a"', 'if ["a", "b", "c"].include? a', ' print a', 'end']) expect(cop.offenses.empty?).to be(true) end end rubocop-0.52.1/spec/rubocop/cop/style/mutable_constant_spec.rb000066400000000000000000000103371322072016200244740ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::MutableConstant do subject(:cop) { described_class.new } let(:prefix) { nil } shared_examples :mutable_objects do |o| context 'when assigning with =' do it "registers an offense for #{o} assigned to a constant" do source = [prefix, "CONST = #{o}"].compact.join("\n") inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects by adding .freeze' do source = [prefix, "CONST = #{o}"].compact.join("\n") new_source = autocorrect_source(source) expect(new_source).to eq("#{source}.freeze") end end context 'when assigning with ||=' do it "registers an offense for #{o} assigned to a constant" do source = [prefix, "CONST ||= #{o}"].compact.join("\n") inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects by adding .freeze' do source = [prefix, "CONST ||= #{o}"].compact.join("\n") new_source = autocorrect_source(source) expect(new_source).to eq("#{source}.freeze") end end end it_behaves_like :mutable_objects, '[1, 2, 3]' it_behaves_like :mutable_objects, '{ a: 1, b: 2 }' it_behaves_like :mutable_objects, "'str'" it_behaves_like :mutable_objects, '"top#{1 + 2}"' shared_examples :immutable_objects do |o| it "allows #{o} to be assigned to a constant" do source = [prefix, "CONST = #{o}"].compact.join("\n") inspect_source(source) expect(cop.offenses.empty?).to be(true) end it "allows #{o} to be ||= to a constant" do source = [prefix, "CONST ||= #{o}"].compact.join("\n") inspect_source(source) expect(cop.offenses.empty?).to be(true) end end it_behaves_like :immutable_objects, '1' it_behaves_like :immutable_objects, '1.5' it_behaves_like :immutable_objects, ':sym' it 'allows method call assignments' do expect_no_offenses('TOP_TEST = Something.new') end context 'when performing a splat assignment' do it 'allows an immutable value' do expect_no_offenses('FOO = *(1...10)') end it 'allows a frozen array value' do expect_no_offenses('FOO = *[1...10].freeze') end it 'registers an offense for a mutable value' do source = 'BAR = *[1, 2, 3]' inspect_source(source) expect(cop.offenses.size).to eq(1) corrected = autocorrect_source(source) expect(corrected).to eq('BAR = *[1, 2, 3].freeze') end end context 'when assigning an array without brackets' do it 'adds brackets when auto-correcting' do new_source = autocorrect_source('XXX = YYY, ZZZ') expect(new_source).to eq 'XXX = [YYY, ZZZ].freeze' end it 'does not add brackets to %w() arrays' do new_source = autocorrect_source('XXX = %w(YYY ZZZ)') expect(new_source).to eq 'XXX = %w(YYY ZZZ).freeze' end end context 'when the constant is a frozen string literal' do if RuboCop::Config::KNOWN_RUBIES.include?(3.0) context 'when the target ruby version >= 3.0' do let(:ruby_version) { 3.0 } context 'when the frozen string literal comment is missing' do it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is true' do let(:prefix) { '# frozen_string_literal: true' } it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is false' do let(:prefix) { '# frozen_string_literal: false' } it_behaves_like :immutable_objects, '"#{a}"' end end end context 'when the target ruby version >= 2.3' do let(:ruby_version) { 2.3 } context 'when the frozen string literal comment is missing' do it_behaves_like :mutable_objects, '"#{a}"' end context 'when the frozen string literal comment is true' do let(:prefix) { '# frozen_string_literal: true' } it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is false' do let(:prefix) { '# frozen_string_literal: false' } it_behaves_like :mutable_objects, '"#{a}"' end end end end rubocop-0.52.1/spec/rubocop/cop/style/negated_if_spec.rb000066400000000000000000000131221322072016200232120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NegatedIf do subject(:cop) do config = RuboCop::Config.new( 'Style/NegatedIf' => { 'SupportedStyles' => %w[both prefix postfix], 'EnforcedStyle' => 'both' } ) described_class.new(config) end describe 'with “both” style' do it 'registers an offense for if with exclamation point condition' do inspect_source(<<-RUBY.strip_indent) if !a_condition some_method end some_method if !a_condition RUBY expect(cop.messages).to eq( ['Favor `unless` over `if` for negative ' \ 'conditions.'] * 2 ) end it 'registers an offense for unless with exclamation point condition' do inspect_source(<<-RUBY.strip_indent) unless !a_condition some_method end some_method unless !a_condition RUBY expect(cop.messages).to eq(['Favor `if` over `unless` for negative ' \ 'conditions.'] * 2) end it 'registers an offense for if with "not" condition' do inspect_source(<<-RUBY.strip_indent) if not a_condition some_method end some_method if not a_condition RUBY expect(cop.messages).to eq( ['Favor `unless` over `if` for negative ' \ 'conditions.'] * 2 ) expect(cop.offenses.map(&:line)).to eq([1, 4]) end it 'accepts an if/else with negative condition' do expect_no_offenses(<<-RUBY.strip_indent) if !a_condition some_method else something_else end if not a_condition some_method elsif other_condition something_else end RUBY end it 'accepts an if where only part of the condition is negated' do expect_no_offenses(<<-RUBY.strip_indent) if !condition && another_condition some_method end if not condition or another_condition some_method end some_method if not condition or another_condition RUBY end it 'accepts an if where the condition is doubly negated' do expect_no_offenses(<<-RUBY.strip_indent) if !!condition some_method end some_method if !!condition RUBY end it 'is not confused by negated elsif' do expect_no_offenses(<<-RUBY.strip_indent) if test.is_a?(String) 3 elsif test.is_a?(Array) 2 elsif !test.nil? 1 end RUBY end it 'autocorrects for postfix' do corrected = autocorrect_source('bar if !foo') expect(corrected).to eq 'bar unless foo' end it 'autocorrects by replacing if not with unless' do corrected = autocorrect_source('something if !x.even?') expect(corrected).to eq 'something unless x.even?' end it 'autocorrects by replacing parenthesized if not with unless' do corrected = autocorrect_source('something if (!x.even?)') expect(corrected).to eq 'something unless (x.even?)' end it 'autocorrects by replacing unless not with if' do corrected = autocorrect_source('something unless !x.even?') expect(corrected).to eq 'something if x.even?' end it 'autocorrects for prefix' do corrected = autocorrect_source(<<-RUBY.strip_indent) if !foo end RUBY expect(corrected).to eq <<-RUBY.strip_indent unless foo end RUBY end end describe 'with “prefix” style' do subject(:cop) do config = RuboCop::Config.new( 'Style/NegatedIf' => { 'SupportedStyles' => %w[both prefix postfix], 'EnforcedStyle' => 'prefix' } ) described_class.new(config) end it 'registers an offence for prefix' do inspect_source(<<-RUBY.strip_indent) if !foo end RUBY expect(cop.messages).to eq( ['Favor `unless` over `if` for negative conditions.'] ) end it 'does not register an offence for postfix' do expect_no_offenses('foo if !bar') end it 'autocorrects for prefix' do corrected = autocorrect_source(<<-RUBY.strip_indent) if !foo end RUBY expect(corrected).to eq <<-RUBY.strip_indent unless foo end RUBY end end describe 'with “postfix” style' do subject(:cop) do config = RuboCop::Config.new( 'Style/NegatedIf' => { 'SupportedStyles' => %w[both prefix postfix], 'EnforcedStyle' => 'postfix' } ) described_class.new(config) end it 'registers an offence for postfix' do expect_offense(<<-RUBY.strip_indent) foo if !bar ^^^^^^^^^^^ Favor `unless` over `if` for negative conditions. RUBY end it 'does not register an offence for prefix' do expect_no_offenses(<<-RUBY.strip_indent) if !foo end RUBY end it 'autocorrects for postfix' do corrected = autocorrect_source('bar if !foo') expect(corrected).to eq 'bar unless foo' end end it 'does not blow up for ternary ops' do expect_no_offenses('a ? b : c') end it 'does not blow up on a negated ternary operator' do expect_no_offenses('!foo.empty? ? :bar : :baz') end it 'does not blow up for empty if condition' do expect_no_offenses(<<-RUBY.strip_indent) if () end RUBY end it 'does not blow up for empty unless condition' do expect_no_offenses(<<-RUBY.strip_indent) unless () end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/negated_while_spec.rb000066400000000000000000000046601322072016200237330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NegatedWhile do subject(:cop) { described_class.new } it 'registers an offense for while with exclamation point condition' do inspect_source(<<-RUBY.strip_indent) while !a_condition some_method end some_method while !a_condition RUBY expect(cop.messages).to eq( ['Favor `until` over `while` for negative conditions.'] * 2 ) end it 'registers an offense for until with exclamation point condition' do inspect_source(<<-RUBY.strip_indent) until !a_condition some_method end some_method until !a_condition RUBY expect(cop.messages) .to eq(['Favor `while` over `until` for negative conditions.'] * 2) end it 'registers an offense for while with "not" condition' do inspect_source(<<-RUBY.strip_indent) while (not a_condition) some_method end some_method while not a_condition RUBY expect(cop.messages).to eq( ['Favor `until` over `while` for negative conditions.'] * 2 ) expect(cop.offenses.map(&:line)).to eq([1, 4]) end it 'accepts a while where only part of the condition is negated' do expect_no_offenses(<<-RUBY.strip_indent) while !a_condition && another_condition some_method end while not a_condition or another_condition some_method end some_method while not a_condition or other_cond RUBY end it 'accepts a while where the condition is doubly negated' do expect_no_offenses(<<-RUBY.strip_indent) while !!a_condition some_method end some_method while !!a_condition RUBY end it 'autocorrects by replacing while not with until' do corrected = autocorrect_source(<<-RUBY.strip_indent) something while !x.even? something while(!x.even?) RUBY expect(corrected).to eq <<-RUBY.strip_indent something until x.even? something until(x.even?) RUBY end it 'autocorrects by replacing until not with while' do corrected = autocorrect_source('something until !x.even?') expect(corrected).to eq 'something while x.even?' end it 'does not blow up for empty while condition' do expect_no_offenses(<<-RUBY.strip_indent) while () end RUBY end it 'does not blow up for empty until condition' do expect_no_offenses(<<-RUBY.strip_indent) until () end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/nested_modifier_spec.rb000066400000000000000000000054051322072016200242720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NestedModifier do subject(:cop) { described_class.new } shared_examples 'avoidable' do |keyword| it "registers an offense for modifier #{keyword}" do inspect_source("something #{keyword} a if b") expect(cop.messages).to eq(['Avoid using nested modifiers.']) expect(cop.highlights).to eq([keyword]) end end shared_examples 'not correctable' do |keyword| it "does not auto-correct when #{keyword} is the outer modifier" do source = "something if a #{keyword} b" corrected = autocorrect_source(source) expect(corrected).to eq source expect(cop.offenses.map(&:corrected?)).to eq [false] end it "does not auto-correct when #{keyword} is the inner modifier" do source = "something #{keyword} a if b" corrected = autocorrect_source(source) expect(corrected).to eq source expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'if' do it_behaves_like 'avoidable', 'if' end context 'unless' do it_behaves_like 'avoidable', 'unless' end it 'auto-corrects if + if' do corrected = autocorrect_source('something if a if b') expect(corrected).to eq 'something if b && a' end it 'auto-corrects unless + unless' do corrected = autocorrect_source('something unless a unless b') expect(corrected).to eq 'something unless b || a' end it 'auto-corrects if + unless' do corrected = autocorrect_source('something if a unless b') expect(corrected).to eq 'something unless b || !a' end it 'auto-corrects unless with a comparison operator + if' do corrected = autocorrect_source('something unless b > 1 if true') expect(corrected).to eq 'something if true && !(b > 1)' end it 'auto-corrects unless + if' do corrected = autocorrect_source('something unless a if b') expect(corrected).to eq 'something if b && !a' end it 'adds parentheses when needed in auto-correction' do corrected = autocorrect_source('something if a || b if c || d') expect(corrected).to eq 'something if (c || d) && (a || b)' end it 'does not add redundant parentheses in auto-correction' do corrected = autocorrect_source('something if a unless c || d') expect(corrected).to eq 'something unless c || d || !a' end context 'while' do it_behaves_like 'avoidable', 'while' it_behaves_like 'not correctable', 'while' end context 'until' do it_behaves_like 'avoidable', 'until' it_behaves_like 'not correctable', 'until' end it 'registers one offense for more than two modifiers' do expect_offense(<<-RUBY.strip_indent) something until a while b unless c if d ^^^^^^ Avoid using nested modifiers. RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/nested_parenthesized_calls_spec.rb000066400000000000000000000051001322072016200265070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NestedParenthesizedCalls do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new( 'Style/NestedParenthesizedCalls' => { 'Whitelist' => ['be'] } ) end context 'on a non-parenthesized method call' do it "doesn't register an offense" do expect_no_offenses('puts 1, 2') end end context 'on a method call with no arguments' do it "doesn't register an offense" do expect_no_offenses('puts') end end context 'on a nested, parenthesized method call' do it "doesn't register an offense" do expect_no_offenses('puts(compute(something))') end end context 'on a non-parenthesized call nested in a parenthesized one' do context 'with a single argument to the nested call' do let(:source) { 'puts(compute something)' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) puts(compute something) ^^^^^^^^^^^^^^^^^ Add parentheses to nested method call `compute something`. RUBY end it 'auto-corrects by adding parentheses' do new_source = autocorrect_source(source) expect(new_source).to eq('puts(compute(something))') end end context 'with multiple arguments to the nested call' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) puts(compute first, second) ^^^^^^^^^^^^^^^^^^^^^ Add parentheses to nested method call `compute first, second`. RUBY end it 'auto-corrects by adding parentheses' do new_source = autocorrect_source('puts(compute first, second)') expect(new_source).to eq('puts(compute(first, second))') end end end context 'on a call with no arguments, nested in a parenthesized one' do it "doesn't register an offense" do expect_no_offenses('puts(compute)') end end context 'on an aref, nested in a parenthesized method call' do it "doesn't register an offense" do expect_no_offenses('method(obj[1])') end end context 'on a deeply nested argument' do it "doesn't register an offense" do expect_no_offenses('method(block_taker { another_method 1 })') end end context 'on a whitelisted method' do it "doesn't register an offense" do expect_no_offenses('expect(obj).to(be true)') end end context 'on a call to a setter method' do it "doesn't register an offense" do expect_no_offenses('expect(object1.attr = 1).to eq 1') end end end rubocop-0.52.1/spec/rubocop/cop/style/nested_ternary_operator_spec.rb000066400000000000000000000011121322072016200260620ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NestedTernaryOperator do subject(:cop) { described_class.new } it 'registers an offense for a nested ternary operator expression' do expect_offense(<<-RUBY.strip_indent) a ? (b ? b1 : b2) : a2 ^^^^^^^^^^^ Ternary operators must not be nested. Prefer `if` or `else` constructs instead. RUBY end it 'accepts a non-nested ternary operator within an if' do expect_no_offenses(<<-RUBY.strip_indent) a = if x cond ? b : c else d end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/next_spec.rb000066400000000000000000000345651322072016200221210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Next, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'MinBodyLength' => 1 } } shared_examples 'iterators' do |condition| let(:opposite) { condition == 'if' ? 'unless' : 'if' } it "registers an offense for #{condition} inside of downto" do inspect_source(<<-RUBY.strip_indent) 3.downto(1) do #{condition} o == 1 puts o end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "autocorrects #{condition} inside of downto" do new_source = autocorrect_source(<<-RUBY.strip_indent) 3.downto(1) do #{condition} o == 1 puts o end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) 3.downto(1) do next #{opposite} o == 1 puts o end RUBY end it "registers an offense for #{condition} inside of each" do inspect_source(<<-RUBY.strip_indent) [].each do |o| #{condition} o == 1 puts o end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "autocorrects #{condition} inside of each" do new_source = autocorrect_source(<<-RUBY.strip_indent) [].each do |o| #{condition} o == 1 puts o end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [].each do |o| next #{opposite} o == 1 puts o end RUBY end it "registers an offense for #{condition} inside of each_with_object" do inspect_source(<<-RUBY.strip_indent) [].each_with_object({}) do |o, a| #{condition} o == 1 a[o] = {} end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of for" do inspect_source(<<-RUBY.strip_indent) for o in 1..3 do #{condition} o == 1 puts o end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "autocorrects #{condition} inside of for" do new_source = autocorrect_source(<<-RUBY.strip_indent) for o in 1..3 do #{condition} o == 1 puts o end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) for o in 1..3 do next #{opposite} o == 1 puts o end RUBY end it "registers an offense for #{condition} inside of loop" do inspect_source(<<-RUBY.strip_indent) loop do #{condition} o == 1 puts o end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of map" do inspect_source(<<-RUBY.strip_indent) loop do {}.map do |k, v| #{condition} v == 1 puts k end end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} v == 1"]) end it "registers an offense for #{condition} inside of times" do inspect_source(<<-RUBY.strip_indent) loop do 3.times do |o| #{condition} o == 1 puts o end end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of collect" do inspect_source(<<-RUBY.strip_indent) [].collect do |o| #{condition} o == 1 true end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of select" do inspect_source(<<-RUBY.strip_indent) [].select do |o| #{condition} o == 1 true end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of select!" do inspect_source(<<-RUBY.strip_indent) [].select! do |o| #{condition} o == 1 true end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of reject" do inspect_source(<<-RUBY.strip_indent) [].reject do |o| #{condition} o == 1 true end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of reject!" do inspect_source(<<-RUBY.strip_indent) [].reject! do |o| #{condition} o == 1 true end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of nested iterators" do inspect_source(<<-RUBY.strip_indent) loop do until false #{condition} o == 1 puts o end end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it "registers an offense for #{condition} inside of nested iterators" do inspect_source(<<-RUBY.strip_indent) loop do while true #{condition} o == 1 puts o end end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it 'registers an offense for a condition at the end of an iterator ' \ 'when there is more in the iterator than the condition' do inspect_source(<<-RUBY.strip_indent) [].each do |o| puts o #{condition} o == 1 puts o end end RUBY expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["#{condition} o == 1"]) end it 'allows loops with conditional break' do expect_no_offenses(<<-RUBY.strip_indent) loop do puts '' break #{condition} o == 1 end RUBY end it 'allows loops with conditional return' do expect_no_offenses(<<-RUBY.strip_indent) loop do puts '' return #{condition} o == 1 end RUBY end it "allows loops with #{condition} being the entire body with else" do inspect_source(<<-RUBY.strip_indent) [].each do |o| #{condition} o == 1 puts o else puts 'no' end end RUBY expect(cop.offenses.empty?).to be(true) end it "allows loops with #{condition} with else, nested in another " \ 'condition' do inspect_source(<<-RUBY.strip_indent) [].each do |o| if foo #{condition} o == 1 puts o else puts 'no' end end end RUBY expect(cop.offenses.empty?).to be(true) end it "allows loops with #{condition} with else at the end" do inspect_source(<<-RUBY.strip_indent) [].each do |o| puts o #{condition} o == 1 puts o else puts 'no' end end RUBY expect(cop.offenses.empty?).to be(true) end it "reports an offense for #{condition} whose body has 3 lines" do inspect_source(<<-RUBY.strip_indent) arr.each do |e| #{condition} something work work work end end RUBY expect(cop.offenses.size).to eq(1) expect(cop.highlights).to eq(["#{condition} something"]) end context 'EnforcedStyle: skip_modifier_ifs' do let(:cop_config) do { 'EnforcedStyle' => 'skip_modifier_ifs' } end it "allows modifier #{condition}" do inspect_source(<<-RUBY.strip_indent) [].each do |o| puts o #{condition} o == 1 end RUBY expect(cop.offenses.empty?).to be(true) end end context 'EnforcedStyle: always' do let(:cop_config) do { 'EnforcedStyle' => 'always' } end let(:opposite) { condition == 'if' ? 'unless' : 'if' } let(:source) do <<-RUBY.strip_indent [].each do |o| puts o #{condition} o == 1 # comment end RUBY end it "registers an offense for modifier #{condition}" do inspect_source(source) expect(cop.messages).to eq(['Use `next` to skip iteration.']) expect(cop.highlights).to eq(["puts o #{condition} o == 1"]) end it "auto-corrects modifier #{condition}" do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) [].each do |o| next #{opposite} o == 1 puts o # comment end RUBY end end it 'auto-corrects a misaligned end' do new_source = autocorrect_source(<<-RUBY.strip_indent) [1, 2, 3, 4].each do |num| if !opts.nil? puts num if num != 2 puts 'hello' puts 'world' end end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) [1, 2, 3, 4].each do |num| next unless !opts.nil? puts num if num != 2 puts 'hello' puts 'world' end end RUBY end end it 'keeps comments when autocorrecting' do new_source = autocorrect_source(['loop do', ' if test # keep me', ' # keep me', ' something # keep me', ' # keep me', ' ', ' end # keep me', 'end']) expect(new_source).to eq(['loop do', ' next unless test # keep me', ' # keep me', ' something # keep me', ' # keep me', ' ', ' # keep me', 'end'].join("\n")) end it 'handles `then` when autocorrecting' do new_source = autocorrect_source(<<-RUBY.strip_indent) loop do if test then something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) loop do next unless test something end RUBY end it "doesn't reindent heredoc bodies when autocorrecting" do new_source = autocorrect_source(<<-RUBY.strip_indent) loop do if test str = <<-BLAH this is a heredoc nice eh? BLAH something end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) loop do next unless test str = <<-BLAH this is a heredoc nice eh? BLAH something end RUBY end it 'handles nested autocorrections' do new_source = autocorrect_source(<<-RUBY.strip_indent) loop do if test loop do if test something end end end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) loop do next unless test loop do next unless test something end end RUBY end it_behaves_like 'iterators', 'if' it_behaves_like 'iterators', 'unless' it 'allows empty blocks' do expect_no_offenses(<<-RUBY.strip_indent) [].each do end [].each { } RUBY end it 'allows loops with conditions at the end with ternary op' do expect_no_offenses(<<-RUBY.strip_indent) [].each do |o| o == x ? y : z end RUBY end it 'allows super nodes' do # https://github.com/bbatsov/rubocop/issues/1115 expect_no_offenses(<<-RUBY.strip_indent) def foo super(a, a) { a } end RUBY end it 'does not blow up on empty body until block' do expect_no_offenses('until sup; end') end it 'does not blow up on empty body while block' do expect_no_offenses('while sup; end') end it 'does not blow up on empty body for block' do expect_no_offenses('for x in y; end') end it 'does not crash with an empty body branch' do expect_no_offenses(<<-RUBY.strip_indent) loop do if true end end RUBY end it 'does not crash with empty brackets' do expect_no_offenses(<<-RUBY.strip_indent) loop do () end RUBY end context 'MinBodyLength: 3' do let(:cop_config) do { 'MinBodyLength' => 3 } end it 'accepts if whose body has 1 line' do expect_no_offenses(<<-RUBY.strip_indent) arr.each do |e| if something work end end RUBY end end context 'Invalid MinBodyLength' do let(:cop_config) do { 'MinBodyLength' => -2 } end it 'fails with an error' do source = <<-RUBY.strip_indent loop do if o == 1 puts o end end RUBY expect { inspect_source(source) } .to raise_error('MinBodyLength needs to be a positive integer!') end end end rubocop-0.52.1/spec/rubocop/cop/style/nil_comparison_spec.rb000066400000000000000000000013611322072016200241430ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NilComparison do subject(:cop) { described_class.new } it 'registers an offense for == nil' do expect_offense(<<-RUBY.strip_indent) x == nil ^^ Prefer the use of the `nil?` predicate. RUBY end it 'registers an offense for === nil' do expect_offense(<<-RUBY.strip_indent) x === nil ^^^ Prefer the use of the `nil?` predicate. RUBY end it 'autocorrects by replacing == nil with .nil?' do corrected = autocorrect_source('x == nil') expect(corrected).to eq 'x.nil?' end it 'autocorrects by replacing === nil with .nil?' do corrected = autocorrect_source('x === nil') expect(corrected).to eq 'x.nil?' end end rubocop-0.52.1/spec/rubocop/cop/style/non_nil_check_spec.rb000066400000000000000000000104331322072016200237200ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NonNilCheck, :config do subject(:cop) { described_class.new(config) } context 'when not allowing semantic changes' do let(:cop_config) do { 'IncludeSemanticChanges' => false } end it 'registers an offense for != nil' do expect_offense(<<-RUBY.strip_indent) x != nil ^^ Prefer `!expression.nil?` over `expression != nil`. RUBY end it 'does not register an offense for != 0' do expect_no_offenses('x != 0') end it 'does not register an offense for !x.nil?' do expect_no_offenses('!x.nil?') end it 'does not register an offense for not x.nil?' do expect_no_offenses('not x.nil?') end it 'does not register an offense if only expression in predicate' do expect_no_offenses(<<-RUBY.strip_indent) def signed_in? !current_user.nil? end RUBY end it 'does not register an offense if only expression in class predicate' do expect_no_offenses(<<-RUBY.strip_indent) def Test.signed_in? current_user != nil end RUBY end it 'does not register an offense if last expression in predicate' do expect_no_offenses(<<-RUBY.strip_indent) def signed_in? something current_user != nil end RUBY end it 'does not register an offense if last expression in class predicate' do expect_no_offenses(<<-RUBY.strip_indent) def Test.signed_in? something current_user != nil end RUBY end it 'autocorrects by changing `!= nil` to `!x.nil?`' do corrected = autocorrect_source('x != nil') expect(corrected).to eq '!x.nil?' end it 'does not autocorrect by removing non-nil (!x.nil?) check' do corrected = autocorrect_source('!x.nil?') expect(corrected).to eq '!x.nil?' end it 'does not blow up when autocorrecting implicit receiver' do corrected = autocorrect_source('!nil?') expect(corrected).to eq '!nil?' end it 'does not report corrected when the code was not modified' do source = 'return nil unless (line =~ //) != nil' corrected = autocorrect_source(source) expect(corrected).to eq(source) expect(cop.corrections.empty?).to be(true) end end context 'when allowing semantic changes' do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'IncludeSemanticChanges' => true } end it 'registers an offense for `!x.nil?`' do expect_offense(<<-RUBY.strip_indent) !x.nil? ^^^^^^^ Explicit non-nil checks are usually redundant. RUBY end it 'registers an offense for unless x.nil?' do expect_offense(<<-RUBY.strip_indent) puts b unless x.nil? ^^^^^^ Explicit non-nil checks are usually redundant. RUBY end it 'does not register an offense for `x.nil?`' do expect_no_offenses('x.nil?') end it 'does not register an offense for `!x`' do expect_no_offenses('!x') end it 'registers an offense for `not x.nil?`' do expect_offense(<<-RUBY.strip_indent) not x.nil? ^^^^^^^^^^ Explicit non-nil checks are usually redundant. RUBY end it 'does not blow up with ternary operators' do expect_no_offenses('my_var.nil? ? 1 : 0') end it 'autocorrects by changing unless x.nil? to if x' do corrected = autocorrect_source('puts a unless x.nil?') expect(corrected).to eq 'puts a if x' end it 'autocorrects by changing `x != nil` to `x`' do corrected = autocorrect_source('x != nil') expect(corrected).to eq 'x' end it 'autocorrects by changing `!x.nil?` to `x`' do corrected = autocorrect_source('!x.nil?') expect(corrected).to eq 'x' end it 'does not blow up when autocorrecting implicit receiver' do corrected = autocorrect_source('!nil?') expect(corrected).to eq 'self' end it 'corrects code that would not be modified if ' \ 'IncludeSemanticChanges were false' do corrected = autocorrect_source('return nil unless (line =~ //) != nil') expect(corrected).to eq('return nil unless (line =~ //)') end end end rubocop-0.52.1/spec/rubocop/cop/style/not_spec.rb000066400000000000000000000030121322072016200217220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Not, :config do subject(:cop) { described_class.new(config) } it 'registers an offense for not' do expect_offense(<<-RUBY.strip_indent) not test ^^^ Use `!` instead of `not`. RUBY end it 'does not register an offense for !' do expect_no_offenses('!test') end it 'auto-corrects "not" with !' do new_source = autocorrect_source('x = 10 if not y') expect(new_source).to eq('x = 10 if !y') end it 'auto-corrects "not" followed by parens with !' do new_source = autocorrect_source('not(test)') expect(new_source).to eq('!(test)') end it 'uses the reverse operator when `not` is applied to a comparison' do src = 'not x < y' new_source = autocorrect_source(src) expect(new_source).to eq('x >= y') end it 'parenthesizes when `not` would change the meaning of a binary exp' do src = 'not a >> b' new_source = autocorrect_source(src) expect(new_source).to eq('!(a >> b)') end it 'parenthesizes when `not` is applied to a ternary op' do src = 'not a ? b : c' new_source = autocorrect_source(src) expect(new_source).to eq('!(a ? b : c)') end it 'parenthesizes when `not` is applied to and' do src = 'not a && b' new_source = autocorrect_source(src) expect(new_source).to eq('!(a && b)') end it 'parenthesizes when `not` is applied to or' do src = 'not a || b' new_source = autocorrect_source(src) expect(new_source).to eq('!(a || b)') end end rubocop-0.52.1/spec/rubocop/cop/style/numeric_literal_prefix_spec.rb000066400000000000000000000103721322072016200256640ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NumericLiteralPrefix, :config do subject(:cop) { described_class.new(config) } context 'octal literals' do context 'when config is zero_with_o' do let(:cop_config) do { 'EnforcedOctalStyle' => 'zero_with_o' } end it 'registers an offense for prefixes `0` and `0O`' do inspect_source(<<-RUBY.strip_indent) a = 01234 b(0O1234) RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq).to eq(['Use 0o for octal literals.']) expect(cop.highlights).to eq(%w[01234 0O1234]) end it 'does not register offense for lowercase prefix' do expect_no_offenses(<<-RUBY.strip_indent) a = 0o101 b = 0o567 RUBY end it 'autocorrects an octal literal starting with 0' do corrected = autocorrect_source(['a = 01234']) expect(corrected).to eq('a = 0o1234') end it 'autocorrects an octal literal starting with 0O' do corrected = autocorrect_source(['b(0O1234, a)']) expect(corrected).to eq('b(0o1234, a)') end end context 'when config is zero_only' do let(:cop_config) do { 'EnforcedOctalStyle' => 'zero_only' } end it 'registers an offense for prefix `0O` and `0o`' do inspect_source(<<-RUBY.strip_indent) a = 0O1234 b(0o1234) RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq).to eq(['Use 0 for octal literals.']) expect(cop.highlights).to eq(%w[0O1234 0o1234]) end it 'does not register offense for prefix `0`' do expect_no_offenses('b = 0567') end it 'autocorrects an octal literal starting with 0O or 0o' do corrected = autocorrect_source(<<-RUBY.strip_indent) a = 0O1234 b(0o1234) RUBY expect(corrected).to eq <<-RUBY.strip_indent a = 01234 b(01234) RUBY end it 'does not autocorrect an octal literal starting with 0' do corrected = autocorrect_source(['b(01234, a)']) expect(corrected).to eq 'b(01234, a)' end end end context 'hex literals' do it 'registers an offense for uppercase prefix' do inspect_source(<<-RUBY.strip_indent) a = 0X1AC b(0XABC) RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq).to eq(['Use 0x for hexadecimal literals.']) expect(cop.highlights).to eq(%w[0X1AC 0XABC]) end it 'does not register offense for lowercase prefix' do expect_no_offenses('a = 0x101') end it 'autocorrects literals with uppercase prefix' do corrected = autocorrect_source(['a = 0XAB']) expect(corrected).to eq 'a = 0xAB' end end context 'binary literals' do it 'registers an offense for uppercase prefix' do inspect_source(<<-RUBY.strip_indent) a = 0B10101 b(0B111) RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq).to eq(['Use 0b for binary literals.']) expect(cop.highlights).to eq(%w[0B10101 0B111]) end it 'does not register offense for lowercase prefix' do expect_no_offenses('a = 0b101') end it 'autocorrects literals with uppercase prefix' do corrected = autocorrect_source(['a = 0B1010']) expect(corrected).to eq 'a = 0b1010' end end context 'decimal literals' do it 'registers an offense for prefixes' do inspect_source(<<-RUBY.strip_indent) a = 0d1234 b(0D1234) RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages.uniq) .to eq(['Do not use prefixes for decimal literals.']) expect(cop.highlights).to eq(%w[0d1234 0D1234]) end it 'does not register offense for no prefix' do expect_no_offenses('a = 101') end it 'autocorrects literals with prefix' do corrected = autocorrect_source(['a = 0d1234', 'b(0D1990)']) expect(corrected).to eq "a = 1234\nb(1990)" end it 'does not autocorrect literals with no prefix' do corrected = autocorrect_source(['a = 1234', 'b(1990)']) expect(corrected).to eq "a = 1234\nb(1990)" end end end rubocop-0.52.1/spec/rubocop/cop/style/numeric_literals_spec.rb000066400000000000000000000055701322072016200244760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NumericLiterals, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'MinDigits' => 5 } } it 'registers an offense for a long undelimited integer' do inspect_source('a = 12345') expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('MinDigits' => 6) end it 'registers an offense for a float with a long undelimited integer part' do inspect_source('a = 123456.789') expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('MinDigits' => 7) end it 'accepts integers with less than three places at the end' do expect_no_offenses(<<-RUBY.strip_indent) a = 123_456_789_00 b = 819_2 RUBY end it 'registers an offense for an integer with misplaced underscore' do inspect_source(<<-RUBY.strip_indent) a = 123_456_78_90_00 b = 1_8192 RUBY expect(cop.offenses.size).to eq(2) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'accepts long numbers with underscore' do expect_no_offenses(<<-RUBY.strip_indent) a = 123_456 b = 123_456.55 RUBY end it 'accepts a short integer without underscore' do expect_no_offenses('a = 123') end it 'does not count a leading minus sign as a digit' do expect_no_offenses('a = -1230') end it 'accepts short numbers without underscore' do expect_no_offenses(<<-RUBY.strip_indent) a = 123 b = 123.456 RUBY end it 'ignores non-decimal literals' do expect_no_offenses(<<-RUBY.strip_indent) a = 0b1010101010101 b = 01717171717171 c = 0xab11111111bb RUBY end it 'autocorrects a long integer offense' do corrected = autocorrect_source(['a = 123456']) expect(corrected).to eq 'a = 123_456' end it 'autocorrects an integer with misplaced underscore' do corrected = autocorrect_source(['a = 123_456_78_90_00']) expect(corrected).to eq 'a = 123_456_789_000' end it 'autocorrects negative numbers' do corrected = autocorrect_source(['a = -123456']) expect(corrected).to eq 'a = -123_456' end it 'autocorrects floating-point numbers' do corrected = autocorrect_source(['a = 123456.78']) expect(corrected).to eq 'a = 123_456.78' end it 'autocorrects negative floating-point numbers' do corrected = autocorrect_source(['a = -123456.78']) expect(corrected).to eq 'a = -123_456.78' end context 'strict' do let(:cop_config) do { 'MinDigits' => 5, 'Strict' => true } end it 'registers an offense for an integer with misplaced underscore' do inspect_source(<<-RUBY.strip_indent) a = 123_456_78_90_00 b = 81_92 RUBY expect(cop.offenses.size).to eq(2) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end end rubocop-0.52.1/spec/rubocop/cop/style/numeric_predicate_spec.rb000066400000000000000000000126511322072016200246150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::NumericPredicate, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end shared_examples 'code with offense' do |code, expected| context "when checking #{code}" do let(:source) { code } let(:message) { "Use `#{expected}` instead of `#{code}`." } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end context 'when configured to enforce numeric predicate methods' do let(:cop_config) do { 'EnforcedStyle' => 'predicate', 'AutoCorrect' => true } end context 'when checking if a number is zero' do it_behaves_like 'code with offense', 'number == 0', 'number.zero?' it_behaves_like 'code with offense', '0 == number', 'number.zero?' context 'with a complex expression' do it_behaves_like 'code with offense', 'foo - 1 == 0', '(foo - 1).zero?' it_behaves_like 'code with offense', '0 == foo - 1', '(foo - 1).zero?' end context 'when comparing against a global variable' do it_behaves_like 'code without offense', '$CHILD_STATUS == 0' it_behaves_like 'code without offense', '0 == $CHILD_STATUS' end end context 'with checking if a number is not zero' do it_behaves_like 'code without offense', 'number != 0' it_behaves_like 'code without offense', '0 != number' context 'with a complex expression' do it_behaves_like 'code without offense', 'foo - 1 != 0' it_behaves_like 'code without offense', '0 != foo - 1' end context 'when comparing against a global variable' do it_behaves_like 'code without offense', '$CHILD_STATUS != 0' it_behaves_like 'code without offense', '0 != $CHILD_STATUS' end end context 'when checking if a number is positive' do context 'when target ruby version is 2.3 or higher', :ruby23 do it_behaves_like 'code with offense', 'number > 0', 'number.positive?' it_behaves_like 'code with offense', '0 < number', 'number.positive?' context 'with a complex expression' do it_behaves_like 'code with offense', 'foo - 1 > 0', '(foo - 1).positive?' it_behaves_like 'code with offense', '0 < foo - 1', '(foo - 1).positive?' end end context 'when target ruby version is 2.2 or lower', :ruby22 do it_behaves_like 'code without offense', 'number > 0' it_behaves_like 'code without offense', '0 < number' end end context 'when checking if a number is negative' do context 'when target ruby version is 2.3 or higher', :ruby23 do it_behaves_like 'code with offense', 'number < 0', 'number.negative?' it_behaves_like 'code with offense', '0 > number', 'number.negative?' context 'with a complex expression' do it_behaves_like 'code with offense', 'foo - 1 < 0', '(foo - 1).negative?' it_behaves_like 'code with offense', '0 > foo - 1', '(foo - 1).negative?' end end context 'when target ruby version is 2.2 or lower', :ruby22 do it_behaves_like 'code without offense', 'number < 0' it_behaves_like 'code without offense', '0 > number' end end end context 'when configured to enforce numeric comparison methods' do let(:cop_config) do { 'EnforcedStyle' => 'comparison', 'AutoCorrect' => true } end context 'when checking if a number is zero' do it_behaves_like 'code with offense', 'number.zero?', 'number == 0' end context 'with checking if a number is not zero' do it_behaves_like 'code without offense', 'number.nonzero?' end context 'when checking if a number is positive' do it_behaves_like 'code with offense', 'number.positive?', 'number > 0' end context 'when checking if a number is negative' do it_behaves_like 'code with offense', 'number.negative?', 'number < 0' end end end rubocop-0.52.1/spec/rubocop/cop/style/one_line_conditional_spec.rb000066400000000000000000000062261322072016200253070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::OneLineConditional do subject(:cop) { described_class.new } shared_examples 'offense' do |condition| it 'registers an offense' do inspect_source(source) expect(cop.messages) .to eq(['Favor the ternary operator (`?:`)' \ " over `#{condition}/then/else/end` constructs."]) end end shared_examples 'no offense' do it 'does not register an offense' do inspect_source(source) expect(cop.messages.empty?).to be(true) end end shared_examples 'autocorrect' do |correct_code| it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq(correct_code) end end context 'one line if/then/else/end' do let(:source) { 'if cond then run else dont end' } include_examples 'offense', 'if' include_examples 'autocorrect', 'cond ? run : dont' context 'empty else' do let(:source) { 'if cond then run else end' } include_examples 'no offense' end end context 'one line if/then/end' do let(:source) { 'if cond then run end' } include_examples 'no offense' end context 'one line unless/then/else/end' do let(:source) { 'unless cond then run else dont end' } include_examples 'offense', 'unless' include_examples 'autocorrect', 'cond ? dont : run' context 'empty else' do let(:source) { 'unless cond then run else end' } include_examples 'no offense' end end context 'one line unless/then/end' do let(:source) { 'unless cond then run end' } include_examples 'no offense' end %w[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ ! != !~ && ||].each do |operator| it 'parenthesizes the expression if it is preceded by an operator' do corrected = autocorrect_source("a #{operator} if cond then run else dont end") expect(corrected).to eq("a #{operator} (cond ? run : dont)") end end shared_examples 'changed precedence' do |expr| it "adds parentheses around `#{expr}`" do corrected = autocorrect_source("if #{expr} then #{expr} else #{expr} end") expect(corrected).to eq("(#{expr}) ? (#{expr}) : (#{expr})") end end it_behaves_like 'changed precedence', 'puts 1' it_behaves_like 'changed precedence', 'defined? :A' it_behaves_like 'changed precedence', 'yield a' it_behaves_like 'changed precedence', 'super b' it_behaves_like 'changed precedence', 'not a' it_behaves_like 'changed precedence', 'a and b' it_behaves_like 'changed precedence', 'a or b' it_behaves_like 'changed precedence', 'a = b' it_behaves_like 'changed precedence', 'a ? b : c' it 'does not parenthesize expressions when they do not contain method ' \ 'calls with unparenthesized arguments' do corrected = autocorrect_source('if a(0) then puts(1) else yield(2) end') expect(corrected).to eq('a(0) ? puts(1) : yield(2)') end it 'does not parenthesize expressions when they contain unparenthesized ' \ 'operator method calls' do corrected = autocorrect_source('if 0 + 0 then 1 + 1 else 2 + 2 end') expect(corrected).to eq('0 + 0 ? 1 + 1 : 2 + 2') end end rubocop-0.52.1/spec/rubocop/cop/style/option_hash_spec.rb000066400000000000000000000037321322072016200234460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::OptionHash, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'SuspiciousParamNames' => suspicious_names } } let(:suspicious_names) { ['options'] } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def some_method(options = {}) ^^^^^^^^^^^^ Prefer keyword arguments to options hashes. puts some_arg end RUBY end context 'when the last argument is an options hash named something else' do let(:source) do <<-RUBY.strip_indent def steep(flavor, duration, config={}) mug = config.fetch(:mug) prep(flavor, duration, mug) end RUBY end it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def steep(flavor, duration, config={}) mug = config.fetch(:mug) prep(flavor, duration, mug) end RUBY end context 'when the argument name is in the list of suspicious names' do let(:suspicious_names) { %w[options config] } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def steep(flavor, duration, config={}) ^^^^^^^^^ Prefer keyword arguments to options hashes. mug = config.fetch(:mug) prep(flavor, duration, mug) end RUBY end end end context 'when there are no arguments' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def meditate puts true puts true end RUBY end end context 'when the last argument is a non-options-hash optional hash' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) def cook(instructions, ingredients = { hot: [], cold: [] }) prep(ingredients) end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/optional_arguments_spec.rb000066400000000000000000000055101322072016200250410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::OptionalArguments do subject(:cop) { described_class.new } let(:message) do 'Optional arguments should appear at the end of the argument list.' end it 'registers an offense when an optional argument is followed by a ' \ 'required argument' do inspect_source(<<-RUBY.strip_indent) def foo(a = 1, b) end RUBY expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(['a = 1']) end it 'registers an offense for each optional argument when multiple ' \ 'optional arguments are followed by a required argument' do inspect_source(<<-RUBY.strip_indent) def foo(a = 1, b = 2, c) end RUBY expect(cop.messages).to eq([message, message]) expect(cop.highlights).to eq(['a = 1', 'b = 2']) end it 'allows methods without arguments' do expect_no_offenses(<<-RUBY.strip_indent) def foo end RUBY end it 'allows methods with only one required argument' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a) end RUBY end it 'allows methods with only required arguments' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a, b, c) end RUBY end it 'allows methods with only one optional argument' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a = 1) end RUBY end it 'allows methods with only optional arguments' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a = 1, b = 2, c = 3) end RUBY end it 'allows methods with multiple optional arguments at the end' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a, b = 2, c = 3) end RUBY end context 'named params' do context 'with default values' do it 'allows optional arguments before an optional named argument' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a = 1, b: 2) end RUBY end end context 'required params' do it 'registers an offense for optional arguments that come before ' \ 'required arguments where there are name arguments' do inspect_source(<<-RUBY.strip_indent) def foo(a = 1, b, c:, d: 4) end RUBY expect(cop.messages).to eq([message]) expect(cop.highlights).to eq(['a = 1']) end it 'allows optional arguments before required named arguments' do expect_no_offenses(<<-RUBY.strip_indent) def foo(a = 1, b:) end RUBY end it 'allows optional arguments to come before a mix of required and ' \ 'optional named argument' do inspect_source(<<-RUBY.strip_indent) def foo(a = 1, b:, c: 3) end RUBY expect(cop.messages.empty?).to be(true) end end end end rubocop-0.52.1/spec/rubocop/cop/style/or_assignment_spec.rb000066400000000000000000000234321322072016200240020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::OrAssignment do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } context 'when using var = var ? var : something' do it 'registers an offense with normal variables' do expect_offense(<<-RUBY.strip_indent) foo = foo ? foo : 'default' ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense with instance variables' do expect_offense(<<-RUBY.strip_indent) @foo = @foo ? @foo : 'default' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense with class variables' do expect_offense(<<-RUBY.strip_indent) @@foo = @@foo ? @@foo : 'default' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense with global variables' do expect_offense(<<-RUBY.strip_indent) $foo = $foo ? $foo : 'default' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'autocorrects normal variables to `var ||= something`' do expect(autocorrect_source('x = x ? x : 3')).to eq('x ||= 3') end it 'autocorrects instance variables to `var ||= something`' do expect(autocorrect_source('@x = @x ? @x : 3')).to eq('@x ||= 3') end it 'autocorrects class variables to `var ||= something`' do expect(autocorrect_source('@@x = @@x ? @@x : 3')).to eq('@@x ||= 3') end it 'autocorrects global variables to `var ||= something`' do expect(autocorrect_source('$x = $x ? $x : 3')).to eq('$x ||= 3') end it 'does not register an offense if any of the variables are different' do expect_no_offenses('foo = bar ? foo : 3') expect_no_offenses('foo = foo ? bar : 3') end end context 'when using var = if var; var; else; something; end' do it 'registers an offense with normal variables' do code = <<-RUBY.strip_indent foo = if foo foo else 'default' end RUBY inspect_source(code) expect(cop.highlights).to eq([code.strip]) expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense with instance variables' do code = <<-RUBY.strip_indent @foo = if @foo @foo else 'default' end RUBY inspect_source(code) expect(cop.highlights).to eq([code.strip]) expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense with class variables' do code = <<-RUBY.strip_indent @@foo = if @@foo @@foo else 'default' end RUBY inspect_source(code) expect(cop.highlights).to eq([code.strip]) expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense with global variables' do code = <<-RUBY.strip_indent $foo = if $foo $foo else 'default' end RUBY inspect_source(code) expect(cop.highlights).to eq([code.strip]) expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'autocorrects normal variables to `var ||= something`' do expect(autocorrect_source(<<-RUBY.strip_indent)).to eq("x ||= 3\n") x = if x x else 3 end RUBY end it 'autocorrects instance variables to `var ||= something`' do expect(autocorrect_source(<<-RUBY.strip_indent)).to eq("@x ||= 3\n") @x = if @x @x else 3 end RUBY end it 'autocorrects class variables to `var ||= something`' do expect(autocorrect_source(<<-RUBY.strip_indent)).to eq("@@x ||= 3\n") @@x = if @@x @@x else 3 end RUBY end it 'autocorrects global variables to `var ||= something`' do expect(autocorrect_source(<<-RUBY.strip_indent)).to eq("$x ||= 3\n") $x = if $x $x else 3 end RUBY end it 'does not register an offense if any of the variables are different' do expect_no_offenses(<<-RUBY.strip_indent) foo = if foo bar else 3 end RUBY expect_no_offenses(<<-RUBY.strip_indent) foo = if bar foo else 3 end RUBY end end context 'when using var = something unless var' do it 'registers an offense for normal variables' do expect_offense(<<-RUBY.strip_indent) foo = 'default' unless foo ^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense for instance variables' do expect_offense(<<-RUBY.strip_indent) @foo = 'default' unless @foo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense for class variables' do expect_offense(<<-RUBY.strip_indent) @@foo = 'default' unless @@foo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'registers an offense for global variables' do expect_offense(<<-RUBY.strip_indent) $foo = 'default' unless $foo ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use the double pipe equals operator `||=` instead. RUBY end it 'autocorrects normal variables to `var ||= something`' do expect(autocorrect_source('x = 3 unless x')).to eq('x ||= 3') end it 'autocorrects instance variables to `var ||= something`' do expect(autocorrect_source('@x = 3 unless @x')).to eq('@x ||= 3') end it 'autocorrects class variables to `var ||= something`' do expect(autocorrect_source('@@x = 3 unless @@x')).to eq('@@x ||= 3') end it 'autocorrects global variables to `var ||= something`' do expect(autocorrect_source('$x = 3 unless $x')).to eq('$x ||= 3') end it 'does not register an offense if any of the variables are different' do expect_no_offenses('foo = 3 unless bar') expect_no_offenses(<<-RUBY.strip_indent) unless foo bar = 3 end RUBY end end context 'when using unless var; var = something; end' do it 'registers an offense for normal variables' do inspect_source(<<-RUBY.strip_indent) foo = nil unless foo foo = 'default' end RUBY expect(cop.highlights).to eq([<<-RUBY.strip_indent.strip]) unless foo foo = 'default' end RUBY expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense for instance variables' do inspect_source(<<-RUBY.strip_indent) @foo = nil unless @foo @foo = 'default' end RUBY expect(cop.highlights).to eq([<<-RUBY.strip_indent.strip]) unless @foo @foo = 'default' end RUBY expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense for class variables' do inspect_source(<<-RUBY.strip_indent) @@foo = nil unless @@foo @@foo = 'default' end RUBY expect(cop.highlights).to eq([<<-RUBY.strip_indent.strip]) unless @@foo @@foo = 'default' end RUBY expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'registers an offense for global variables' do inspect_source(<<-RUBY.strip_indent) $foo = nil unless $foo $foo = 'default' end RUBY expect(cop.highlights).to eq([<<-RUBY.strip_indent.strip]) unless $foo $foo = 'default' end RUBY expect(cop.messages) .to eq(['Use the double pipe equals operator `||=` instead.']) end it 'autocorrects normal variables to `var ||= something`' do new_source_normal = autocorrect_source(<<-RUBY.strip_indent) foo = nil unless foo foo = 3 end RUBY expect(new_source_normal).to eq("foo = nil\nfoo ||= 3\n") end it 'autocorrects instance variables to `var ||= something`' do new_source_instance = autocorrect_source(<<-RUBY.strip_indent) @foo = nil unless @foo @foo = 3 end RUBY expect(new_source_instance).to eq("@foo = nil\n@foo ||= 3\n") end it 'autocorrects class variables to `var ||= something`' do new_source_class = autocorrect_source(<<-RUBY.strip_indent) @@foo = nil unless @@foo @@foo = 3 end RUBY expect(new_source_class).to eq("@@foo = nil\n@@foo ||= 3\n") end it 'autocorrects global variables to `var ||= something`' do new_source_global = autocorrect_source(<<-RUBY.strip_indent) $foo = nil unless $foo $foo = 3 end RUBY expect(new_source_global).to eq("$foo = nil\n$foo ||= 3\n") end it 'does not register an offense if any of the variables are different' do expect_no_offenses(<<-RUBY.strip_indent) unless foo bar = 3 end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/parallel_assignment_spec.rb000066400000000000000000000357551322072016200251710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ParallelAssignment, :config do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end shared_examples('offenses') do |source| it "registers an offense for: #{source.gsub(/\s*\n\s*/, '; ')}" do inspect_source(source) expect(cop.messages).to eq(['Do not use parallel assignment.']) end end it_behaves_like('offenses', 'a, b, c = 1, 2, 3') it_behaves_like('offenses', 'a, b, c = [1, 2, 3]') it_behaves_like('offenses', 'a, b, c = [1, 2], [3, 4], [5, 6]') it_behaves_like('offenses', 'a, b, c = {a: 1}, {b: 2}, {c: 3}') it_behaves_like('offenses', 'a, b, c = CONSTANT1, CONSTANT2, CONSTANT3') it_behaves_like('offenses', 'a, b, c = [1, 2], {a: 1}, CONSTANT3') it_behaves_like('offenses', 'a, b = foo(), bar()') it_behaves_like('offenses', 'a, b = foo { |a| puts a }, bar()') it_behaves_like('offenses', 'CONSTANT1, CONSTANT2 = CONSTANT3, CONSTANT4') it_behaves_like('offenses', 'a, b = 1, 2 if something') it_behaves_like('offenses', 'a, b = 1, 2 unless something') it_behaves_like('offenses', 'a, b = 1, 2 while something') it_behaves_like('offenses', 'a, b = 1, 2 until something') it_behaves_like('offenses', "a, b = 1, 2 rescue 'Error'") it_behaves_like('offenses', 'a, b = 1, a') it_behaves_like('offenses', 'a, b = a, b') it_behaves_like('offenses', 'a, b = foo.map { |e| e.id }, bar.map { |e| e.id }') it_behaves_like('offenses', <<-RUBY.strip_indent) array = [1, 2, 3] a, b, c, = 8, 9, array RUBY it_behaves_like('offenses', <<-RUBY.strip_indent) if true a, b = 1, 2 end RUBY it_behaves_like('offenses', 'a, b = Float::INFINITY, Float::INFINITY') it_behaves_like('offenses', 'Float::INFINITY, Float::INFINITY = 1, 2') it_behaves_like('offenses', 'a[0], a[1] = a[1], a[2]') it_behaves_like('offenses', 'obj.attr1, obj.attr2 = obj.attr3, obj.attr1') it_behaves_like('offenses', 'obj.attr1, ary[0] = ary[1], obj.attr1') it_behaves_like('offenses', 'a[0], a[1] = a[1], b[0]') shared_examples('allowed') do |source| it "allows assignment of: #{source.gsub(/\s*\n\s*/, '; ')}" do inspect_source(source) expect(cop.messages.empty?).to be(true) end end it_behaves_like('allowed', 'a = 1') it_behaves_like('allowed', 'a = a') it_behaves_like('allowed', 'a, = a') it_behaves_like('allowed', 'a, = 1') it_behaves_like('allowed', "a = *'foo'") it_behaves_like('allowed', "a, = *'foo'") it_behaves_like('allowed', 'a, = 1, 2, 3') it_behaves_like('allowed', 'a, = *foo') it_behaves_like('allowed', 'a, *b = [1, 2, 3]') it_behaves_like('allowed', '*a, b = [1, 2, 3]') it_behaves_like('allowed', 'a, b = b, a') it_behaves_like('allowed', 'a, b, c = b, c, a') it_behaves_like('allowed', 'a, b = (a + b), (a - b)') it_behaves_like('allowed', 'a, b = foo.map { |e| e.id }') it_behaves_like('allowed', 'a, b = foo()') it_behaves_like('allowed', 'a, b = *foo') it_behaves_like('allowed', 'a, b, c = 1, 2, *node') it_behaves_like('allowed', 'a, b, c = *node, 1, 2') it_behaves_like('allowed', 'begin_token, end_token = CONSTANT') it_behaves_like('allowed', 'CONSTANT, = 1, 2') it_behaves_like('allowed', <<-RUBY.strip_indent) a = 1 b = 2 RUBY it_behaves_like('allowed', <<-RUBY.strip_indent) foo = [1, 2, 3] a, b, c = foo RUBY it_behaves_like('allowed', <<-RUBY.strip_indent) array = [1, 2, 3] a, = array RUBY it_behaves_like('allowed', 'a, b = Float::INFINITY') it_behaves_like('allowed', 'a[0], a[1] = a[1], a[0]') it_behaves_like('allowed', 'obj.attr1, obj.attr2 = obj.attr2, obj.attr1') it_behaves_like('allowed', 'obj.attr1, ary[0] = ary[0], obj.attr1') it_behaves_like('allowed', 'ary[0], ary[1], ary[2] = ary[1], ary[2], ary[0]') it_behaves_like('allowed', 'self.a, self.b = self.b, self.a') it_behaves_like('allowed', 'self.a, self.b = b, a') it 'highlights the entire expression' do expect_offense(<<-RUBY.strip_indent) a, b = 1, 2 ^^^^^^^^^^^ Do not use parallel assignment. RUBY end it 'does not highlight the modifier statement' do expect_offense(<<-RUBY.strip_indent) a, b = 1, 2 if true ^^^^^^^^^^^ Do not use parallel assignment. RUBY end describe 'autocorrect' do it 'corrects when the number of left hand variables matches ' \ 'the number of right hand variables' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c = 1, 2, 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = 1 b = 2 c = 3 RUBY end it 'corrects when the right variable is an array' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c = ["1", "2", :c] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = "1" b = "2" c = :c RUBY end it 'corrects when the right variable is a word array' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c = %w(1 2 3) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = '1' b = '2' c = '3' RUBY end it 'corrects when the right variable is a symbol array' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c = %i(a b c) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = :a b = :b c = :c RUBY end it 'corrects when assigning to method returns' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = foo(), bar() RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = foo() b = bar() RUBY end it 'corrects when assigning from multiple methods with blocks' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = foo() { |c| puts c }, bar() { |d| puts d } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = foo() { |c| puts c } b = bar() { |d| puts d } RUBY end it 'corrects when using constants' do new_source = autocorrect_source(<<-RUBY.strip_indent) CONSTANT1, CONSTANT2 = CONSTANT3, CONSTANT4 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) CONSTANT1 = CONSTANT3 CONSTANT2 = CONSTANT4 RUBY end it 'corrects when the expression is missing spaces' do new_source = autocorrect_source(<<-RUBY.strip_indent) a,b,c=1,2,3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = 1 b = 2 c = 3 RUBY end it 'corrects when using single indentation' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo a, b, c = 1, 2, 3 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo a = 1 b = 2 c = 3 end RUBY end it 'corrects when using nested indentation' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo if true a, b, c = 1, 2, 3 end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo if true a = 1 b = 2 c = 3 end end RUBY end it 'corrects when the expression uses a modifier if statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 if foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if foo a = 1 b = 2 end RUBY end it 'corrects when the expression uses a modifier if statement ' \ 'inside a method' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo a, b = 1, 2 if foo end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo if foo a = 1 b = 2 end end RUBY end it 'corrects parallel assignment in if statements' do new_source = autocorrect_source(<<-RUBY.strip_indent) if foo a, b = 1, 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if foo a = 1 b = 2 end RUBY end it 'corrects when the expression uses a modifier unless statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 unless foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) unless foo a = 1 b = 2 end RUBY end it 'corrects parallel assignment in unless statements' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless foo a, b = 1, 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) unless foo a = 1 b = 2 end RUBY end it 'corrects when the expression uses a modifier while statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 while foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) while foo a = 1 b = 2 end RUBY end it 'corrects parallel assignment in while statements' do new_source = autocorrect_source(<<-RUBY.strip_indent) while foo a, b = 1, 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) while foo a = 1 b = 2 end RUBY end it 'corrects when the expression uses a modifier until statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 until foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until foo a = 1 b = 2 end RUBY end it 'corrects parallel assignment in until statements' do new_source = autocorrect_source(<<-RUBY.strip_indent) until foo a, b = 1, 2 end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) until foo a = 1 b = 2 end RUBY end it 'corrects when the expression uses a modifier rescue statement' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 rescue foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin a = 1 b = 2 rescue foo end RUBY end it 'corrects parallel assignment inside rescue statements '\ 'within method definitions' do new_source = autocorrect_source(<<-RUBY.strip_indent) def bar a, b = 1, 2 rescue 'foo' end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def bar a = 1 b = 2 rescue 'foo' end RUBY end it 'corrects parallel assignment in rescue statements '\ 'within begin ... rescue' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin a, b = 1, 2 rescue 'foo' end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin a = 1 b = 2 rescue 'foo' end RUBY end it 'corrects when the expression uses a modifier rescue statement ' \ 'as the only thing inside of a method' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo a, b = 1, 2 rescue foo end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo a = 1 b = 2 rescue foo end RUBY end it 'corrects when the expression uses a modifier rescue statement ' \ 'inside of a method' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo a, b = %w(1 2) rescue foo something_else end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo begin a = '1' b = '2' rescue foo end something_else end RUBY end it 'corrects when assignments must be reordered to avoid changing ' \ 'meaning' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c, d = 1, a + 1, b + 1, a + b + c RUBY expect(new_source).to eq(<<-RUBY.strip_indent) d = a + b + c c = b + 1 b = a + 1 a = 1 RUBY end shared_examples('no correction') do |description, source| context description do it "does not change: #{source.gsub(/\s*\n\s*/, '; ')}" do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end it_behaves_like 'no correction', 'when there are more left variables than right variables', 'a, b, c, d = 1, 2' it_behaves_like 'no correction', 'when there are more right variables than left variables', 'a, b = 1, 2, 3' it_behaves_like 'no correction', 'when expanding an assigned variable', <<-RUBY.strip_indent foo = [1, 2, 3] a, b, c = foo RUBY describe 'using custom indentation width' do let(:config) do RuboCop::Config.new('Performance/ParallelAssignment' => { 'Enabled' => true }, 'Layout/IndentationWidth' => { 'Enabled' => true, 'Width' => 3 }) end it 'works with standard correction' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b, c = 1, 2, 3 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) a = 1 b = 2 c = 3 RUBY end it 'works with guard clauses' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 if foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if foo a = 1 b = 2 end RUBY end it 'works with rescue' do new_source = autocorrect_source(<<-RUBY.strip_indent) a, b = 1, 2 rescue foo RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin a = 1 b = 2 rescue foo end RUBY end it 'works with nesting' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foo if true a, b, c = 1, 2, 3 end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foo if true a = 1 b = 2 c = 3 end end RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/parentheses_around_condition_spec.rb000066400000000000000000000104271322072016200270710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ParenthesesAroundCondition, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowSafeAssignment' => true } } it 'registers an offense for parentheses around condition' do inspect_source(<<-RUBY.strip_indent) if (x > 10) elsif (x < 3) end unless (x > 10) end while (x > 10) end until (x > 10) end x += 1 if (x < 10) x += 1 unless (x < 10) x += 1 until (x < 10) x += 1 while (x < 10) RUBY expect(cop.offenses.size).to eq(9) expect(cop.messages.first) .to eq("Don't use parentheses around the condition of an `if`.") expect(cop.messages.last) .to eq("Don't use parentheses around the condition of a `while`.") end it 'accepts parentheses if there is no space between the keyword and (.' do expect_no_offenses(<<-RUBY.strip_indent) if(x > 5) then something end do_something until(x > 5) RUBY end it 'auto-corrects parentheses around condition' do corrected = autocorrect_source(<<-RUBY.strip_indent) if (x > 10) elsif (x < 3) end unless (x > 10) end while (x > 10) end until (x > 10) end x += 1 if (x < 10) x += 1 unless (x < 10) x += 1 while (x < 10) x += 1 until (x < 10) RUBY expect(corrected).to eq <<-RUBY.strip_indent if x > 10 elsif x < 3 end unless x > 10 end while x > 10 end until x > 10 end x += 1 if x < 10 x += 1 unless x < 10 x += 1 while x < 10 x += 1 until x < 10 RUBY end it 'accepts condition without parentheses' do expect_no_offenses(<<-RUBY.strip_indent) if x > 10 end unless x > 10 end while x > 10 end until x > 10 end x += 1 if x < 10 x += 1 unless x < 10 x += 1 while x < 10 x += 1 until x < 10 RUBY end it 'accepts parentheses around condition in a ternary' do expect_no_offenses('(a == 0) ? b : a') end it 'is not confused by leading parentheses in subexpression' do expect_no_offenses('(a > b) && other ? one : two') end it 'is not confused by unbalanced parentheses' do expect_no_offenses(<<-RUBY.strip_indent) if (a + b).c() end RUBY end %w[rescue if unless while until].each do |op| it "allows parens if the condition node is a modifier #{op} op" do inspect_source(<<-RUBY.strip_indent) if (something #{op} top) end RUBY expect(cop.offenses.empty?).to be(true) end end it 'does not blow up when the condition is a ternary op' do expect_offense(<<-RUBY.strip_indent) x if (a ? b : c) ^^^^^^^^^^^ Don't use parentheses around the condition of an `if`. RUBY end it 'does not blow up for empty if condition' do expect_no_offenses(<<-RUBY.strip_indent) if () end RUBY end it 'does not blow up for empty unless condition' do expect_no_offenses(<<-RUBY.strip_indent) unless () end RUBY end context 'safe assignment is allowed' do it 'accepts variable assignment in condition surrounded with parentheses' do expect_no_offenses(<<-RUBY.strip_indent) if (test = 10) end RUBY end it 'accepts element assignment in condition surrounded with parentheses' do expect_no_offenses(<<-RUBY.strip_indent) if (test[0] = 10) end RUBY end it 'accepts setter in condition surrounded with parentheses' do expect_no_offenses(<<-RUBY.strip_indent) if (self.test = 10) end RUBY end end context 'safe assignment is not allowed' do let(:cop_config) { { 'AllowSafeAssignment' => false } } it 'does not accept variable assignment in condition surrounded with ' \ 'parentheses' do inspect_source(<<-RUBY.strip_indent) if (test = 10) end RUBY expect(cop.offenses.size).to eq(1) end it 'does not accept element assignment in condition surrounded with ' \ 'parentheses' do inspect_source(<<-RUBY.strip_indent) if (test[0] = 10) end RUBY expect(cop.offenses.size).to eq(1) end end end rubocop-0.52.1/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb000066400000000000000000000271151322072016200265310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::PercentLiteralDelimiters, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'PreferredDelimiters' => { 'default' => '[]' } } end context '`default` override' do let(:cop_config) do { 'PreferredDelimiters' => { 'default' => '[]', '%' => '()' } } end it 'allows all preferred delimiters to be set with one key' do expect_no_offenses('%w[string] + %i[string]') end it 'allows individual preferred delimiters to override `default`' do expect_no_offenses('%w[string] + [%(string)]') end end context 'invalid cop config' do let(:cop_config) { { 'PreferredDelimiters' => { 'foobar' => '()' } } } it 'raises an error when invalid configuration is specified' do expect { inspect_source('%w[string]') }.to raise_error(ArgumentError) end end context '`%` interpolated string' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%[string]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %(string) ^^^^^^^^^ `%`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%([string])') expect(cop.offenses.empty?).to be(true) end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%(#{[1].first})') expect(cop.messages.size).to eq(1) end end context '`%q` string' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%q[string]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %q(string) ^^^^^^^^^^ `%q`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%q([string])') expect(cop.offenses.empty?).to be(true) end end context '`%Q` interpolated string' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%Q[string]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %Q(string) ^^^^^^^^^^ `%Q`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%Q([string])') expect(cop.offenses.empty?).to be(true) end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%Q(#{[1].first})') expect(cop.messages.size).to eq(1) end end context '`%w` string array' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%w[some words]') end it 'does not register an offense for preferred delimiters ' \ 'with a pairing delimiters' do expect_no_offenses('%w(\(some words\))') end it 'does not register an offense for preferred delimiters ' \ 'with only a closing delimiter' do expect_no_offenses('%w(only closing delimiter charapter\))') end it 'does not register an offense for preferred delimiters ' \ 'with not a pairing delimiter' do expect_no_offenses('%w|\|not pairirng delimiter|') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %w(some words) ^^^^^^^^^^^^^^ `%w`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%w([some] [words])') expect(cop.offenses.empty?).to be(true) end end context '`%W` interpolated string array' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%W[some words]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %W(some words) ^^^^^^^^^^^^^^ `%W`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%W([some] [words])') expect(cop.offenses.empty?).to be(true) end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%W(#{[1].first})') expect(cop.messages.size).to eq(1) end end context '`%r` interpolated regular expression' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%r[regexp]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %r(regexp) ^^^^^^^^^^ `%r`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%r([regexp])') expect(cop.offenses.empty?).to be(true) end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%r(#{[1].first})') expect(cop.messages.size).to eq(1) end end context '`%i` symbol array' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%i[some symbols]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %i(some symbols) ^^^^^^^^^^^^^^^^ `%i`-literals should be delimited by `[` and `]`. RUBY end end context '`%I` interpolated symbol array' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%I[some words]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %I(some words) ^^^^^^^^^^^^^^ `%I`-literals should be delimited by `[` and `]`. RUBY end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%I(#{[1].first})') expect(cop.messages).to eq( ['`%I`-literals should be delimited by `[` and `]`.'] ) end end context '`%s` symbol' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%s[symbol]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %s(symbol) ^^^^^^^^^^ `%s`-literals should be delimited by `[` and `]`. RUBY end end context '`%x` interpolated system call' do it 'does not register an offense for preferred delimiters' do expect_no_offenses('%x[command]') end it 'registers an offense for other delimiters' do expect_offense(<<-RUBY.strip_indent) %x(command) ^^^^^^^^^^^ `%x`-literals should be delimited by `[` and `]`. RUBY end it 'does not register an offense for other delimiters ' \ 'when containing preferred delimiter characters' do inspect_source('%x([command])') expect(cop.offenses.empty?).to be(true) end it 'registers an offense for other delimiters ' \ 'when containing preferred delimiter characters in interpolation' do inspect_source('%x(#{[1].first})') expect(cop.messages.size).to eq(1) end end context 'auto-correct' do it 'fixes a string' do new_source = autocorrect_source('%(string)') expect(new_source).to eq('%[string]') end it 'fixes a string with no content' do new_source = autocorrect_source('%()') expect(new_source).to eq('%[]') end it 'fixes a string array' do new_source = autocorrect_source('%w(some words)') expect(new_source).to eq('%w[some words]') end it 'fixes a string array in a scope' do new_source = autocorrect_source(<<-RUBY.strip_indent) module Foo class Bar def baz %(one two) end end end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) module Foo class Bar def baz %[one two] end end end RUBY end it 'fixes a regular expression' do original_source = '%r(.*)' new_source = autocorrect_source(original_source) expect(new_source).to eq('%r[.*]') end it 'fixes a string with interpolation' do original_source = '%Q|#{with_interpolation}|' new_source = autocorrect_source(original_source) expect(new_source).to eq('%Q[#{with_interpolation}]') end it 'fixes a regular expression with interpolation' do original_source = '%r|#{with_interpolation}|' new_source = autocorrect_source(original_source) expect(new_source).to eq('%r[#{with_interpolation}]') end it 'fixes a regular expression with option' do original_source = '%r(.*)i' new_source = autocorrect_source(original_source) expect(new_source).to eq('%r[.*]i') end it 'preserves line breaks when fixing a multiline array' do new_source = autocorrect_source(<<-RUBY.strip_indent) %w( some words ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) %w[ some words ] RUBY end it 'preserves indentation when correcting a multiline array' do original_source = <<-RUBY.strip_margin('|') | array = %w( | first | second | ) RUBY corrected_source = <<-RUBY.strip_margin('|') | array = %w[ | first | second | ] RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(corrected_source) end it 'preserves irregular indentation when correcting a multiline array' do original_source = <<-RUBY.strip_indent array = %w( first second ) RUBY corrected_source = <<-RUBY.strip_indent array = %w[ first second ] RUBY new_source = autocorrect_source(original_source) expect(new_source).to eq(corrected_source) end shared_examples :escape_characters do |percent_literal| it "corrects #{percent_literal} with \\n in it" do new_source = autocorrect_source("#{percent_literal}{\n}") expect(new_source).to eq("#{percent_literal}[\n]") end it "corrects #{percent_literal} with \\t in it" do new_source = autocorrect_source("#{percent_literal}{\t}") expect(new_source).to eq("#{percent_literal}[\t]") end end it_behaves_like(:escape_characters, '%') it_behaves_like(:escape_characters, '%q') it_behaves_like(:escape_characters, '%Q') it_behaves_like(:escape_characters, '%s') it_behaves_like(:escape_characters, '%w') it_behaves_like(:escape_characters, '%W') it_behaves_like(:escape_characters, '%x') it_behaves_like(:escape_characters, '%r') it_behaves_like(:escape_characters, '%i') end end rubocop-0.52.1/spec/rubocop/cop/style/percent_q_literals_spec.rb000066400000000000000000000055431322072016200250140ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::PercentQLiterals, :config do subject(:cop) { described_class.new(config) } shared_examples 'accepts quote characters' do it 'accepts single quotes' do expect_no_offenses("'hi'") end it 'accepts double quotes' do expect_no_offenses('"hi"') end end shared_examples 'accepts any q string with backslash t' do context 'with special characters' do it 'accepts %q' do expect_no_offenses('%q(\t)') end it 'accepts %Q' do expect_no_offenses('%Q(\t)') end end end context 'when EnforcedStyle is lower_case_q' do let(:cop_config) { { 'EnforcedStyle' => 'lower_case_q' } } context 'without interpolation' do it 'accepts %q' do expect_no_offenses('%q(hi)') end it 'registers offense for %Q' do expect_offense(<<-RUBY.strip_indent) %Q(hi) ^^^ Do not use `%Q` unless interpolation is needed. Use `%q`. RUBY end it 'auto-corrects' do new_source = autocorrect_source('%Q(hi)') expect(new_source).to eq('%q(hi)') end include_examples 'accepts quote characters' include_examples 'accepts any q string with backslash t' end context 'with interpolation' do it 'accepts %Q' do expect_no_offenses('%Q(#{1 + 2})') end it 'accepts %q' do # This is most probably a mistake, but not this cop's responsibility. expect_no_offenses('%q(#{1 + 2})') end include_examples 'accepts quote characters' end end context 'when EnforcedStyle is upper_case_q' do let(:cop_config) { { 'EnforcedStyle' => 'upper_case_q' } } context 'without interpolation' do it 'registers offense for %q' do expect_offense(<<-RUBY.strip_indent) %q(hi) ^^^ Use `%Q` instead of `%q`. RUBY end it 'accepts %Q' do expect_no_offenses('%Q(hi)') end it 'auto-corrects' do new_source = autocorrect_source('%q[hi]') expect(new_source).to eq('%Q[hi]') end include_examples 'accepts quote characters' include_examples 'accepts any q string with backslash t' end context 'with interpolation' do it 'accepts %Q' do expect_no_offenses('%Q(#{1 + 2})') end it 'accepts %q' do # It's strange if interpolation syntax appears inside a static string, # but we can't be sure if it's a mistake or not. Changing it to %Q # would alter semantics, so we leave it as it is. expect_no_offenses('%q(#{1 + 2})') end it 'does not auto-correct' do source = '%q(#{1 + 2})' new_source = autocorrect_source(source) expect(new_source).to eq(source) end include_examples 'accepts quote characters' end end end rubocop-0.52.1/spec/rubocop/cop/style/perl_backrefs_spec.rb000066400000000000000000000011361322072016200237310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::PerlBackrefs do subject(:cop) { described_class.new } it 'registers an offense for $1' do expect_offense(<<-RUBY.strip_indent) puts $1 ^^ Avoid the use of Perl-style backrefs. RUBY end it 'auto-corrects $1 to Regexp.last_match(1)' do new_source = autocorrect_source('$1') expect(new_source).to eq('Regexp.last_match(1)') end it 'auto-corrects #$1 to #{Regexp.last_match(1)}' do new_source = autocorrect_source('"#$1"') expect(new_source).to eq('"#{Regexp.last_match(1)}"') end end rubocop-0.52.1/spec/rubocop/cop/style/preferred_hash_methods_spec.rb000066400000000000000000000042641322072016200256400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::PreferredHashMethods, :config do subject(:cop) { described_class.new(config) } context 'with enforced `short` style' do let(:cop_config) { { 'EnforcedStyle' => 'short' } } it 'registers an offense for has_key? with one arg' do expect_offense(<<-RUBY.strip_indent) o.has_key?(o) ^^^^^^^^ Use `Hash#key?` instead of `Hash#has_key?`. RUBY end it 'accepts has_key? with no args' do expect_no_offenses('o.has_key?') end it 'registers an offense for has_value? with one arg' do expect_offense(<<-RUBY.strip_indent) o.has_value?(o) ^^^^^^^^^^ Use `Hash#value?` instead of `Hash#has_value?`. RUBY end it 'accepts has_value? with no args' do expect_no_offenses('o.has_value?') end it 'auto-corrects has_key? with key?' do new_source = autocorrect_source('hash.has_key?(:test)') expect(new_source).to eq('hash.key?(:test)') end it 'auto-corrects has_value? with value?' do new_source = autocorrect_source('hash.has_value?(value)') expect(new_source).to eq('hash.value?(value)') end end context 'with enforced `verbose` style' do let(:cop_config) { { 'EnforcedStyle' => 'verbose' } } it 'registers an offense for key? with one arg' do expect_offense(<<-RUBY.strip_indent) o.key?(o) ^^^^ Use `Hash#has_key?` instead of `Hash#key?`. RUBY end it 'accepts key? with no args' do expect_no_offenses('o.key?') end it 'registers an offense for value? with one arg' do expect_offense(<<-RUBY.strip_indent) o.value?(o) ^^^^^^ Use `Hash#has_value?` instead of `Hash#value?`. RUBY end it 'accepts value? with no args' do expect_no_offenses('o.value?') end it 'auto-corrects key? with has_key?' do new_source = autocorrect_source('hash.key?(:test)') expect(new_source).to eq('hash.has_key?(:test)') end it 'auto-corrects value? with has_value?' do new_source = autocorrect_source('hash.value?(value)') expect(new_source).to eq('hash.has_value?(value)') end end end rubocop-0.52.1/spec/rubocop/cop/style/proc_spec.rb000066400000000000000000000012161322072016200220710ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Proc do subject(:cop) { described_class.new } it 'registers an offense for a Proc.new call' do expect_offense(<<-RUBY.strip_indent) f = Proc.new { |x| puts x } ^^^^^^^^ Use `proc` instead of `Proc.new`. RUBY end it 'accepts the proc method' do expect_no_offenses('f = proc { |x| puts x }') end it 'accepts the Proc.new call outside of block' do expect_no_offenses('p = Proc.new') end it 'auto-corrects Proc.new to proc' do corrected = autocorrect_source(['Proc.new { test }']) expect(corrected).to eq 'proc { test }' end end rubocop-0.52.1/spec/rubocop/cop/style/raise_args_spec.rb000066400000000000000000000121551322072016200232510ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RaiseArgs, :config do subject(:cop) { described_class.new(config) } context 'when enforced style is compact' do let(:cop_config) { { 'EnforcedStyle' => 'compact' } } context 'with a raise with 2 args' do it 'reports an offense' do inspect_source('raise RuntimeError, msg') expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'exploded') end it 'auto-corrects to compact style' do new_source = autocorrect_source('raise RuntimeError, msg') expect(new_source).to eq('raise RuntimeError.new(msg)') end end context 'with correct + opposite' do it 'reports an offense' do inspect_source(<<-RUBY.strip_indent) if a raise RuntimeError, msg else raise Ex.new(msg) end RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Provide an exception object as an argument to `raise`.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects to compact style' do new_source = autocorrect_source(<<-RUBY.strip_indent) if a raise RuntimeError, msg else raise Ex.new(msg) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if a raise RuntimeError.new(msg) else raise Ex.new(msg) end RUBY end end context 'with a raise with 3 args' do it 'reports an offense' do expect_offense(<<-RUBY.strip_indent) raise RuntimeError, msg, caller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Provide an exception object as an argument to `raise`. RUBY end it 'does not auto-correct to compact style' do initial_source = 'raise RuntimeError, msg, caller' new_source = autocorrect_source([initial_source]) expect(new_source).to eq(initial_source) end end it 'accepts a raise with msg argument' do expect_no_offenses('raise msg') end it 'accepts a raise with an exception argument' do expect_no_offenses('raise Ex.new(msg)') end end context 'when enforced style is exploded' do let(:cop_config) { { 'EnforcedStyle' => 'exploded' } } context 'with a raise with exception object' do context 'with one argument' do it 'reports an offense' do inspect_source('raise Ex.new(msg)') expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Provide an exception class and message ' \ 'as arguments to `raise`.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'compact') end it 'auto-corrects to exploded style' do new_source = autocorrect_source(['raise Ex.new(msg)']) expect(new_source).to eq('raise Ex, msg') end end context 'with no arguments' do it 'reports an offense' do inspect_source('raise Ex.new') expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Provide an exception class and message ' \ 'as arguments to `raise`.']) expect(cop.config_to_allow_offenses) .to eq('EnforcedStyle' => 'compact') end it 'auto-corrects to exploded style' do new_source = autocorrect_source(['raise Ex.new']) expect(new_source).to eq('raise Ex') end end end context 'with opposite + correct' do it 'reports an offense for opposite + correct' do inspect_source(<<-RUBY.strip_indent) if a raise RuntimeError, msg else raise Ex.new(msg) end RUBY expect(cop.offenses.size).to eq(1) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'auto-corrects to exploded style' do new_source = autocorrect_source(<<-RUBY.strip_indent) if a raise RuntimeError, msg else raise Ex.new(msg) end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) if a raise RuntimeError, msg else raise Ex, msg end RUBY end end it 'accepts exception constructor with more than 1 argument' do expect_no_offenses('raise MyCustomError.new(a1, a2, a3)') end it 'accepts exception constructor with keyword arguments' do expect_no_offenses('raise MyKwArgError.new(a: 1, b: 2)') end it 'accepts a raise with splatted arguments' do expect_no_offenses('raise MyCustomError.new(*args)') end it 'accepts a raise with 3 args' do expect_no_offenses('raise RuntimeError, msg, caller') end it 'accepts a raise with 2 args' do expect_no_offenses('raise RuntimeError, msg') end it 'accepts a raise with msg argument' do expect_no_offenses('raise msg') end end end rubocop-0.52.1/spec/rubocop/cop/style/random_with_offset_spec.rb000066400000000000000000000125731322072016200250170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RandomWithOffset do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using rand(int) + offset' do expect_offense(<<-RUBY.strip_indent) rand(6) + 1 ^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using offset + rand(int)' do expect_offense(<<-RUBY.strip_indent) 1 + rand(6) ^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(int).succ' do expect_offense(<<-RUBY.strip_indent) rand(6).succ ^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(int) - offset' do expect_offense(<<-RUBY.strip_indent) rand(6) - 1 ^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using offset - rand(int)' do expect_offense(<<-RUBY.strip_indent) 1 - rand(6) ^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(int).pred' do expect_offense(<<-RUBY.strip_indent) rand(6).pred ^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(int).next' do expect_offense(<<-RUBY.strip_indent) rand(6).next ^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using Kernel.rand' do expect_offense(<<-RUBY.strip_indent) Kernel.rand(6) + 1 ^^^^^^^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using Random.rand' do expect_offense(<<-RUBY.strip_indent) Random.rand(6) + 1 ^^^^^^^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(irange) + offset' do expect_offense(<<-RUBY.strip_indent) rand(0..6) + 1 ^^^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'registers an offense when using rand(erange) + offset' do expect_offense(<<-RUBY.strip_indent) rand(0...6) + 1 ^^^^^^^^^^^^^^^ Prefer ranges when generating random numbers instead of integers with offsets. RUBY end it 'autocorrects rand(int) + offset' do new_source = autocorrect_source('rand(6) + 1') expect(new_source).to eq 'rand(1..6)' end it 'autocorrects offset + rand(int)' do new_source = autocorrect_source('1 + rand(6)') expect(new_source).to eq 'rand(1..6)' end it 'autocorrects rand(int) - offset' do new_source = autocorrect_source('rand(6) - 1') expect(new_source).to eq 'rand(-1..4)' end it 'autocorrects offset - rand(int)' do new_source = autocorrect_source('1 - rand(6)') expect(new_source).to eq 'rand(-4..1)' end it 'autocorrects rand(int).succ' do new_source = autocorrect_source('rand(6).succ') expect(new_source).to eq 'rand(1..6)' end it 'autocorrects rand(int).pred' do new_source = autocorrect_source('rand(6).pred') expect(new_source).to eq 'rand(-1..4)' end it 'autocorrects rand(int).next' do new_source = autocorrect_source('rand(6).next') expect(new_source).to eq 'rand(1..6)' end it 'autocorrects the use of Random.rand' do new_source = autocorrect_source('Random.rand(6) + 1') expect(new_source).to eq 'Random.rand(1..6)' end it 'autocorrects the use of Kernel.rand' do new_source = autocorrect_source('Kernel.rand(6) + 1') expect(new_source).to eq 'Kernel.rand(1..6)' end it 'autocorrects rand(irange) + offset' do new_source = autocorrect_source('rand(0..6) + 1') expect(new_source).to eq 'rand(1..7)' end it 'autocorrects rand(3range) + offset' do new_source = autocorrect_source('rand(0...6) + 1') expect(new_source).to eq 'rand(1..6)' end it 'autocorrects rand(irange) - offset' do new_source = autocorrect_source('rand(0..6) - 1') expect(new_source).to eq 'rand(-1..5)' end it 'autocorrects rand(erange) - offset' do new_source = autocorrect_source('rand(0...6) - 1') expect(new_source).to eq 'rand(-1..4)' end it 'autocorrects offset - rand(irange)' do new_source = autocorrect_source('1 - rand(0..6)') expect(new_source).to eq 'rand(-5..1)' end it 'autocorrects offset - rand(erange)' do new_source = autocorrect_source('1 - rand(0...6)') expect(new_source).to eq 'rand(-4..1)' end it 'autocorrects rand(irange).succ' do new_source = autocorrect_source('rand(0..6).succ') expect(new_source).to eq 'rand(1..7)' end it 'autocorrects rand(erange).succ' do new_source = autocorrect_source('rand(0...6).succ') expect(new_source).to eq 'rand(1..6)' end it 'does not register an offense when using range with double dots' do expect_no_offenses('rand(1..6)') end it 'does not register an offense when using range with triple dots' do expect_no_offenses('rand(1...6)') end end rubocop-0.52.1/spec/rubocop/cop/style/redundant_begin_spec.rb000066400000000000000000000116641322072016200242660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantBegin, :config do subject(:cop) { described_class.new(config) } it 'reports an offense for single line def with redundant begin block' do src = ' def func; begin; x; y; rescue; z end end' inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for def with redundant begin block' do src = <<-RUBY.strip_indent def func begin ala rescue => e bala end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs with redundant begin block' do src = <<-RUBY.strip_indent def Test.func begin ala rescue => e bala end end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts a def with required begin block' do expect_no_offenses(<<-RUBY.strip_indent) def func begin ala rescue => e bala end something end RUBY end it 'accepts a defs with required begin block' do expect_no_offenses(<<-RUBY.strip_indent) def Test.func begin ala rescue => e bala end something end RUBY end it 'accepts a def with a begin block after a statement' do expect_no_offenses(<<-RUBY.strip_indent) def Test.func something begin ala rescue => e bala end end RUBY end it 'auto-corrects source separated by newlines ' \ 'by removing redundant begin blocks' do src = <<-RUBY.strip_margin('|') | def func | begin | foo | bar | rescue | baz | end | end RUBY result_src = [' def func', ' ', ' foo', ' bar', ' rescue', ' baz', ' ', ' end', ''].join("\n") new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end it 'auto-corrects source separated by semicolons ' \ 'by removing redundant begin blocks' do src = ' def func; begin; x; y; rescue; z end end' result_src = ' def func; ; x; y; rescue; z end' new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end it "doesn't modify spacing when auto-correcting" do src = <<-RUBY.strip_indent def method begin BlockA do |strategy| foo end BlockB do |portfolio| foo end rescue => e # some problem bar end end RUBY result_src = ['def method', ' ', ' BlockA do |strategy|', ' foo', ' end', '', ' BlockB do |portfolio|', ' foo', ' end', '', ' rescue => e # some problem', ' bar', ' ', 'end', ''].join("\n") new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end it 'auto-corrects when there are trailing comments' do src = <<-RUBY.strip_indent def method begin # comment 1 do_some_stuff rescue # comment 2 end # comment 3 end RUBY result_src = <<-RUBY.strip_indent def method # comment 1 do_some_stuff rescue # comment 2 # comment 3 end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end context '< Ruby 2.5', :ruby24 do it 'accepts a do-end block with a begin-end' do expect_no_offenses(<<-RUBY.strip_indent) do_something do begin foo rescue => e bar end end RUBY end end context '>= ruby 2.5', :ruby25 do it 'registers an offense for a do-end block with redundant begin-end' do expect_offense(<<-RUBY.strip_indent) do_something do begin ^^^^^ Redundant `begin` block detected. foo rescue => e bar end end RUBY end it 'accepts a {} block with a begin-end' do expect_no_offenses(<<-RUBY.strip_indent) do_something { begin foo rescue => e bar end } RUBY end it 'accepts a block with a begin block after a statement' do expect_no_offenses(<<-RUBY.strip_indent) do_something do something begin ala rescue => e bala end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/redundant_conditional_spec.rb000066400000000000000000000070611322072016200255010ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantConditional do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } before { inspect_source(source) } shared_examples 'code with offense' do |code, expected, message_expression| context "when checking #{code.inspect}" do let(:source) { code } it 'registers an offense' do expected_message = 'This conditional expression '\ "can just be replaced by `#{message_expression || expected}`." expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([expected_message]) end it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end it 'claims to auto-correct' do autocorrect_source(code) expect(cop.offenses.last.status).to eq(:corrected) end end end shared_examples 'code without offense' do |code| let(:source) { code } context "when checking #{code.inspect}" do it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end end it_behaves_like 'code with offense', 'x == y ? true : false', 'x == y' it_behaves_like 'code with offense', 'x == y ? false : true', '!(x == y)' it_behaves_like 'code without offense', 'x == y ? 1 : 10' it_behaves_like 'code with offense', <<-RUBY.strip_indent, if x == y true else false end RUBY "x == y\n", 'x == y' it_behaves_like 'code with offense', <<-RUBY.strip_indent, if x == y false else true end RUBY "!(x == y)\n", '!(x == y)' it_behaves_like 'code with offense', <<-RUBY.strip_indent, if cond false elsif x == y true else false end RUBY <<-RUBY.strip_indent, if cond false else x == y end RUBY "\nelse\n x == y" it_behaves_like 'code with offense', <<-RUBY.strip_indent, if cond false elsif x == y false else true end RUBY <<-RUBY.strip_indent, if cond false else !(x == y) end RUBY "\nelse\n !(x == y)" it_behaves_like 'code without offense', <<-RUBY.strip_indent if x == y 1 else 2 end RUBY it_behaves_like 'code without offense', <<-RUBY.strip_indent if cond 1 elseif x == y 2 else 3 end RUBY end rubocop-0.52.1/spec/rubocop/cop/style/redundant_exception_spec.rb000066400000000000000000000044171322072016200251760ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantException do subject(:cop) { described_class.new } shared_examples 'common behavior' do |keyword| it "reports an offense for a #{keyword} with RuntimeError" do src = "#{keyword} RuntimeError, msg" inspect_source(src) expect(cop.highlights).to eq([src]) expect(cop.messages) .to eq(['Redundant `RuntimeError` argument can be removed.']) end it "reports an offense for a #{keyword} with RuntimeError.new" do src = "#{keyword} RuntimeError.new(msg)" inspect_source(src) expect(cop.highlights).to eq([src]) expect(cop.messages) .to eq(['Redundant `RuntimeError.new` call can be replaced with ' \ 'just the message.']) end it "accepts a #{keyword} with RuntimeError if it does not have 2 args" do inspect_source("#{keyword} RuntimeError, msg, caller") expect(cop.offenses.empty?).to be(true) end it "auto-corrects a #{keyword} RuntimeError by removing RuntimeError" do src = "#{keyword} RuntimeError, msg" result_src = "#{keyword} msg" new_src = autocorrect_source(src) expect(new_src).to eq(result_src) end it "auto-corrects a #{keyword} RuntimeError.new with parentheses by " \ 'removing RuntimeError.new' do src = "#{keyword} RuntimeError.new(msg)" result_src = "#{keyword} msg" new_src = autocorrect_source(src) expect(new_src).to eq(result_src) end it "auto-corrects a #{keyword} RuntimeError.new without parentheses by " \ 'removing RuntimeError.new' do src = "#{keyword} RuntimeError.new msg" result_src = "#{keyword} msg" new_src = autocorrect_source(src) expect(new_src).to eq(result_src) end it "does not modify #{keyword} w/ RuntimeError if it does not have 2 " \ 'args' do src = "#{keyword} runtimeError, msg, caller" new_src = autocorrect_source(src) expect(new_src).to eq(src) end it 'does not modify rescue w/ non redundant error' do src = "#{keyword} OtherError, msg" new_src = autocorrect_source(src) expect(new_src).to eq(src) end end include_examples 'common behavior', 'raise' include_examples 'common behavior', 'fail' end rubocop-0.52.1/spec/rubocop/cop/style/redundant_freeze_spec.rb000066400000000000000000000053411322072016200244550ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantFreeze do subject(:cop) { described_class.new } let(:prefix) { nil } shared_examples :immutable_objects do |o| it "registers an offense for frozen #{o}" do source = [prefix, "CONST = #{o}.freeze"].compact.join("\n") inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects by removing .freeze' do source = [prefix, "CONST = #{o}.freeze"].compact.join("\n") new_source = autocorrect_source(source) expect(new_source).to eq(source.chomp('.freeze')) end end it_behaves_like :immutable_objects, '1' it_behaves_like :immutable_objects, '1.5' it_behaves_like :immutable_objects, ':sym' it_behaves_like :immutable_objects, ':""' it_behaves_like :immutable_objects, '/./' it_behaves_like :immutable_objects, '1..5' shared_examples :mutable_objects do |o| it "allows #{o} with freeze" do source = [prefix, "CONST = #{o}.freeze"].compact.join("\n") inspect_source(source) expect(cop.offenses.empty?).to be(true) end end it_behaves_like :mutable_objects, '[1, 2, 3]' it_behaves_like :mutable_objects, '{ a: 1, b: 2 }' it_behaves_like :mutable_objects, "'str'" it_behaves_like :mutable_objects, '"top#{1 + 2}"' it 'allows .freeze on method call' do expect_no_offenses('TOP_TEST = Something.new.freeze') end context 'when the receiver is a frozen string literal' do if RuboCop::Config::KNOWN_RUBIES.include?(3.0) context 'when the target ruby version >= 3.0' do let(:ruby_version) { 3.0 } context 'when the frozen string literal comment is missing' do it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is true' do let(:prefix) { '# frozen_string_literal: true' } it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is false' do let(:prefix) { '# frozen_string_literal: false' } it_behaves_like :immutable_objects, '"#{a}"' end end end context 'when the target ruby version >= 2.3' do let(:ruby_version) { 2.3 } context 'when the frozen string literal comment is missing' do it_behaves_like :mutable_objects, '"#{a}"' end context 'when the frozen string literal comment is true' do let(:prefix) { '# frozen_string_literal: true' } it_behaves_like :immutable_objects, '"#{a}"' end context 'when the frozen string literal comment is false' do let(:prefix) { '# frozen_string_literal: false' } it_behaves_like :mutable_objects, '"#{a}"' end end end end rubocop-0.52.1/spec/rubocop/cop/style/redundant_parentheses_spec.rb000066400000000000000000000215561322072016200255240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantParentheses do subject(:cop) { described_class.new } shared_examples 'redundant' do |expr, correct, type, highlight = nil| it "registers an offense for parentheses around #{type}" do inspect_source(expr) expect(cop.messages) .to eq(["Don't use parentheses around #{type}."]) expect(cop.highlights).to eq([highlight || expr]) end it 'auto-corrects' do expect(autocorrect_source(expr)).to eq correct end end shared_examples 'plausible' do |expr| it 'accepts parentheses when arguments are unparenthesized' do inspect_source(expr) expect(cop.offenses.empty?).to be(true) end end shared_examples 'keyword with return value' do |keyword| it_behaves_like 'redundant', "(#{keyword})", keyword, 'a keyword' it_behaves_like 'redundant', "(#{keyword}())", "#{keyword}()", 'a keyword' it_behaves_like 'redundant', "(#{keyword}(1))", "#{keyword}(1)", 'a keyword' it_behaves_like 'plausible', "(#{keyword} 1, 2)" end shared_examples 'keyword with arguments' do |keyword| it_behaves_like 'redundant', "(#{keyword})", keyword, 'a keyword' it_behaves_like 'redundant', "(#{keyword}())", "#{keyword}()", 'a keyword' it_behaves_like 'redundant', "(#{keyword}(1, 2))", "#{keyword}(1, 2)", 'a keyword' it_behaves_like 'plausible', "(#{keyword} 1, 2)" end it_behaves_like 'redundant', '("x")', '"x"', 'a literal' it_behaves_like 'redundant', '("#{x}")', '"#{x}"', 'a literal' it_behaves_like 'redundant', '(:x)', ':x', 'a literal' it_behaves_like 'redundant', '(:"#{x}")', ':"#{x}"', 'a literal' it_behaves_like 'redundant', '(1)', '1', 'a literal' it_behaves_like 'redundant', '(1.2)', '1.2', 'a literal' it_behaves_like 'redundant', '({})', '{}', 'a literal' it_behaves_like 'redundant', '([])', '[]', 'a literal' it_behaves_like 'redundant', '(nil)', 'nil', 'a literal' it_behaves_like 'redundant', '(true)', 'true', 'a literal' it_behaves_like 'redundant', '(false)', 'false', 'a literal' it_behaves_like 'redundant', '(/regexp/)', '/regexp/', 'a literal' it_behaves_like 'redundant', '("x"; "y")', '"x"; "y"', 'a literal' it_behaves_like 'redundant', '(1; 2)', '1; 2', 'a literal' it_behaves_like 'redundant', '(1i)', '1i', 'a literal' it_behaves_like 'redundant', '(1r)', '1r', 'a literal' it_behaves_like 'redundant', '(__FILE__)', '__FILE__', 'a keyword' it_behaves_like 'redundant', '(__LINE__)', '__LINE__', 'a keyword' it_behaves_like 'redundant', '(__ENCODING__)', '__ENCODING__', 'a keyword' it_behaves_like 'redundant', '(redo)', 'redo', 'a keyword' it_behaves_like 'redundant', '(retry)', 'retry', 'a keyword' it_behaves_like 'redundant', '(self)', 'self', 'a keyword' it_behaves_like 'redundant', '(X) ? Y : N', 'X ? Y : N', 'a constant', '(X)' it_behaves_like 'redundant', '(X)? Y : N', 'X ? Y : N', 'a constant', '(X)' it_behaves_like 'keyword with return value', 'break' it_behaves_like 'keyword with return value', 'next' it_behaves_like 'keyword with return value', 'return' it_behaves_like 'keyword with arguments', 'super' it_behaves_like 'keyword with arguments', 'yield' it_behaves_like 'redundant', '(defined?(:A))', 'defined?(:A)', 'a keyword' it_behaves_like 'plausible', '(defined? :A)' it_behaves_like 'plausible', '(alias a b)' it_behaves_like 'plausible', '(not 1)' it_behaves_like 'plausible', '(a until b)' it_behaves_like 'plausible', '(a while b)' it_behaves_like 'redundant', 'x = 1; (x)', 'x = 1; x', 'a variable', '(x)' it_behaves_like 'redundant', '(@x)', '@x', 'a variable' it_behaves_like 'redundant', '(@@x)', '@@x', 'a variable' it_behaves_like 'redundant', '($x)', '$x', 'a variable' it_behaves_like 'redundant', '(X)', 'X', 'a constant' it_behaves_like 'redundant', '(x)', 'x', 'a method call' it_behaves_like 'redundant', '(x(1, 2))', 'x(1, 2)', 'a method call' it_behaves_like 'redundant', '("x".to_sym)', '"x".to_sym', 'a method call' it_behaves_like 'redundant', '(x[:y])', 'x[:y]', 'a method call' it_behaves_like 'redundant', '("foo"[0])', '"foo"[0]', 'a method call' it_behaves_like 'redundant', '(["foo"][0])', '["foo"][0]', 'a method call' it_behaves_like 'redundant', '({0 => :a}[0])', '{0 => :a}[0]', 'a method call' it_behaves_like 'redundant', '(x; y)', 'x; y', 'a method call' it_behaves_like 'redundant', '(!x)', '!x', 'an unary operation' it_behaves_like 'redundant', '(~x)', '~x', 'an unary operation' it_behaves_like 'redundant', '(-x)', '-x', 'an unary operation' it_behaves_like 'redundant', '(+x)', '+x', 'an unary operation' it_behaves_like 'plausible', '(!x.m arg)' it_behaves_like 'plausible', '(!x).y' it_behaves_like 'plausible', '-(1.foo)' it_behaves_like 'plausible', '+(1.foo)' it_behaves_like 'plausible', '-(1.foo.bar)' it_behaves_like 'plausible', '+(1.foo.bar)' it_behaves_like 'plausible', '()' it_behaves_like 'redundant', '[(1)]', '[1]', 'a literal', '(1)' it_behaves_like 'redundant', "[(1\n)]", "[1\n]", 'a literal', "(1\n)" it_behaves_like 'plausible', "[(1\n),]" it_behaves_like 'redundant', '{a: (1)}', '{a: 1}', 'a literal', '(1)' it_behaves_like 'redundant', "{a: (1\n)}", "{a: 1\n}", 'a literal', "(1\n)" it_behaves_like 'plausible', "{a: (1\n),}" it_behaves_like 'redundant', '(0)**2', '0**2', 'a literal', '(0)' it_behaves_like 'redundant', '(2)**2', '2**2', 'a literal', '(2)' it_behaves_like 'redundant', '(2.1)**2', '2.1**2', 'a literal', '(2.1)' it_behaves_like 'redundant', '2**(-2)', '2**-2', 'a literal', '(-2)' it_behaves_like 'redundant', '2**(2)', '2**2', 'a literal', '(2)' it_behaves_like 'plausible', '(-2)**2' it_behaves_like 'plausible', '(-2.1)**2' it_behaves_like 'plausible', 'x = (foo; bar)' it_behaves_like 'plausible', 'x += (foo; bar)' it_behaves_like 'plausible', 'x + (foo; bar)' it_behaves_like 'plausible', 'x((foo; bar))' it_behaves_like 'redundant', <<-RUBY, <<-RUBY2, 'a method call', '(foo; bar)' def x (foo; bar) end RUBY def x foo; bar end RUBY2 it_behaves_like 'redundant', <<-RUBY, <<-RUBY2, 'a method call', '(foo; bar)' def x baz (foo; bar) end RUBY def x baz foo; bar end RUBY2 it_behaves_like 'redundant', <<-RUBY, <<-RUBY2, 'a method call', '(foo; bar)' x do (foo; bar) end RUBY x do foo; bar end RUBY2 it_behaves_like 'redundant', <<-RUBY, <<-RUBY2, 'a method call', '(foo; bar)' x do baz (foo; bar) end RUBY x do baz foo; bar end RUBY2 it 'accepts parentheses around a method call with unparenthesized ' \ 'arguments' do inspect_source('(a 1, 2) && (1 + 1)') expect(cop.offenses.empty?).to be(true) end it 'accepts parentheses inside an irange' do expect_no_offenses('(a)..(b)') end it 'accepts parentheses inside an erange' do expect_no_offenses('(a)...(b)') end it 'accepts parentheses around an irange' do expect_no_offenses('(a..b)') end it 'accepts parentheses around an erange' do expect_no_offenses('(a...b)') end it 'accepts parentheses around operator keywords' do expect_no_offenses('(1 and 2) and (3 or 4)') end it 'registers an offense when there is space around the parentheses' do expect_offense(<<-RUBY.strip_indent) if x; y else (1) end ^^^ Don't use parentheses around a literal. RUBY end it 'accepts parentheses when they touch the preceding keyword' do expect_no_offenses('if x; y else(1) end') end it 'accepts parentheses when they touch the following keyword' do expect_no_offenses('if x; y else (1)end') end context 'when a hash literal is the first argument in a method call' do it 'accepts parentheses if the argument list is not parenthesized ' do expect_no_offenses('x ({ y: 1 }), z') end it 'registers an offense if the argument list is parenthesized ' do expect_offense(<<-RUBY.strip_indent) x(({ y: 1 }), z) ^^^^^^^^^^ Don't use parentheses around a literal. RUBY end end context 'when a hash literal is the second argument in a method call' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) x ({ y: 1 }), ({ y: 1 }) ^^^^^^^^^^ Don't use parentheses around a literal. RUBY end end context 'when a non-parenthesized call has an arg and a block' do it 'accepts parens around the arg' do expect_no_offenses('method (:arg) { blah }') end end it 'accepts parentheses around the error passed to rescue' do expect_no_offenses(<<-RUBY.strip_indent) begin some_method rescue(StandardError) end RUBY end it 'accepts parentheses around a constant passed to when' do expect_no_offenses(<<-RUBY.strip_indent) case foo when(Const) bar end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/redundant_return_spec.rb000066400000000000000000000210611322072016200245110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantReturn, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowMultipleReturnValues' => false } } it 'reports an offense for def with only a return' do src = <<-RUBY.strip_indent def func return something end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs with only a return' do src = <<-RUBY.strip_indent def Test.func return something end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for def ending with return' do src = <<-RUBY.strip_indent def func one two return something end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs ending with return' do src = <<-RUBY.strip_indent def self.func one two return something end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'accepts return in a non-final position' do expect_no_offenses(<<-RUBY.strip_indent) def func return something if something_else end RUBY end it 'does not blow up on empty method body' do expect_no_offenses(<<-RUBY.strip_indent) def func end RUBY end it 'does not blow up on empty if body' do expect_no_offenses(<<-RUBY.strip_indent) def func if x elsif y else end end RUBY end it 'auto-corrects by removing redundant returns' do src = <<-RUBY.strip_indent def func one two return something end RUBY result_src = <<-RUBY.strip_indent def func one two something end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end context 'when return has no arguments' do shared_examples 'common behavior' do |ret| let(:src) do <<-RUBY.strip_indent def func one two #{ret} # comment end RUBY end it "registers an offense for #{ret}" do inspect_source(src) expect(cop.offenses.size).to eq(1) end it "auto-corrects by replacing #{ret} with nil" do new_source = autocorrect_source(src) expect(new_source).to eq(<<-RUBY.strip_indent) def func one two nil # comment end RUBY end end it_behaves_like 'common behavior', 'return' it_behaves_like 'common behavior', 'return()' end context 'when multi-value returns are not allowed' do it 'reports an offense for def with only a return' do src = <<-RUBY.strip_indent def func return something, test end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs with only a return' do src = <<-RUBY.strip_indent def Test.func return something, test end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for def ending with return' do src = <<-RUBY.strip_indent def func one two return something, test end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'reports an offense for defs ending with return' do src = <<-RUBY.strip_indent def self.func one two return something, test end RUBY inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'registers a helpful message for defs with multiple returns' do expect_offense(<<-RUBY.strip_indent) def func return something, test ^^^^^^ Redundant `return` detected. To return multiple values, use an array. end RUBY end it 'auto-corrects by making implicit arrays explicit' do src = <<-RUBY.strip_indent def func return 1, 2 end RUBY # Just 1, 2 is not valid Ruby. result_src = <<-RUBY.strip_indent def func [1, 2] end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end it 'auto-corrects removes return when using an explicit hash' do src = <<-RUBY.strip_indent def func return {:a => 1, :b => 2} end RUBY # :a => 1, :b => 2 is not valid Ruby result_src = <<-RUBY.strip_indent def func {:a => 1, :b => 2} end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end it 'auto-corrects by making an implicit hash explicit' do src = <<-RUBY.strip_indent def func return :a => 1, :b => 2 end RUBY # :a => 1, :b => 2 is not valid Ruby result_src = <<-RUBY.strip_indent def func {:a => 1, :b => 2} end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(result_src) end end context 'when multi-value returns are allowed' do let(:cop_config) { { 'AllowMultipleReturnValues' => true } } it 'accepts def with only a return' do expect_no_offenses(<<-RUBY.strip_indent) def func return something, test end RUBY end it 'accepts defs with only a return' do expect_no_offenses(<<-RUBY.strip_indent) def Test.func return something, test end RUBY end it 'accepts def ending with return' do expect_no_offenses(<<-RUBY.strip_indent) def func one two return something, test end RUBY end it 'accepts defs ending with return' do expect_no_offenses(<<-RUBY.strip_indent) def self.func one two return something, test end RUBY end it 'does not auto-correct' do src = <<-RUBY.strip_indent def func return 1, 2 end RUBY new_source = autocorrect_source(src) expect(new_source).to eq(src) end end context 'when return is inside an if-branch' do let(:src) do <<-RUBY.strip_indent def func if x return 1 elsif y return 2 else return 3 end end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def func if x return 1 ^^^^^^ Redundant `return` detected. elsif y return 2 ^^^^^^ Redundant `return` detected. else return 3 ^^^^^^ Redundant `return` detected. end end RUBY end it 'auto-corrects' do corrected = autocorrect_source(src) expect(corrected).to eq <<-RUBY.strip_indent def func if x 1 elsif y 2 else 3 end end RUBY end end context 'when return is inside a when-branch' do let(:src) do <<-RUBY.strip_indent def func case x when y then return 1 when z then return 2 when q else return 3 end end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def func case x when y then return 1 ^^^^^^ Redundant `return` detected. when z then return 2 ^^^^^^ Redundant `return` detected. when q else return 3 ^^^^^^ Redundant `return` detected. end end RUBY end it 'auto-corrects' do corrected = autocorrect_source(src) expect(corrected).to eq <<-RUBY.strip_indent def func case x when y then 1 when z then 2 when q else 3 end end RUBY end end context 'when case nodes are empty' do it 'accepts empty when nodes' do expect_no_offenses(<<-RUBY.strip_indent) def func case x when y then 1 when z # do nothing else 3 end end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/redundant_self_spec.rb000066400000000000000000000126031322072016200241250ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RedundantSelf do subject(:cop) { described_class.new } it 'reports an offense a self receiver on an rvalue' do src = 'a = self.b' inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'does not report an offense when receiver and lvalue have the same name' do expect_no_offenses('a = self.a') end it 'accepts a self receiver on an lvalue of an assignment' do expect_no_offenses('self.a = b') end it 'accepts a self receiver on an lvalue of a parallel assignment' do expect_no_offenses('a, self.b = c, d') end it 'accepts a self receiver on an lvalue of an or-assignment' do expect_no_offenses('self.logger ||= Rails.logger') end it 'accepts a self receiver on an lvalue of an and-assignment' do expect_no_offenses('self.flag &&= value') end it 'accepts a self receiver on an lvalue of a plus-assignment' do expect_no_offenses('self.sum += 10') end it 'accepts a self receiver with the square bracket operator' do expect_no_offenses('self[a]') end it 'accepts a self receiver with the double less-than operator' do expect_no_offenses('self << a') end it 'accepts a self receiver for methods named like ruby keywords' do expect_no_offenses(<<-RUBY.strip_indent) a = self.class self.for(deps, [], true) self.and(other) self.or(other) self.alias self.begin self.break self.case self.def self.defined? self.do self.else self.elsif self.end self.ensure self.false self.if self.in self.module self.next self.nil self.not self.redo self.rescue self.retry self.return self.self self.super self.then self.true self.undef self.unless self.until self.when self.while self.yield RUBY end it 'accepts a self receiver used to distinguish from argument of block' do expect_no_offenses(<<-RUBY.strip_indent) %w[draft preview moderation approved rejected].each do |state| self.state == state define_method "\#{state}?" do self.state == state end end RUBY end describe 'instance methods' do it 'accepts a self receiver used to distinguish from blockarg' do expect_no_offenses(<<-RUBY.strip_indent) def requested_specs(&groups) some_method(self.groups) end RUBY end it 'accepts a self receiver used to distinguish from argument' do expect_no_offenses(<<-RUBY.strip_indent) def requested_specs(groups) some_method(self.groups) end RUBY end it 'accepts a self receiver used to distinguish from optional argument' do expect_no_offenses(<<-RUBY.strip_indent) def requested_specs(final = true) something if self.final != final end RUBY end it 'accepts a self receiver used to distinguish from local variable' do expect_no_offenses(<<-RUBY.strip_indent) def requested_specs @requested_specs ||= begin groups = self.groups - Bundler.settings.without groups.map! { |g| g.to_sym } specs_for(groups) end end RUBY end it 'accepts a self receiver used to distinguish from an argument' do expect_no_offenses(<<-RUBY.strip_indent) def foo(bar) puts bar, self.bar end RUBY end it 'accepts a self receiver used to distinguish from an argument' \ ' when an inner method is defined' do src = <<-RUBY.strip_indent def foo(bar) def inner_method(); end puts bar, self.bar end RUBY inspect_source(src) expect(cop.offenses.empty?).to be(true) end end describe 'class methods' do it 'accepts a self receiver used to distinguish from blockarg' do expect_no_offenses(<<-RUBY.strip_indent) def self.requested_specs(&groups) some_method(self.groups) end RUBY end it 'accepts a self receiver used to distinguish from argument' do expect_no_offenses(<<-RUBY.strip_indent) def self.requested_specs(groups) some_method(self.groups) end RUBY end it 'accepts a self receiver used to distinguish from optional argument' do expect_no_offenses(<<-RUBY.strip_indent) def self.requested_specs(final = true) something if self.final != final end RUBY end it 'accepts a self receiver used to distinguish from local variable' do expect_no_offenses(<<-RUBY.strip_indent) def self.requested_specs @requested_specs ||= begin groups = self.groups - Bundler.settings.without groups.map! { |g| g.to_sym } specs_for(groups) end end RUBY end end it 'accepts a self receiver used to distinguish from constant' do expect_no_offenses('self.Foo') end it 'accepts a self receiver of .()' do expect_no_offenses('self.()') end it 'reports an offence a self receiver of .call' do src = 'self.call' inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'auto-corrects by removing redundant self' do new_source = autocorrect_source('self.x') expect(new_source).to eq('x') end end rubocop-0.52.1/spec/rubocop/cop/style/regexp_literal_spec.rb000066400000000000000000000272311322072016200241410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RegexpLiteral, :config do subject(:cop) { described_class.new(config) } let(:config) do supported_styles = { 'SupportedStyles' => %w[slashes percent_r mixed] } RuboCop::Config.new('Style/PercentLiteralDelimiters' => percent_literal_delimiters_config, 'Style/RegexpLiteral' => cop_config.merge(supported_styles)) end let(:percent_literal_delimiters_config) do { 'PreferredDelimiters' => { '%r' => '{}' } } end describe 'when regex contains slashes in interpolation' do let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } it 'ignores the slashes that do not belong // regex' do expect_no_offenses('x =~ /\s{#{x[/\s+/].length}}/') end end describe '%r regex with other delimiters than curly braces' do let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) %r_ls_ ^^^^^^ Use `//` around regular expression. RUBY end end describe 'when PercentLiteralDelimiters is configured with brackets' do let(:cop_config) { { 'EnforcedStyle' => 'percent_r' } } let(:percent_literal_delimiters_config) do { 'PreferredDelimiters' => { '%r' => '[]' } } end it 'respects the configuration when auto-correcting' do new_source = autocorrect_source('/a/') expect(new_source).to eq('%r[a]') end end context 'when EnforcedStyle is set to slashes' do let(:cop_config) { { 'EnforcedStyle' => 'slashes' } } describe 'a single-line `//` regex without slashes' do it 'is accepted' do expect_no_offenses('foo = /a/') end end describe 'a single-line `//` regex with slashes' do let(:source) { 'foo = /home\//' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = /home\// ^^^^^^^^ Use `%r` around regular expression. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'is accepted' do expect_no_offenses('foo = /home\\//') end end end describe 'a multi-line `//` regex without slashes' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = / foo bar /x RUBY end end describe 'a multi-line `//` regex with slashes' do let(:source) do ['foo = /', ' https?:\/\/', ' example\.com', '/x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `%r` around regular expression.']) end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'is accepted' do expect_no_offenses(<<-'RUBY'.strip_indent) foo = / https?:\/\/ example\.com /x RUBY end end end describe 'a single-line %r regex without slashes' do let(:source) { 'foo = %r{a}' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %r{a} ^^^^^ Use `//` around regular expression. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = /a/') end end describe 'a single-line %r regex with slashes' do let(:source) { 'foo = %r{home/}' } it 'is accepted' do expect_no_offenses('foo = %r{home/}') end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %r{home/} ^^^^^^^^^ Use `//` around regular expression. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end describe 'a multi-line %r regex without slashes' do let(:source) do ['foo = %r{', ' foo', ' bar', '}x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `//` around regular expression.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = /\n foo\n bar\n/x") end end describe 'a multi-line %r regex with slashes' do let(:source) do ['foo = %r{', ' https?://', ' example\.com', '}x'] end it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %r{ https?:// example\.com }x RUBY end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `//` around regular expression.']) end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end end end context 'when EnforcedStyle is set to percent_r' do let(:cop_config) { { 'EnforcedStyle' => 'percent_r' } } describe 'a single-line `//` regex without slashes' do let(:source) { 'foo = /a/' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = /a/ ^^^ Use `%r` around regular expression. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = %r{a}') end end describe 'a single-line `//` regex with slashes' do let(:source) { 'foo = /home\//' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = /home\// ^^^^^^^^ Use `%r` around regular expression. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end describe 'a multi-line `//` regex without slashes' do let(:source) do ['foo = /', ' foo', ' bar', '/x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `%r` around regular expression.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = %r{\n foo\n bar\n}x") end end describe 'a multi-line `//` regex with slashes' do let(:source) do ['foo = /', ' https?:\/\/', ' example\.com', '/x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `%r` around regular expression.']) end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end describe 'a single-line %r regex without slashes' do it 'is accepted' do expect_no_offenses('foo = %r{a}') end end describe 'a single-line %r regex with slashes' do it 'is accepted' do expect_no_offenses('foo = %r{home/}') end end describe 'a multi-line %r regex without slashes' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %r{ foo bar }x RUBY end end describe 'a multi-line %r regex with slashes' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %r{ https?:// example\.com }x RUBY end end end context 'when EnforcedStyle is set to mixed' do let(:cop_config) { { 'EnforcedStyle' => 'mixed' } } describe 'a single-line `//` regex without slashes' do it 'is accepted' do expect_no_offenses('foo = /a/') end end describe 'a single-line `//` regex with slashes' do let(:source) { 'foo = /home\//' } it 'registers an offense' do expect_offense(<<-'RUBY'.strip_indent) foo = /home\// ^^^^^^^^ Use `%r` around regular expression. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'is accepted' do expect_no_offenses('foo = /home\\//') end end end describe 'a multi-line `//` regex without slashes' do let(:source) do ['foo = /', ' foo', ' bar', '/x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `%r` around regular expression.']) end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq("foo = %r{\n foo\n bar\n}x") end end describe 'a multi-line `//` regex with slashes' do let(:source) do ['foo = /', ' https?:\/\/', ' example\.com', '/x'] end it 'registers an offense' do inspect_source(source) expect(cop.messages).to eq(['Use `%r` around regular expression.']) end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join("\n")) end end describe 'a single-line %r regex without slashes' do let(:source) { 'foo = %r{a}' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %r{a} ^^^^^ Use `//` around regular expression. RUBY end it 'auto-corrects' do new_source = autocorrect_source(source) expect(new_source).to eq('foo = /a/') end end describe 'a single-line %r regex with slashes' do let(:source) { 'foo = %r{home/}' } it 'is accepted' do expect_no_offenses('foo = %r{home/}') end describe 'when configured to allow inner slashes' do before { cop_config['AllowInnerSlashes'] = true } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo = %r{home/} ^^^^^^^^^ Use `//` around regular expression. RUBY end it 'cannot auto-correct' do new_source = autocorrect_source(source) expect(new_source).to eq(source) end end end describe 'a multi-line %r regex without slashes' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %r{ foo bar }x RUBY end end describe 'a multi-line %r regex with slashes' do it 'is accepted' do expect_no_offenses(<<-RUBY.strip_indent) foo = %r{ https?:// example\.com }x RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/rescue_modifier_spec.rb000066400000000000000000000131511322072016200242730ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RescueModifier do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end it 'registers an offense for modifier rescue' do expect_offense(<<-RUBY.strip_indent) method rescue handle ^^^^^^^^^^^^^^^^^^^^ Avoid using `rescue` in its modifier form. RUBY end it 'registers an offense for modifier rescue around parallel assignment' do expect_offense(<<-RUBY.strip_indent) a, b = 1, 2 rescue nil ^^^^^^^^^^^^^^^^^^^^^^ Avoid using `rescue` in its modifier form. RUBY end it 'handles more complex expression with modifier rescue' do expect_offense(<<-RUBY.strip_indent) method1 or method2 rescue handle ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid using `rescue` in its modifier form. RUBY end it 'handles modifier rescue in normal rescue' do inspect_source(<<-RUBY.strip_indent) begin test rescue modifier_handle rescue normal_handle end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['test rescue modifier_handle']) end it 'handles modifier rescue in a method' do inspect_source(<<-RUBY.strip_indent) def a_method test rescue nil end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(2) end it 'does not register an offense for normal rescue' do expect_no_offenses(<<-RUBY.strip_indent) begin test rescue handle end RUBY end it 'does not register an offense for normal rescue with ensure' do expect_no_offenses(<<-RUBY.strip_indent) begin test rescue handle ensure cleanup end RUBY end it 'does not register an offense for nested normal rescue' do expect_no_offenses(<<-RUBY.strip_indent) begin begin test rescue handle_inner end rescue handle_outer end RUBY end context 'when an instance method has implicit begin' do it 'accepts normal rescue' do expect_no_offenses(<<-RUBY.strip_indent) def some_method test rescue handle end RUBY end it 'handles modifier rescue in body of implicit begin' do inspect_source(<<-RUBY.strip_indent) def some_method test rescue modifier_handle rescue normal_handle end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['test rescue modifier_handle']) end end context 'when a singleton method has implicit begin' do it 'accepts normal rescue' do expect_no_offenses(<<-RUBY.strip_indent) def self.some_method test rescue handle end RUBY end it 'handles modifier rescue in body of implicit begin' do inspect_source(<<-RUBY.strip_indent) def self.some_method test rescue modifier_handle rescue normal_handle end RUBY expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line).to eq(2) expect(cop.highlights).to eq(['test rescue modifier_handle']) end end context 'autocorrect' do it 'corrects basic rescue modifier' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo rescue bar RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue bar end RUBY end it 'corrects complex rescue modifier' do new_source = autocorrect_source(<<-RUBY.strip_indent) foo || bar rescue bar RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo || bar rescue bar end RUBY end it 'corrects rescue modifier nested inside of def' do source = <<-RUBY.strip_indent def foo test rescue modifier_handle end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) def foo begin test rescue modifier_handle end end RUBY end it 'corrects nested rescue modifier' do source = <<-RUBY.strip_indent begin test rescue modifier_handle rescue normal_handle end RUBY new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) begin begin test rescue modifier_handle end rescue normal_handle end RUBY end it 'corrects doubled rescue modifiers' do new_source = autocorrect_source_with_loop(<<-RUBY.strip_indent) blah rescue 1 rescue 2 RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin begin blah rescue 1 end rescue 2 end RUBY end end describe 'excluded file' do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/RescueModifier' => { 'Enabled' => true, 'Exclude' => ['**/**'] }) end it 'processes excluded files with issue' do expect_no_offenses('foo rescue bar') end end end rubocop-0.52.1/spec/rubocop/cop/style/rescue_standard_error_spec.rb000066400000000000000000000327471322072016200255220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::RescueStandardError, :config do subject(:cop) { described_class.new(config) } context 'implicit' do let(:cop_config) do { 'EnforcedStyle' => 'implicit', 'SupportedStyles' => %w[implicit explicit] } end context 'when rescuing in a begin block' do it 'accpets rescuing no error class' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue bar end RUBY end it 'accepts rescuing no error class, assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue => e bar end RUBY end it 'accepts rescuing a single error class other than StandardError' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue BarError bar end RUBY end it 'accepts rescuing a single error class other than StandardError, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue BarError => e bar end RUBY end context 'when rescuing StandardError by itself' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) begin foo rescue StandardError ^^^^^^^^^^^^^^^^^^^^ Omit the error class when rescuing `StandardError` by itself. bar end RUBY end it 'autocorrect will remove StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin foo rescue StandardError bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue bar end RUBY end context 'when the error is assigned to a variable' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) begin foo rescue StandardError => e ^^^^^^^^^^^^^^^^^^^^ Omit the error class when rescuing `StandardError` by itself. bar end RUBY end it 'autocorrect will remove StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin foo rescue StandardError => e bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue => e bar end RUBY end end end it 'accepts rescuing StandardError with other errors' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError, BarError bar rescue BazError, StandardError baz end RUBY end it 'accepts rescuing StandardError with other errors, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError, BarError => e bar rescue BazError, StandardError => e baz end RUBY end end context 'when rescuing in a method definition' do it 'accepts rescuing no error class' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue bar end RUBY end it 'accepts rescuing no error class, assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue => e bar end RUBY end it 'accepts rescuing a single error other than StandardError' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue BarError bar end RUBY end it 'accepts rescuing a single error other than StandardError, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue BarError => e bar end RUBY end context 'when rescuing StandardError by itself' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def foobar foo rescue StandardError ^^^^^^^^^^^^^^^^^^^^ Omit the error class when rescuing `StandardError` by itself. bar end RUBY end it 'autocorrect will remove StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foobar foo rescue StandardError bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foobar foo rescue bar end RUBY end context 'when the error is assigned to a variable' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def foobar foo rescue StandardError => e ^^^^^^^^^^^^^^^^^^^^ Omit the error class when rescuing `StandardError` by itself. bar end RUBY end it 'autocorrect will remove StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) def foobar foo rescue StandardError => e bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def foobar foo rescue => e bar end RUBY end end end it 'accepts rescuing StandardError with other errors' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError, BarError bar rescue BazError, StandardError baz end RUBY end it 'accepts rescuing StandardError with other errors, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError, BarError => e bar rescue BazError, StandardError => e baz end RUBY end end it 'accepts rescue modifier' do expect_no_offenses(<<-RUBY.strip_indent) foo rescue 42 RUBY end end context 'explicit' do let(:cop_config) do { 'EnforcedStyle' => 'explicit', 'SupportedStyles' => %w[implicit explicit] } end context 'when rescuing in a begin block' do context 'when calling rescue without an error class' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) begin foo rescue ^^^^^^ Avoid rescuing without specifying an error class. bar end RUBY end it 'autocorrect will add StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin foo rescue bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue StandardError bar end RUBY end context 'when the error is assigned to a variable' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) begin foo rescue => e ^^^^^^ Avoid rescuing without specifying an error class. bar end RUBY end it 'autocorrect will add StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin foo rescue => e bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin foo rescue StandardError => e bar end RUBY end end end it 'accepts rescuing a single error other than StandardError' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue BarError bar end RUBY end it 'accepts rescuing a single error other than StandardError' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue BarError => e bar end RUBY end it 'accepts rescuing StandardError by itself' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError bar end RUBY end it 'accepts rescuing StandardError by itself, assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError => e bar end RUBY end it 'accepts rescuing StandardError with other errors' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError, BarError bar rescue BazError, StandardError baz end RUBY end it 'accepts rescuing StandardError with other errors, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) begin foo rescue StandardError, BarError => e bar rescue BazError, StandardError => e baz end RUBY end end context 'when rescuing in a method definition' do context 'when rescue is called without an error class' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def baz foo rescue ^^^^^^ Avoid rescuing without specifying an error class. bar end RUBY end it 'autocorrect will add StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) def baz foo rescue bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def baz foo rescue StandardError bar end RUBY end end context 'when the error is assigned to a variable' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) def baz foo rescue => e ^^^^^^ Avoid rescuing without specifying an error class. bar end RUBY end it 'autocorrect will add StandardError' do new_source = autocorrect_source(<<-RUBY.strip_indent) def baz foo rescue => e bar end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) def baz foo rescue StandardError => e bar end RUBY end end it 'accepts rescueing a single error other than StandardError' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue BarError bar end RUBY end it 'accepts rescueing a single error other than StandardError, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def baz foo rescue BarError => e bar end RUBY end it 'accepts rescuing StandardError by itself' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError bar end RUBY end it 'accepts rescuing StandardError by itself, assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError => e bar end RUBY end it 'accepts rescuing StandardError with other errors' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError, BarError bar rescue BazError, StandardError baz end RUBY end it 'accepts rescuing StandardError with other errors, ' \ 'assigned to a variable' do expect_no_offenses(<<-RUBY.strip_indent) def foobar foo rescue StandardError, BarError => e bar rescue BazError, StandardError => e baz end RUBY end end it 'accepts rescue modifier' do expect_no_offenses(<<-RUBY.strip_indent) foo rescue 42 RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/return_nil_spec.rb000066400000000000000000000034611322072016200233130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ReturnNil do subject(:cop) { described_class.new(config) } context 'when enforced style is `return`' do let(:config) do RuboCop::Config.new( 'Style/ReturnNil' => { 'EnforcedStyle' => 'return', 'SupportedStyles' => %w[return return_nil] } ) end it 'registers an offense for return nil' do expect_offense(<<-RUBY.strip_indent) return nil ^^^^^^^^^^ Use `return` instead of `return nil`. RUBY end it 'auto-corrects `return nil` into `return`' do expect(autocorrect_source('return nil')).to eq 'return' end it 'does not register an offense for return' do expect_no_offenses('return') end it 'does not register an offense for returning others' do expect_no_offenses('return 2') end it 'does not register an offense for return nil from iterators' do expect_no_offenses(<<-RUBY) loop do return if x end RUBY end end context 'when enforced style is `return_nil`' do let(:config) do RuboCop::Config.new( 'Style/ReturnNil' => { 'EnforcedStyle' => 'return_nil', 'SupportedStyles' => %w[return return_nil] } ) end it 'registers an offense for return' do expect_offense(<<-RUBY.strip_indent) return ^^^^^^ Use `return nil` instead of `return`. RUBY end it 'auto-corrects `return` into `return nil`' do expect(autocorrect_source('return')).to eq 'return nil' end it 'does not register an offense for return nil' do expect_no_offenses('return nil') end it 'does not register an offense for returning others' do expect_no_offenses('return 2') end end end rubocop-0.52.1/spec/rubocop/cop/style/safe_navigation_spec.rb000066400000000000000000001065351322072016200242750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SafeNavigation, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'ConvertCodeThatCanStartToReturnNil' => false } } let(:message) do 'Use safe navigation (`&.`) instead of checking if an object ' \ 'exists before calling the method.' end context 'target_ruby_version > 2.3', :ruby23 do it 'allows calls to methods not safeguarded by respond_to' do expect_no_offenses('foo.bar') end it 'allows calls using safe navigation' do expect_no_offenses('foo&.bar') end it 'allows calls on nil' do expect_no_offenses('nil&.bar') end it 'allows method calls that nil responds to safe guarded by ' \ 'an object check' do expect_no_offenses('foo.to_i if foo') end it 'allows an object check before a method calls that nil responds to ' do expect_no_offenses('foo && foo.to_i') end it 'allows an object check before hash access' do expect_no_offenses('foo && foo[:bar]') end it 'allows an object check before a negated predicate' do expect_no_offenses('foo && !foo.bar?') end it 'allows an object check before a negated predicate method chain' do expect_no_offenses('foo && !foo.bar.baz?') end it 'allows method call that are used in a comparison safe guarded by ' \ 'an object check' do expect_no_offenses('foo.bar > 2 if foo') end it 'allows an object check before a method call that are used in ' \ 'a comparison' do expect_no_offenses('foo && foo.bar > 2') end it 'allows method calls that do not get called using . safe guarded by ' \ 'an object check' do expect_no_offenses('foo + bar if foo') end it 'allows chained method calls during arithmetic operations safe ' \ 'guarded by an object check' do expect_no_offenses('foo.baz + bar if foo') end it 'allows chained method calls during assignment safe guarded' \ 'by an object check' do expect_no_offenses('foo.baz = bar if foo') end it 'allows object checks in the condition of an elsif statement ' \ 'and a method call on that object in the body' do expect_no_offenses(<<-RUBY.strip_indent) if foo something elsif bar bar.baz end RUBY end it 'allows a method call as a parameter when the parameter is ' \ 'safe guarded with an object check' do expect_no_offenses('foo(bar.baz) if bar') end shared_examples 'all variable types' do |variable| context 'modifier if' do it 'registers an offense for a method call on an accessor ' \ 'safeguarded by a check for the accessed variable' do inspect_source("#{variable}[1].bar if #{variable}[1]") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call safeguarded with a check ' \ 'for the object' do inspect_source("#{variable}.bar if #{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params safeguarded ' \ 'with a check for the object' do inspect_source("#{variable}.bar(baz) if #{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with a block safeguarded ' \ 'with a check for the object' do inspect_source("#{variable}.bar { |e| e.qux } if #{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params and a block ' \ 'safeguarded with a check for the object' do inspect_source("#{variable}.bar(baz) { |e| e.qux } if #{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call safeguarded with a ' \ 'negative check for the object' do inspect_source("#{variable}.bar unless !#{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params safeguarded ' \ 'with a negative check for the object' do inspect_source("#{variable}.bar(baz) unless !#{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with a block safeguarded ' \ 'with a negative check for the object' do inspect_source("#{variable}.bar { |e| e.qux } unless !#{variable}") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params and a block ' \ 'safeguarded with a negative check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.bar(baz) { |e| e.qux } unless !#{variable} RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a method call safeguarded with a nil ' \ 'check for the object' do inspect_source("#{variable}.bar unless #{variable}.nil?") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params safeguarded ' \ 'with a nil check for the object' do inspect_source("#{variable}.bar(baz) unless #{variable}.nil?") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with a block safeguarded ' \ 'with a nil check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.bar { |e| e.qux } unless #{variable}.nil? RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params and a block ' \ 'safeguarded with a nil check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.bar(baz) { |e| e.qux } unless #{variable}.nil? RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a method call safeguarded with a ' \ 'negative nil check for the object' do inspect_source("#{variable}.bar if !#{variable}.nil?") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params safeguarded ' \ 'with a negative nil check for the object' do inspect_source("#{variable}.bar(baz) if !#{variable}.nil?") expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with a block safeguarded ' \ 'with a negative nil check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.bar { |e| e.qux } if !#{variable}.nil? RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a method call with params and a block ' \ 'safeguarded with a negative nil check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.bar(baz) { |e| e.qux } if !#{variable}.nil? RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a chained method call safeguarded ' \ 'with a negative nil check for the object' do inspect_source(<<-RUBY.strip_indent) #{variable}.one.two(baz) { |e| e.qux } if !#{variable}.nil? RUBY expect(cop.messages).to eq([message]) end end context 'if expression' do it 'registers an offense for a single method call inside of a check ' \ 'for the object' do inspect_source(<<-RUBY.strip_indent) if #{variable} #{variable}.bar end RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a single method call inside of a ' \ 'non-nil check for the object' do inspect_source(<<-RUBY.strip_indent) if !#{variable}.nil? #{variable}.bar end RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a single method call inside of an ' \ 'unless nil check for the object' do inspect_source(<<-RUBY.strip_indent) unless #{variable}.nil? #{variable}.bar end RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a single method call inside of an ' \ 'unless negative check for the object' do inspect_source(<<-RUBY.strip_indent) unless !#{variable} #{variable}.bar end RUBY expect(cop.messages).to eq([message]) end it 'allows a single method call inside of a check for the object ' \ 'with an else' do expect_no_offenses(<<-RUBY.strip_indent) if #{variable} #{variable}.bar else something end RUBY end context 'ternary expression' do it 'allows ternary expression' do expect_no_offenses(<<-RUBY.strip_indent) !#{variable}.nil? ? #{variable}.bar : something RUBY end end end context 'object check before method call' do context 'ConvertCodeThatCanStartToReturnNil true' do let(:cop_config) { { 'ConvertCodeThatCanStartToReturnNil' => true } } it 'registers an offense for a non-nil object check followed by a ' \ 'method call' do inspect_source("!#{variable}.nil? && #{variable}.bar") expect(cop.messages).to eq([message]) end it 'registers an offense for a non-nil object check followed by a ' \ 'method call with params' do inspect_source("!#{variable}.nil? && #{variable}.bar(baz)") expect(cop.messages).to eq([message]) end it 'registers an offense for a non-nil object check followed by a ' \ 'method call with a block' do inspect_source(<<-RUBY.strip_indent) !#{variable}.nil? && #{variable}.bar { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a non-nil object check followed by a ' \ 'method call with params and a block' do inspect_source(<<-RUBY.strip_indent) !#{variable}.nil? && #{variable}.bar(baz) { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by a ' \ 'method call' do inspect_source("#{variable} && #{variable}.bar") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by a ' \ 'method call with params' do inspect_source("#{variable} && #{variable}.bar(baz)") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by a ' \ 'method call with a block' do inspect_source("#{variable} && #{variable}.bar { |e| e.qux }") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by a ' \ 'method call with params and a block' do inspect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.bar(baz) { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a check for the object followed by a ' \ 'method call in the condition for an if expression' do inspect_source(<<-RUBY.strip_indent) if #{variable} && #{variable}.bar something end RUBY expect(cop.messages).to eq([message]) end context 'method chaining' do it 'registers an offense for an object check followed by ' \ 'chained method calls' do inspect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.one.two.three(baz) { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by a ' \ 'chained method calls with blocks' do inspect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.one { |a| b}.two(baz) { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end end end context 'ConvertCodeThatCanStartToReturnNil false' do let(:cop_config) { { 'ConvertCodeThatCanStartToReturnNil' => false } } it 'allows a non-nil object check followed by a method call' do expect_no_offenses("!#{variable}.nil? && #{variable}.bar") end it 'allows a non-nil object check followed by a method call ' \ 'with params' do expect_no_offenses("!#{variable}.nil? && #{variable}.bar(baz)") end it 'allows a non-nil object check followed by a method call ' \ 'with a block' do expect_no_offenses(<<-RUBY.strip_indent) !#{variable}.nil? && #{variable}.bar { |e| e.qux } RUBY end it 'allows a non-nil object check followed by a method call ' \ 'with params and a block' do expect_no_offenses(<<-RUBY.strip_indent) !#{variable}.nil? && #{variable}.bar(baz) { |e| e.qux } RUBY end it 'registers an offense for an object check followed by ' \ 'a method call' do inspect_source("#{variable} && #{variable}.bar") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by ' \ 'a method call with params' do inspect_source("#{variable} && #{variable}.bar(baz)") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by ' \ 'a method call with a block' do inspect_source("#{variable} && #{variable}.bar { |e| e.qux }") expect(cop.messages).to eq([message]) end it 'registers an offense for an object check followed by ' \ 'a method call with params and a block' do inspect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.bar(baz) { |e| e.qux } RUBY expect(cop.messages).to eq([message]) end it 'registers an offense for a check for the object followed by ' \ 'a method call in the condition for an if expression' do inspect_source(<<-RUBY.strip_indent) if #{variable} && #{variable}.bar something end RUBY expect(cop.messages).to eq([message]) end end it 'allows a nil object check followed by a method call' do expect_no_offenses("#{variable}.nil? || #{variable}.bar") end it 'allows a nil object check followed by a method call with params' do expect_no_offenses("#{variable}.nil? || #{variable}.bar(baz)") end it 'allows a nil object check followed by a method call with a block' do expect_no_offenses(<<-RUBY.strip_indent) #{variable}.nil? || #{variable}.bar { |e| e.qux } RUBY end it 'allows a nil object check followed by a method call with params ' \ 'and a block' do expect_no_offenses(<<-RUBY.strip_indent) #{variable}.nil? || #{variable}.bar(baz) { |e| e.qux } RUBY end it 'allows a non object check followed by a method call' do expect_no_offenses("!#{variable} || #{variable}.bar") end it 'allows a non object check followed by a method call with params' do expect_no_offenses("!#{variable} || #{variable}.bar(baz)") end it 'allows a non object check followed by a method call with a block' do expect_no_offenses("!#{variable} || #{variable}.bar { |e| e.qux }") end it 'allows a non object check followed by a method call with params ' \ 'and a block' do expect_no_offenses(<<-RUBY.strip_indent) !#{variable} || #{variable}.bar(baz) { |e| e.qux } RUBY end end end it_behaves_like('all variable types', 'foo') it_behaves_like('all variable types', 'FOO') it_behaves_like('all variable types', 'FOO::BAR') it_behaves_like('all variable types', '@foo') it_behaves_like('all variable types', '@@foo') it_behaves_like('all variable types', '$FOO') context 'respond_to?' do it 'allows method calls safeguarded by a respond_to check' do expect_no_offenses('foo.bar if foo.respond_to?(:bar)') end it 'allows method calls safeguarded by a respond_to check to a ' \ 'different method' do expect_no_offenses('foo.bar if foo.respond_to?(:foobar)') end it 'allows method calls safeguarded by a respond_to check on a' \ 'different variable but the same method' do expect_no_offenses('foo.bar if baz.respond_to?(:bar)') end it 'allows method calls safeguarded by a respond_to check on a' \ 'different variable and method' do expect_no_offenses('foo.bar if baz.respond_to?(:foo)') end it 'allows enumerable accessor method calls safeguarded by ' \ 'a respond_to check' do expect_no_offenses('foo[0] if foo.respond_to?(:[])') end end context 'auto-correct' do shared_examples 'all variable types' do |variable| context 'modifier if' do it 'corrects a method call safeguarded with a check for the object' do new_source = autocorrect_source("#{variable}.bar if #{variable}") expect(new_source).to eq("#{variable}&.bar") end it 'corrects a method call with params safeguarded with a check ' \ 'for the object' do source = "#{variable}.bar(baz) if #{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects a method call with a block safeguarded with a check ' \ 'for the object' do source = "#{variable}.bar { |e| e.qux } if #{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects a method call with params and a block safeguarded ' \ 'with a check for the object' do source = "#{variable}.bar(baz) { |e| e.qux } if #{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }") end it 'corrects a method call safeguarded with a negative check for ' \ 'the object' do source = "#{variable}.bar unless !#{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar") end it 'corrects a method call with params safeguarded with a ' \ 'negative check for the object' do source = "#{variable}.bar(baz) unless !#{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects a method call with a block safeguarded with a ' \ 'negative check for the object' do source = "#{variable}.bar { |e| e.qux } unless !#{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects a method call with params and a block safeguarded ' \ 'with a negative check for the object' do source = "#{variable}.bar(baz) { |e| e.qux } unless !#{variable}" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }") end it 'corrects a method call safeguarded with a nil check for the ' \ 'object' do source = "#{variable}.bar unless #{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar") end it 'corrects a method call with params safeguarded with a nil ' \ 'check for the object' do source = "#{variable}.bar(baz) unless #{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects a method call with a block safeguarded with a nil ' \ 'check for the object' do source = "#{variable}.bar { |e| e.qux } unless #{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects a method call with params and a block safeguarded ' \ 'with a nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable}.bar(baz) { |e| e.qux } unless #{variable}.nil? RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.bar(baz) { |e| e.qux } RUBY end it 'corrects a method call safeguarded with a negative nil check ' \ 'for the object' do source = "#{variable}.bar if !#{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar") end it 'corrects a method call with params safeguarded with a ' \ 'negative nil check for the object' do source = "#{variable}.bar(baz) if !#{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects a method call with a block safeguarded with a ' \ 'negative nil check for the object' do source = "#{variable}.bar { |e| e.qux } if !#{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects a method call with params and a block safeguarded ' \ 'with a negative nil check for the object' do source = "#{variable}.bar(baz) { |e| e.qux } if !#{variable}.nil?" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }") end it 'corrects a method call on an accessor safeguarded by a check ' \ 'for the accessed variable' do source = "#{variable}[1].bar if #{variable}[1]" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}[1]&.bar") end it 'corrects a chained method call safeguarded ' \ 'with a negative nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable}.one.two(baz) { |e| e.qux } if !#{variable}.nil? RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one.two(baz) { |e| e.qux } RUBY end it 'corrects a chained method call safeguarded ' \ 'with a check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable}.one.two(baz) { |e| e.qux } if #{variable} RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one.two(baz) { |e| e.qux } RUBY end it 'corrects a chained method call safeguarded ' \ 'with an unless nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable}.one.two(baz) { |e| e.qux } unless #{variable}.nil? RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one.two(baz) { |e| e.qux } RUBY end end context 'if expression' do it 'corrects a single method call inside of a check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if #{variable} #{variable}.bar end RUBY expect(new_source).to eq("#{variable}&.bar\n") end it 'corrects a single method call with params inside of a check ' \ 'for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if #{variable} #{variable}.bar(baz) end RUBY expect(new_source).to eq("#{variable}&.bar(baz)\n") end it 'corrects a single method call with a block inside of a check ' \ 'for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if #{variable} #{variable}.bar { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar { |e| e.qux }\n") end it 'corrects a single method call with params and a block inside ' \ 'of a check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if #{variable} #{variable}.bar(baz) { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }\n") end it 'corrects a single method call inside of a non-nil check for ' \ 'the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if !#{variable}.nil? #{variable}.bar end RUBY expect(new_source).to eq("#{variable}&.bar\n") end it 'corrects a single method call with params inside of a non-nil ' \ 'check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if !#{variable}.nil? #{variable}.bar(baz) end RUBY expect(new_source).to eq("#{variable}&.bar(baz)\n") end it 'corrects a single method call with a block inside of a non-nil ' \ 'check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if !#{variable}.nil? #{variable}.bar { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar { |e| e.qux }\n") end it 'corrects a single method call with params and a block inside ' \ 'of a non-nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) if !#{variable}.nil? #{variable}.bar(baz) { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }\n") end it 'corrects a single method call inside of an unless nil check ' \ 'for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless #{variable}.nil? #{variable}.bar end RUBY expect(new_source).to eq("#{variable}&.bar\n") end it 'corrects a single method call with params inside of an unless ' \ 'nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless #{variable}.nil? #{variable}.bar(baz) end RUBY expect(new_source).to eq("#{variable}&.bar(baz)\n") end it 'corrects a single method call with a block inside of an unless ' \ 'nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless #{variable}.nil? #{variable}.bar { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar { |e| e.qux }\n") end it 'corrects a single method call with params and a block inside ' \ 'of an unless nil check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless #{variable}.nil? #{variable}.bar(baz) { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }\n") end it 'corrects a single method call inside of an unless negative ' \ 'check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless !#{variable} #{variable}.bar end RUBY expect(new_source).to eq("#{variable}&.bar\n") end it 'corrects a single method call with params inside of an unless ' \ 'negative check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless !#{variable} #{variable}.bar(baz) end RUBY expect(new_source).to eq("#{variable}&.bar(baz)\n") end it 'corrects a single method call with a block inside of an unless ' \ 'negative check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless !#{variable} #{variable}.bar { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar { |e| e.qux }\n") end it 'corrects a single method call with params and a block inside ' \ 'of an unless negative check for the object' do new_source = autocorrect_source(<<-RUBY.strip_indent) unless !#{variable} #{variable}.bar(baz) { |e| e.qux } end RUBY expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }\n") end end context 'object check before method call' do context 'ConvertCodeThatCanStartToReturnNil true' do let(:cop_config) do { 'ConvertCodeThatCanStartToReturnNil' => true } end it 'corrects an object check followed by a method call' do source = "#{variable} && #{variable}.bar" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar") end it 'corrects an object check followed by a method call ' \ 'with params' do source = "#{variable} && #{variable}.bar(baz)" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects an object check followed by a method call with ' \ 'a block' do source = "#{variable} && #{variable}.bar { |e| e.qux }" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects an object check followed by a method call with ' \ 'params and a block' do source = "#{variable} && #{variable}.bar(baz) { |e| e.qux }" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }") end it 'corrects a non-nil object check followed by a method call' do source = "!#{variable}.nil? && #{variable}.bar" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar") end it 'corrects a non-nil object check followed by a method call ' \ 'with params' do source = "!#{variable}.nil? && #{variable}.bar(baz)" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz)") end it 'corrects a non-nil object check followed by a method call ' \ 'with a block' do source = "!#{variable}.nil? && #{variable}.bar { |e| e.qux }" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar { |e| e.qux }") end it 'corrects a non-nil object check followed by a method call ' \ 'with params and a block' do source = "!#{variable}.nil? && #{variable}.bar(baz) { |e| e.qux }" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar(baz) { |e| e.qux }") end it 'corrects an object check followed by a method call and ' \ 'another check' do source = "#{variable} && #{variable}.bar && something" new_source = autocorrect_source(source) expect(new_source).to eq("#{variable}&.bar && something") end end context 'method chaining' do it 'corrects an object check followed by a chained method call' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.one.two(baz) { |e| e.qux } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one.two(baz) { |e| e.qux } RUBY end it 'corrects an object check followed by ' \ 'multiple chained method call' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.one.two.three(baz) { |e| e.qux } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one.two.three(baz) { |e| e.qux } RUBY end it 'corrects an object check followed by ' \ 'multiple chained method calls with blocks' do new_source = autocorrect_source(<<-RUBY.strip_indent) #{variable} && #{variable}.one { |a| b}.two(baz) { |e| e.qux } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) #{variable}&.one { |a| b}.two(baz) { |e| e.qux } RUBY end end end end it_behaves_like('all variable types', 'foo') it_behaves_like('all variable types', 'FOO') it_behaves_like('all variable types', 'FOO::BAR') it_behaves_like('all variable types', '@foo') it_behaves_like('all variable types', '@@foo') it_behaves_like('all variable types', '$FOO') end end context 'target_ruby_version < 2.3', :ruby22 do it 'allows a method call safeguarded by a check for the variable' do expect_no_offenses('foo.bar if foo') end end end rubocop-0.52.1/spec/rubocop/cop/style/self_assignment_spec.rb000066400000000000000000000014671322072016200243170ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SelfAssignment do subject(:cop) { described_class.new } %i[+ - * ** / | & || &&].product(['x', '@x', '@@x']).each do |op, var| it "registers an offense for non-shorthand assignment #{op} and #{var}" do inspect_source("#{var} = #{var} #{op} y") expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(["Use self-assignment shorthand `#{op}=`."]) end it "accepts shorthand assignment for #{op} and #{var}" do inspect_source("#{var} #{op}= y") expect(cop.offenses.empty?).to be(true) end it "auto-corrects a non-shorthand assignment #{op} and #{var}" do new_source = autocorrect_source("#{var} = #{var} #{op} y") expect(new_source).to eq("#{var} #{op}= y") end end end rubocop-0.52.1/spec/rubocop/cop/style/semicolon_spec.rb000066400000000000000000000064151322072016200231240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Semicolon, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'AllowAsExpressionSeparator' => false } } it 'registers an offense for a single expression' do expect_offense(<<-RUBY.strip_indent) puts "this is a test"; ^ Do not use semicolons to terminate expressions. RUBY end it 'registers an offense for several expressions' do expect_offense(<<-RUBY.strip_indent) puts "this is a test"; puts "So is this" ^ Do not use semicolons to terminate expressions. RUBY end it 'registers an offense for one line method with two statements' do expect_offense(<<-RUBY.strip_indent) def foo(a) x(1); y(2); z(3); end ^ Do not use semicolons to terminate expressions. RUBY end it 'accepts semicolon before end if so configured' do expect_no_offenses('def foo(a) z(3); end') end it 'accepts semicolon after params if so configured' do expect_no_offenses('def foo(a); z(3) end') end it 'accepts one line method definitions' do expect_no_offenses(<<-RUBY.strip_indent) def foo1; x(3) end def initialize(*_); end def foo2() x(3); end def foo3; x(3); end RUBY end it 'accepts one line empty class definitions' do expect_no_offenses(<<-RUBY.strip_indent) # Prefer a single-line format for class ... class Foo < Exception; end class Bar; end RUBY end it 'accepts one line empty method definitions' do expect_no_offenses(<<-RUBY.strip_indent) # One exception to the rule are empty-body methods def no_op; end def foo; end RUBY end it 'accepts one line empty module definitions' do expect_no_offenses('module Foo; end') end it 'registers an offense for semicolon at the end no matter what' do expect_offense(<<-RUBY.strip_indent) module Foo; end; ^ Do not use semicolons to terminate expressions. RUBY end it 'accept semicolons inside strings' do expect_no_offenses(<<-RUBY.strip_indent) string = "; multi-line string" RUBY end it 'registers an offense for a semicolon at the beginning of a line' do expect_offense(<<-RUBY.strip_indent) ; puts 1 ^ Do not use semicolons to terminate expressions. RUBY end it 'auto-corrects semicolons when syntactically possible' do corrected = autocorrect_source(<<-RUBY.strip_indent) module Foo; end; puts "this is a test"; puts "this is a test"; puts "So is this" def foo(a) x(1); y(2); z(3); end ;puts 1 RUBY expect(corrected) .to eq(<<-RUBY.strip_indent) module Foo; end puts "this is a test" puts "this is a test"; puts "So is this" def foo(a) x(1); y(2); z(3); end puts 1 RUBY end context 'when AllowAsExpressionSeparator is true' do let(:cop_config) { { 'AllowAsExpressionSeparator' => true } } it 'accepts several expressions' do expect_no_offenses('puts "this is a test"; puts "So is this"') end it 'accepts one line method with two statements' do expect_no_offenses('def foo(a) x(1); y(2); z(3); end') end end end rubocop-0.52.1/spec/rubocop/cop/style/send_spec.rb000066400000000000000000000043571322072016200220700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::Send do subject(:cop) { described_class.new } context 'with send' do context 'and with a receiver' do it 'registers an offense for an invocation with args' do expect_offense(<<-RUBY.strip_indent) Object.send(:inspect) ^^^^ Prefer `Object#__send__` or `Object#public_send` to `send`. RUBY end it 'does not register an offense for an invocation without args' do expect_no_offenses('Object.send') end end context 'and without a receiver' do it 'registers an offense for an invocation with args' do expect_offense(<<-RUBY.strip_indent) send(:inspect) ^^^^ Prefer `Object#__send__` or `Object#public_send` to `send`. RUBY end it 'does not register an offense for an invocation without args' do expect_no_offenses('send') end end end context 'with __send__' do context 'and with a receiver' do it 'does not register an offense for an invocation with args' do expect_no_offenses('Object.__send__(:inspect)') end it 'does not register an offense for an invocation without args' do expect_no_offenses('Object.__send__') end end context 'and without a receiver' do it 'does not register an offense for an invocation with args' do expect_no_offenses('__send__(:inspect)') end it 'does not register an offense for an invocation without args' do expect_no_offenses('__send__') end end end context 'with public_send' do context 'and with a receiver' do it 'does not register an offense for an invocation with args' do expect_no_offenses('Object.public_send(:inspect)') end it 'does not register an offense for an invocation without args' do expect_no_offenses('Object.public_send') end end context 'and without a receiver' do it 'does not register an offense for an invocation with args' do expect_no_offenses('public_send(:inspect)') end it 'does not register an offense for an invocation without args' do expect_no_offenses('public_send') end end end end rubocop-0.52.1/spec/rubocop/cop/style/signal_exception_spec.rb000066400000000000000000000216051322072016200244650ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SignalException, :config do subject(:cop) { described_class.new(config) } context 'when enforced style is `semantic`' do let(:cop_config) { { 'EnforcedStyle' => 'semantic' } } it 'registers an offense for raise in begin section' do expect_offense(<<-RUBY.strip_indent) begin raise ^^^^^ Use `fail` instead of `raise` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for raise in def body' do expect_offense(<<-RUBY.strip_indent) def test raise ^^^^^ Use `fail` instead of `raise` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for fail in rescue section' do expect_offense(<<-RUBY.strip_indent) begin fail rescue Exception fail ^^^^ Use `raise` instead of `fail` to rethrow exceptions. end RUBY end it 'accepts raise in rescue section' do expect_no_offenses(<<-RUBY.strip_indent) begin fail rescue Exception raise RuntimeError end RUBY end it 'accepts raise in def with multiple rescues' do expect_no_offenses(<<-RUBY.strip_indent) def test fail rescue StandardError # handle error rescue Exception raise end RUBY end it 'registers an offense for fail in def rescue section' do expect_offense(<<-RUBY.strip_indent) def test fail rescue Exception fail ^^^^ Use `raise` instead of `fail` to rethrow exceptions. end RUBY end it 'registers an offense for fail in second rescue' do expect_offense(<<-RUBY.strip_indent) def test fail rescue StandardError # handle error rescue Exception fail ^^^^ Use `raise` instead of `fail` to rethrow exceptions. end RUBY end it 'registers only offense for one raise that should be fail' do # This is a special case that has caused double reporting. expect_offense(<<-RUBY.strip_indent) map do raise 'I' ^^^^^ Use `fail` instead of `raise` to signal exceptions. end.flatten.compact RUBY end it 'accepts raise in def rescue section' do expect_no_offenses(<<-RUBY.strip_indent) def test fail rescue Exception raise end RUBY end it 'accepts `raise` and `fail` with explicit receiver' do expect_no_offenses(<<-RUBY.strip_indent) def test test.raise rescue Exception test.fail end RUBY end it 'registers an offense for `raise` and `fail` with `Kernel` as ' \ 'explicit receiver' do inspect_source(<<-RUBY.strip_indent) def test Kernel.raise rescue Exception Kernel.fail end RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages) .to eq(['Use `fail` instead of `raise` to signal exceptions.', 'Use `raise` instead of `fail` to rethrow exceptions.']) end it 'registers an offense for raise not in a begin/rescue/end' do expect_offense(<<-RUBY.strip_indent) case cop_config['EnforcedStyle'] when 'single_quotes' then true when 'double_quotes' then false else raise 'Unknown StringLiterals style' ^^^^^ Use `fail` instead of `raise` to signal exceptions. end RUBY end it 'registers one offense for each raise' do inspect_source(<<-RUBY.strip_indent) cop.stub(:on_def) { raise RuntimeError } cop.stub(:on_def) { raise RuntimeError } RUBY expect(cop.offenses.size).to eq(2) expect(cop.messages) .to eq(['Use `fail` instead of `raise` to signal exceptions.'] * 2) end it 'is not confused by nested begin/rescue' do inspect_source(<<-RUBY.strip_indent) begin raise begin raise rescue fail end rescue Exception #do nothing end RUBY expect(cop.offenses.size).to eq(3) expect(cop.messages) .to eq(['Use `fail` instead of `raise` to signal exceptions.'] * 2 + ['Use `raise` instead of `fail` to rethrow exceptions.']) end it 'auto-corrects raise to fail when appropriate' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin raise rescue Exception raise end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin fail rescue Exception raise end RUBY end it 'auto-corrects fail to raise when appropriate' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin fail rescue Exception fail end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin fail rescue Exception raise end RUBY end end context 'when enforced style is `raise`' do let(:cop_config) { { 'EnforcedStyle' => 'only_raise' } } it 'registers an offense for fail in begin section' do expect_offense(<<-RUBY.strip_indent) begin fail ^^^^ Always use `raise` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for fail in def body' do expect_offense(<<-RUBY.strip_indent) def test fail ^^^^ Always use `raise` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for fail in rescue section' do expect_offense(<<-RUBY.strip_indent) begin raise rescue Exception fail ^^^^ Always use `raise` to signal exceptions. end RUBY end it 'accepts `fail` if a custom `fail` instance method is defined' do expect_no_offenses(<<-RUBY.strip_indent) class A def fail(arg) end def other_method fail "message" end end RUBY end it 'accepts `fail` if a custom `fail` singleton method is defined' do expect_no_offenses(<<-RUBY.strip_indent) class A def self.fail(arg) end def self.other_method fail "message" end end RUBY end it 'accepts `fail` with explicit receiver' do expect_no_offenses('test.fail') end it 'registers an offense for `fail` with `Kernel` as explicit receiver' do expect_offense(<<-RUBY.strip_indent) Kernel.fail ^^^^ Always use `raise` to signal exceptions. RUBY end it 'auto-corrects fail to raise always' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin fail rescue Exception fail end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin raise rescue Exception raise end RUBY end end context 'when enforced style is `fail`' do let(:cop_config) { { 'EnforcedStyle' => 'only_fail' } } it 'registers an offense for raise in begin section' do expect_offense(<<-RUBY.strip_indent) begin raise ^^^^^ Always use `fail` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for raise in def body' do expect_offense(<<-RUBY.strip_indent) def test raise ^^^^^ Always use `fail` to signal exceptions. rescue Exception #do nothing end RUBY end it 'registers an offense for raise in rescue section' do expect_offense(<<-RUBY.strip_indent) begin fail rescue Exception raise ^^^^^ Always use `fail` to signal exceptions. end RUBY end it 'accepts `raise` with explicit receiver' do expect_no_offenses('test.raise') end it 'registers an offense for `raise` with `Kernel` as explicit receiver' do expect_offense(<<-RUBY.strip_indent) Kernel.raise ^^^^^ Always use `fail` to signal exceptions. RUBY end it 'auto-corrects raise to fail always' do new_source = autocorrect_source(<<-RUBY.strip_indent) begin raise rescue Exception raise end RUBY expect(new_source).to eq(<<-RUBY.strip_indent) begin fail rescue Exception fail end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/single_line_block_params_spec.rb000066400000000000000000000045261322072016200261420ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SingleLineBlockParams, :config do subject(:cop) { described_class.new(config) } let(:cop_config) do { 'Methods' => [{ 'reduce' => %w[a e] }, { 'test' => %w[x y] }] } end it 'finds wrong argument names in calls with different syntax' do inspect_source(<<-RUBY.strip_indent) def m [0, 1].reduce { |c, d| c + d } [0, 1].reduce{ |c, d| c + d } [0, 1].reduce(5) { |c, d| c + d } [0, 1].reduce(5){ |c, d| c + d } [0, 1].reduce (5) { |c, d| c + d } [0, 1].reduce(5) { |c, d| c + d } ala.test { |x, z| bala } end RUBY expect(cop.offenses.size).to eq(7) expect(cop.offenses.map(&:line).sort).to eq((2..8).to_a) expect(cop.messages.first) .to eq('Name `reduce` block params `|a, e|`.') end it 'allows calls with proper argument names' do expect_no_offenses(<<-RUBY.strip_indent) def m [0, 1].reduce { |a, e| a + e } [0, 1].reduce{ |a, e| a + e } [0, 1].reduce(5) { |a, e| a + e } [0, 1].reduce(5){ |a, e| a + e } [0, 1].reduce (5) { |a, e| a + e } [0, 1].reduce(5) { |a, e| a + e } ala.test { |x, y| bala } end RUBY end it 'allows an unused parameter to have a leading underscore' do expect_no_offenses('File.foreach(filename).reduce(0) { |a, _e| a + 1 }') end it 'finds incorrectly named parameters with leading underscores' do expect_offense(<<-RUBY.strip_indent) File.foreach(filename).reduce(0) { |_x, _y| } ^^^^^^^^ Name `reduce` block params `|a, e|`. RUBY end it 'ignores do..end blocks' do expect_no_offenses(<<-RUBY.strip_indent) def m [0, 1].reduce do |c, d| c + d end end RUBY end it 'ignores :reduce symbols' do expect_no_offenses(<<-RUBY.strip_indent) def m call_method(:reduce) { |a, b| a + b} end RUBY end it 'does not report when destructuring is used' do expect_no_offenses(<<-RUBY.strip_indent) def m test.reduce { |a, (id, _)| a + id} end RUBY end it 'does not report if no block arguments are present' do expect_no_offenses(<<-RUBY.strip_indent) def m test.reduce { true } end RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/single_line_methods_spec.rb000066400000000000000000000071761322072016200251540ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SingleLineMethods do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Style/SingleLineMethods' => cop_config, 'Layout/IndentationWidth' => { 'Width' => 2 }) end let(:cop_config) { { 'AllowIfMethodIsEmpty' => true } } it 'registers an offense for a single-line method' do expect_offense(<<-RUBY.strip_indent) def some_method; body end ^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid single-line method definitions. def link_to(name, url); {:name => name}; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid single-line method definitions. def @table.columns; super; end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid single-line method definitions. RUBY end context 'when AllowIfMethodIsEmpty is disabled' do let(:cop_config) { { 'AllowIfMethodIsEmpty' => false } } it 'registers an offense for an empty method' do expect_offense(<<-RUBY.strip_indent) def no_op; end ^^^^^^^^^^^^^^ Avoid single-line method definitions. def self.resource_class=(klass); end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Avoid single-line method definitions. def @table.columns; end ^^^^^^^^^^^^^^^^^^^^^^^ Avoid single-line method definitions. RUBY end it 'auto-corrects an empty method' do corrected = autocorrect_source('def x; end') expect(corrected).to eq(['def x; ', 'end'].join("\n")) end end context 'when AllowIfMethodIsEmpty is enabled' do let(:cop_config) { { 'AllowIfMethodIsEmpty' => true } } it 'accepts a single-line empty method' do expect_no_offenses(<<-RUBY.strip_indent) def no_op; end def self.resource_class=(klass); end def @table.columns; end RUBY end end it 'accepts a multi-line method' do expect_no_offenses(<<-RUBY.strip_indent) def some_method body end RUBY end it 'does not crash on an method with a capitalized name' do expect_no_offenses(<<-RUBY.strip_indent) def NoSnakeCase end RUBY end it 'auto-corrects def with semicolon after method name' do corrected = autocorrect_source([' def some_method; body end # Cmnt']) expect(corrected).to eq [' # Cmnt', ' def some_method; ', ' body ', ' end '].join("\n") end it 'auto-corrects defs with parentheses after method name' do corrected = autocorrect_source([' def self.some_method() body end']) expect(corrected).to eq [' def self.some_method() ', ' body ', ' end'].join("\n") end it 'auto-corrects def with argument in parentheses' do corrected = autocorrect_source([' def some_method(arg) body end']) expect(corrected).to eq [' def some_method(arg) ', ' body ', ' end'].join("\n") end it 'auto-corrects def with argument and no parentheses' do corrected = autocorrect_source([' def some_method arg; body end']) expect(corrected).to eq [' def some_method arg; ', ' body ', ' end'].join("\n") end it 'auto-corrects def with semicolon before end' do corrected = autocorrect_source([' def some_method; b1; b2; end']) expect(corrected).to eq [' def some_method; ', ' b1; ', ' b2; ', ' end'].join("\n") end end rubocop-0.52.1/spec/rubocop/cop/style/special_global_vars_spec.rb000066400000000000000000000077401322072016200251310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SpecialGlobalVars, :config do subject(:cop) { described_class.new(config) } context 'when style is use_english_names' do let(:cop_config) { { 'EnforcedStyle' => 'use_english_names' } } it 'registers an offense for $:' do expect_offense(<<-RUBY.strip_indent) puts $: ^^ Prefer `$LOAD_PATH` over `$:`. RUBY end it 'registers an offense for $"' do expect_offense(<<-RUBY.strip_indent) puts $" ^^ Prefer `$LOADED_FEATURES` over `$"`. RUBY end it 'registers an offense for $0' do expect_offense(<<-RUBY.strip_indent) puts $0 ^^ Prefer `$PROGRAM_NAME` over `$0`. RUBY end it 'registers an offense for $$' do expect_offense(<<-RUBY.strip_indent) puts $$ ^^ Prefer `$PROCESS_ID` or `$PID` from the stdlib 'English' module (don't forget to require it) over `$$`. RUBY end it 'is clear about variables from the English library vs those not' do expect_offense(<<-RUBY.strip_indent) puts $* ^^ Prefer `$ARGV` from the stdlib 'English' module (don't forget to require it), or `ARGV` over `$*`. RUBY end it 'does not register an offense for backrefs like $1' do expect_no_offenses('puts $1') end it 'auto-corrects $: to $LOAD_PATH' do new_source = autocorrect_source('$:') expect(new_source).to eq('$LOAD_PATH') end it 'auto-corrects $/ to $INPUT_RECORD_SEPARATOR' do new_source = autocorrect_source('$/') expect(new_source).to eq('$INPUT_RECORD_SEPARATOR') end it 'auto-corrects #$: to #{$LOAD_PATH}' do new_source = autocorrect_source('"#$:"') expect(new_source).to eq('"#{$LOAD_PATH}"') end it 'auto-corrects #{$!} to #{$ERROR_INFO}' do new_source = autocorrect_source('"#{$!}"') expect(new_source).to eq('"#{$ERROR_INFO}"') end it 'generates correct auto-config when Perl variable names are used' do inspect_source('$0') expect(cop.config_to_allow_offenses).to eq( 'EnforcedStyle' => 'use_perl_names' ) end it 'generates correct auto-config when mixed styles are used' do inspect_source('$!; $ERROR_INFO') expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end end context 'when style is use_perl_names' do let(:cop_config) { { 'EnforcedStyle' => 'use_perl_names' } } it 'registers an offense for $LOAD_PATH' do expect_offense(<<-RUBY.strip_indent) puts $LOAD_PATH ^^^^^^^^^^ Prefer `$:` over `$LOAD_PATH`. RUBY end it 'registers an offense for $LOADED_FEATURES' do expect_offense(<<-RUBY.strip_indent) puts $LOADED_FEATURES ^^^^^^^^^^^^^^^^ Prefer `$"` over `$LOADED_FEATURES`. RUBY end it 'registers an offense for $PROGRAM_NAME' do expect_offense(<<-RUBY.strip_indent) puts $PROGRAM_NAME ^^^^^^^^^^^^^ Prefer `$0` over `$PROGRAM_NAME`. RUBY end it 'registers an offense for $PID' do expect_offense(<<-RUBY.strip_indent) puts $PID ^^^^ Prefer `$$` over `$PID`. RUBY end it 'registers an offense for $PROCESS_ID' do expect_offense(<<-RUBY.strip_indent) puts $PROCESS_ID ^^^^^^^^^^^ Prefer `$$` over `$PROCESS_ID`. RUBY end it 'does not register an offense for backrefs like $1' do expect_no_offenses('puts $1') end it 'auto-corrects $LOAD_PATH to $:' do new_source = autocorrect_source('$LOAD_PATH') expect(new_source).to eq('$:') end it 'auto-corrects $INPUT_RECORD_SEPARATOR to $/' do new_source = autocorrect_source('$INPUT_RECORD_SEPARATOR') expect(new_source).to eq('$/') end it 'auto-corrects #{$LOAD_PATH} to #$:' do new_source = autocorrect_source('"#{$LOAD_PATH}"') expect(new_source).to eq('"#$:"') end end end rubocop-0.52.1/spec/rubocop/cop/style/stabby_lambda_parentheses_spec.rb000066400000000000000000000033731322072016200263210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StabbyLambdaParentheses, :config do subject(:cop) { described_class.new(config) } shared_examples 'common' do it 'does not check the old lambda syntax' do expect_no_offenses('lambda(&:nil?)') end it 'does not check a stabby lambda without arguments' do expect_no_offenses('-> { true }') end it 'does not check a method call named lambda' do expect_no_offenses('o.lambda') end end context 'require_parentheses' do let(:cop_config) { { 'EnforcedStyle' => 'require_parentheses' } } it_behaves_like 'common' it 'registers an offense for a stabby lambda without parentheses' do expect_offense(<<-RUBY.strip_indent) ->a,b,c { a + b + c } ^^^^^ Wrap stabby lambda arguments with parentheses. RUBY end it 'does not register an offense for a stabby lambda with parentheses' do expect_no_offenses('->(a,b,c) { a + b + c }') end it 'autocorrects when a stabby lambda has no parentheses' do corrected = autocorrect_source(['->a,b,c { a + b + c }']) expect(corrected).to eq '->(a,b,c) { a + b + c }' end end context 'require_no_parentheses' do let(:cop_config) { { 'EnforcedStyle' => 'require_no_parentheses' } } it_behaves_like 'common' it 'registers an offense for a stabby lambda with parentheses' do expect_offense(<<-RUBY.strip_indent) ->(a,b,c) { a + b + c } ^^^^^^^ Do not wrap stabby lambda arguments with parentheses. RUBY end it 'autocorrects when a stabby lambda does not parentheses' do corrected = autocorrect_source(['->(a,b,c) { a + b + c }']) expect(corrected).to eq '->a,b,c { a + b + c }' end end end rubocop-0.52.1/spec/rubocop/cop/style/stderr_puts_spec.rb000066400000000000000000000010721322072016200235040ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StderrPuts do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it "registers an offense when using `$stderr.puts('hello')`" do expect_offense(<<-RUBY.strip_indent) $stderr.puts('hello') ^^^^^^^^^^^^ Use `warn` instead of `$stderr.puts` to allow such output to be disabled. RUBY end it "autocorrects `warn('hello')`" do new_source = autocorrect_source("$stderr.puts('hello')") expect(new_source).to eq "warn('hello')" end end rubocop-0.52.1/spec/rubocop/cop/style/string_hash_keys_spec.rb000066400000000000000000000024551322072016200245000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StringHashKeys do subject(:cop) { described_class.new(config) } let(:config) { RuboCop::Config.new } it 'registers an offense when using strings as keys' do expect_offense(<<-RUBY.strip_indent) { 'one' => 1 } ^^^^^ Prefer symbols instead of strings as hash keys. RUBY end it 'registers an offense when using strings as keys mixed with other keys' do expect_offense(<<-RUBY.strip_indent) { 'one' => 1, two: 2, 3 => 3 } ^^^^^ Prefer symbols instead of strings as hash keys. RUBY end it 'autocorrects strings as keys into symbols' do new_source = autocorrect_source("{ 'one' => 1 }") expect(new_source).to eq '{ :one => 1 }' end it 'autocorrects strings as keys mixed with other keys into symbols' do new_source = autocorrect_source("{ 'one' => 1, two: 2, 3 => 3 }") expect(new_source).to eq '{ :one => 1, two: 2, 3 => 3 }' end it 'autocorrects strings as keys into symbols with the correct syntax' do new_source = autocorrect_source("{ 'one two :' => 1 }") expect(new_source).to eq '{ :"one two :" => 1 }' end it 'does not register an offense when not using strings as keys' do expect_no_offenses(<<-RUBY.strip_indent) { one: 1 } RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb000066400000000000000000000051511322072016200277720ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StringLiteralsInInterpolation, :config do subject(:cop) { described_class.new(config) } context 'configured with single quotes preferred' do let(:cop_config) { { 'EnforcedStyle' => 'single_quotes' } } it 'registers an offense for double quotes within embedded expression' do src = '"#{"A"}"' inspect_source(src) expect(cop.messages) .to eq(['Prefer single-quoted strings inside interpolations.']) end it 'registers an offense for double quotes within embedded expression in ' \ 'a heredoc string' do src = ['< 'double_quotes' } } it 'registers an offense for single quotes within embedded expression' do src = %q("#{'A'}") inspect_source(src) expect(cop.messages) .to eq(['Prefer double-quoted strings inside interpolations.']) end it 'registers an offense for single quotes within embedded expression in ' \ 'a heredoc string' do src = ['< 'other' } } it 'fails' do expect { inspect_source('a = "#{"b"}"') } .to raise_error(RuntimeError) end end end rubocop-0.52.1/spec/rubocop/cop/style/string_literals_spec.rb000066400000000000000000000273251322072016200243440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StringLiterals, :config do subject(:cop) { described_class.new(config) } context 'configured with single quotes preferred' do let(:cop_config) { { 'EnforcedStyle' => 'single_quotes' } } it 'registers offense for double quotes when single quotes suffice' do inspect_source(['s = "abc"', 'x = "a\\\\b"', 'y ="\\\\b"', 'z = "a\\\\"']) expect(cop.highlights).to eq(['"abc"', '"a\\\\b"', '"\\\\b"', '"a\\\\"']) expect(cop.messages) .to eq(["Prefer single-quoted strings when you don't need " \ 'string interpolation or special symbols.'] * 4) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'double_quotes') end it 'registers offense for correct + opposite' do expect_offense(<<-RUBY.strip_indent) s = "abc" ^^^^^ Prefer single-quoted strings when you don't need string interpolation or special symbols. x = 'abc' RUBY end it 'accepts single quotes' do expect_no_offenses("a = 'x'") end it 'accepts single quotes in interpolation' do expect_no_offenses(%q("hello#{hash['there']}")) end it 'accepts %q and %Q quotes' do expect_no_offenses('a = %q(x) + %Q[x]') end it 'accepts % quotes' do expect_no_offenses('a = %(x)') end it 'accepts heredocs' do expect_no_offenses(<<-RUBY.strip_indent) execute <<-SQL SELECT name from users SQL RUBY end it 'accepts double quotes when new line is used' do expect_no_offenses('"\n"') end it 'accepts double quotes when interpolating & quotes in multiple lines' do expect_no_offenses(<<-'RUBY'.strip_indent) "#{encode_severity}:#{sprintf('%3d', line_number)}: #{m}" RUBY end it 'accepts double quotes when single quotes are used' do expect_no_offenses('"\'"') end it 'accepts double quotes when interpolating an instance variable' do expect_no_offenses('"#@test"') end it 'accepts double quotes when interpolating a global variable' do expect_no_offenses('"#$test"') end it 'accepts double quotes when interpolating a class variable' do expect_no_offenses('"#@@test"') end it 'accepts double quotes when control characters are used' do expect_no_offenses('"\e"') end it 'accepts double quotes when unicode control sequence is used' do expect_no_offenses('"Espa\u00f1a"') end it 'accepts double quotes at the start of regexp literals' do expect_no_offenses('s = /"((?:[^\\"]|\\.)*)"/') end it 'accepts double quotes with some other special symbols' do # "Substitutions in double-quoted strings" # http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html expect_no_offenses(<<-'RUBY'.strip_indent) g = "\xf9" copyright = "\u00A9" RUBY end it 'accepts " in a %w' do expect_no_offenses('%w(")') end it 'accepts \\\\\n in a string' do # this would be: "\\\n" expect_no_offenses('"foo \\\\\n bar"') end it 'accepts double quotes in interpolation' do expect_no_offenses("\"\#{\"A\"}\"") end it 'detects unneeded double quotes within concatenated string' do src = ['"#{x}" \\', '"y"'] inspect_source(src) expect(cop.offenses.size).to eq(1) end it 'can handle a built-in constant parsed as string' do # Parser will produce str nodes for constants such as __FILE__. expect_no_offenses(<<-RUBY.strip_indent) if __FILE__ == $PROGRAM_NAME end RUBY end it 'can handle character literals' do expect_no_offenses('a = ?/') end it 'auto-corrects " with \'' do new_source = autocorrect_source('s = "abc"') expect(new_source).to eq("s = 'abc'") end it 'registers an offense for "\""' do expect_offense(<<-'RUBY'.strip_indent) "\"" ^^^^ Prefer single-quoted strings when you don't need string interpolation or special symbols. RUBY end it 'registers an offense for words with non-ascii chars' do expect_offense(<<-RUBY.strip_indent) "España" ^^^^^^^^ Prefer single-quoted strings when you don't need string interpolation or special symbols. RUBY end it 'autocorrects words with non-ascii chars' do new_source = autocorrect_source('"España"') expect(new_source).to eq("'España'") end it 'does not register an offense for words with non-ascii chars and ' \ 'other control sequences' do inspect_source('"España\n"') expect(cop.offenses.size).to eq(0) end it 'does not autocorrect words with non-ascii chars and other control ' \ 'sequences' do new_source = autocorrect_source('"España\n"') expect(new_source).to eq('"España\n"') end end context 'configured with double quotes preferred' do let(:cop_config) { { 'EnforcedStyle' => 'double_quotes' } } it 'registers offense for single quotes when double quotes would ' \ 'be equivalent' do expect_offense(<<-RUBY.strip_indent) s = 'abc' ^^^^^ Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. RUBY expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'single_quotes') end it 'registers offense for opposite + correct' do expect_offense(<<-'RUBY'.strip_indent) s = "abc" x = 'abc' ^^^^^ Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. RUBY expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it 'registers offense for escaped single quote in single quotes' do expect_offense(<<-'RUBY'.strip_indent) '\'' ^^^^ Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. RUBY end it 'does not accept multiple escaped single quotes in single quotes' do expect_offense(<<-'RUBY'.strip_indent) 'This \'string\' has \'multiple\' escaped quotes' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. RUBY end it 'accepts double quotes' do expect_no_offenses('a = "x"') end it 'accepts single quotes in interpolation' do expect_no_offenses(%q("hello#{hash['there']}")) end it 'accepts %q and %Q quotes' do expect_no_offenses('a = %q(x) + %Q[x]') end it 'accepts % quotes' do expect_no_offenses('a = %(x)') end it 'accepts heredocs' do expect_no_offenses(<<-RUBY.strip_indent) execute <<-SQL SELECT name from users SQL RUBY end it 'accepts single quotes in string with escaped non-\' character' do expect_no_offenses(%q('\n')) end it 'accepts escaped single quote in string with escaped non-\' character' do expect_no_offenses(%q('\'\n')) end it 'accepts single quotes when they are needed' do expect_no_offenses(<<-'RUBY'.strip_indent) a = '\n' b = '"' c = '#{x}' RUBY end it 'flags single quotes with plain # (not #@var or #{interpolation}' do inspect_source("a = 'blah #'") expect(cop.offenses.size).to be 1 end it 'accepts single quotes at the start of regexp literals' do expect_no_offenses("s = /'((?:[^\\']|\\.)*)'/") end it "accepts ' in a %w" do expect_no_offenses("%w(')") end it 'can handle a built-in constant parsed as string' do # Parser will produce str nodes for constants such as __FILE__. expect_no_offenses(<<-RUBY.strip_indent) if __FILE__ == $PROGRAM_NAME end RUBY end it "auto-corrects ' with \"" do new_source = autocorrect_source("s = 'abc'") expect(new_source).to eq('s = "abc"') end end context 'when configured with a bad value' do let(:cop_config) { { 'EnforcedStyle' => 'other' } } it 'fails' do expect { inspect_source('a = "b"') } .to raise_error(RuntimeError) end end context 'when ConsistentQuotesInMultiline is true' do context 'and EnforcedStyle is single_quotes' do let(:cop_config) do { 'ConsistentQuotesInMultiline' => true, 'EnforcedStyle' => 'single_quotes' } end it 'registers an offense for strings with line breaks in them' do expect_offense(<<-'RUBY'.strip_indent) "-- ^^^ Prefer single-quoted strings when you don't need string interpolation or special symbols. SELECT * LEFT JOIN X on Y FROM Models" RUBY end it 'accepts continued strings using all single quotes' do expect_no_offenses(<<-RUBY.strip_indent) 'abc' \ 'def' RUBY end it 'registers an offense for mixed quote styles in a continued string' do expect_offense(<<-'RUBY'.strip_indent) 'abc' \ ^^^^^^^ Inconsistent quote style. "def" RUBY end it 'registers an offense for unneeded double quotes in continuation' do expect_offense(<<-'RUBY'.strip_indent) "abc" \ ^^^^^^^ Prefer single-quoted strings when you don't need string interpolation or special symbols. "def" RUBY end it "doesn't register offense for double quotes with interpolation" do expect_no_offenses(<<-'RUBY'.strip_indent) "abc" \ "def#{1}" RUBY end it "doesn't register offense for double quotes with embedded single" do expect_no_offenses(<<-RUBY.strip_indent) "abc'" \ "def" RUBY end it 'accepts for double quotes with an escaped special character' do expect_no_offenses(<<-'RUBY'.strip_indent) "abc\t" \ "def" RUBY end it 'accepts for double quotes with an escaped normal character' do expect_no_offenses(<<-'RUBY'.strip_indent) "abc\!" \ "def" RUBY end it "doesn't choke on heredocs with inconsistent indentation" do expect_no_offenses(<<-RUBY.strip_indent) <<-QUERY_STRING DEFINE BLAH QUERY_STRING RUBY end end context 'and EnforcedStyle is double_quotes' do let(:cop_config) do { 'ConsistentQuotesInMultiline' => true, 'EnforcedStyle' => 'double_quotes' } end it 'accepts continued strings using all double quotes' do expect_no_offenses(<<-RUBY.strip_indent) "abc" \ "def" RUBY end it 'registers an offense for mixed quote styles in a continued string' do expect_offense(<<-'RUBY'.strip_indent) 'abc' \ ^^^^^^^ Inconsistent quote style. "def" RUBY end it 'registers an offense for unneeded single quotes in continuation' do expect_offense(<<-'RUBY'.strip_indent) 'abs' \ ^^^^^^^ Prefer double-quoted strings unless you need single quotes to avoid extra backslashes for escaping. 'def' RUBY end it "doesn't register offense for single quotes with embedded double" do expect_no_offenses(<<-RUBY.strip_indent) 'abc"' \ 'def' RUBY end end end end rubocop-0.52.1/spec/rubocop/cop/style/string_methods_spec.rb000066400000000000000000000010501322072016200241530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StringMethods, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'intern' => 'to_sym' } } let(:source) { "'something'.intern" } let(:corrected) { autocorrect_source(source) } it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Prefer `to_sym` over `intern`.']) expect(cop.highlights).to eq(%w[intern]) expect(corrected).to eq("'something'.to_sym") end end rubocop-0.52.1/spec/rubocop/cop/style/struct_inheritance_spec.rb000066400000000000000000000022071322072016200250240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::StructInheritance do subject(:cop) { described_class.new } it 'registers an offense when extending instance of Struct' do expect_offense(<<-RUBY.strip_indent) class Person < Struct.new(:first_name, :last_name) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't extend an instance initialized by `Struct.new`. end RUBY end it 'registers an offense when extending instance of Struct with do ... end' do expect_offense(<<-RUBY.strip_indent) class Person < Struct.new(:first_name, :last_name) do end ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Don't extend an instance initialized by `Struct.new`. end RUBY end it 'accepts plain class' do expect_no_offenses(<<-RUBY.strip_indent) class Person end RUBY end it 'accepts extending DelegateClass' do expect_no_offenses(<<-RUBY.strip_indent) class Person < DelegateClass(Animal) end RUBY end it 'accepts assignment to Struct.new' do expect_no_offenses('Person = Struct.new(:first_name, :last_name)') end end rubocop-0.52.1/spec/rubocop/cop/style/symbol_array_spec.rb000066400000000000000000000107001322072016200236270ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SymbolArray, :config do subject(:cop) { described_class.new(config) } before do # Reset data which is shared by all instances of SymbolArray described_class.largest_brackets = -Float::INFINITY end let(:other_cops) do { 'Style/PercentLiteralDelimiters' => { 'PreferredDelimiters' => { 'default' => '()' } } } end context 'when EnforcedStyle is percent' do let(:cop_config) do { 'MinSize' => 0, 'EnforcedStyle' => 'percent' } end it 'registers an offense for arrays of symbols' do inspect_source('[:one, :two, :three]') expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%i` or `%I` for an array of symbols.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'brackets') end it 'autocorrects arrays of symbols' do new_source = autocorrect_source('[:one, :two, :three]') expect(new_source).to eq('%i(one two three)') end it 'autocorrects arrays of symbols with new line' do new_source = autocorrect_source("[:one,\n:two, :three,\n:four]") expect(new_source).to eq("%i(one \ntwo three \nfour)") end it 'uses %I when appropriate' do new_source = autocorrect_source('[:"\\t", :"\\n", :three]') expect(new_source).to eq('%I(\\t \\n three)') end it "doesn't break when a symbol contains )" do source = '[:one, :")", :three, :"(", :"]", :"["]' new_source = autocorrect_source(source) expect(new_source).to eq('%i(one \\) three \\( ] [)') end it 'does not register an offense for array with non-syms' do expect_no_offenses('[:one, :two, "three"]') end it 'does not register an offense for array starting with %i' do expect_no_offenses('%i(one two three)') end it 'does not register an offense for array with one element' do expect_no_offenses('[:three]') end it 'does not register an offense if symbol contains whitespace' do expect_no_offenses('[:one, :two, :"space here"]') end # Bug: https://github.com/bbatsov/rubocop/issues/4481 it 'does not register an offense in an ambiguous block context' do expect_no_offenses('foo [:bar, :baz] { qux }') end it 'registers an offense in a non-ambiguous block context' do expect_offense(<<-RUBY.strip_indent) foo([:bar, :baz]) { qux } ^^^^^^^^^^^^ Use `%i` or `%I` for an array of symbols. RUBY end it 'detects right value for MinSize to use for --auto-gen-config' do inspect_source(<<-RUBY.strip_indent) [:one, :two, :three] %i(a b c d) RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%i` or `%I` for an array of symbols.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'percent', 'MinSize' => 4) end it 'detects when the cop must be disabled to avoid offenses' do inspect_source(<<-RUBY.strip_indent) [:one, :two, :three] %i(a b) RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%i` or `%I` for an array of symbols.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end context 'when PreferredDelimiters is specified' do let(:other_cops) do { 'Style/PercentLiteralDelimiters' => { 'PreferredDelimiters' => { 'default' => '[]' } } } end it 'autocorrects an array with delimiters' do source = '[:one, :")", :three, :"(", :"]", :"["]' new_source = autocorrect_source(source) expect(new_source).to eq('%i[one ) three ( \\] \\[]') end end end context 'when EnforcedStyle is array' do let(:cop_config) { { 'EnforcedStyle' => 'brackets', 'MinSize' => 0 } } it 'does not register an offense for arrays of symbols' do expect_no_offenses('[:one, :two, :three]') end it 'registers an offense for array starting with %i' do expect_offense(<<-RUBY.strip_indent) %i(one two three) ^^^^^^^^^^^^^^^^^ Use `[]` for an array of symbols. RUBY end it 'autocorrects an array starting with %i' do new_source = autocorrect_source('%i(one @two $three four-five)') expect(new_source).to eq("[:one, :@two, :$three, :'four-five']") end end end rubocop-0.52.1/spec/rubocop/cop/style/symbol_literal_spec.rb000066400000000000000000000016001322072016200241440ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SymbolLiteral do subject(:cop) { described_class.new } it 'registers an offense for word-line symbols using string syntax' do expect_offense(<<-RUBY.strip_indent) x = { :"test" => 0 } ^^^^^^^ Do not use strings for word-like symbol literals. RUBY end it 'accepts string syntax when symbols have whitespaces in them' do expect_no_offenses('x = { :"t o" => 0 }') end it 'accepts string syntax when symbols have special chars in them' do expect_no_offenses('x = { :"\\tab" => 1 }') end it 'accepts string syntax when symbol start with a digit' do expect_no_offenses('x = { :"1" => 1 }') end it 'auto-corrects by removing quotes' do new_source = autocorrect_source('{ :"ala" => 1, :"bala" => 2 }') expect(new_source).to eq('{ :ala => 1, :bala => 2 }') end end rubocop-0.52.1/spec/rubocop/cop/style/symbol_proc_spec.rb000066400000000000000000000106261322072016200234630ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::SymbolProc, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'IgnoredMethods' => %w[respond_to] } } it 'registers an offense for a block with parameterless method call on ' \ 'param' do inspect_source('coll.map { |e| e.upcase }') expect(cop.offenses.size).to eq(1) expect(cop.messages) .to eq(['Pass `&:upcase` as an argument to `map` instead of a block.']) expect(cop.highlights).to eq(['{ |e| e.upcase }']) end it 'registers an offense for a block when method in body is unary -/=' do expect_offense(<<-RUBY.strip_indent) something.map { |x| -x } ^^^^^^^^^^ Pass `&:-@` as an argument to `map` instead of a block. RUBY end it 'accepts block with more than 1 arguments' do expect_no_offenses('something { |x, y| x.method }') end it 'accepts lambda with 1 argument' do expect_no_offenses('->(x) { x.method }') end it 'accepts proc with 1 argument' do expect_no_offenses('proc { |x| x.method }') end it 'accepts Proc.new with 1 argument' do expect_no_offenses('Proc.new { |x| x.method }') end it 'accepts ignored method' do expect_no_offenses('respond_to { |format| format.xml }') end it 'accepts block with no arguments' do expect_no_offenses('something { x.method }') end it 'accepts empty block body' do expect_no_offenses('something { |x| }') end it 'accepts block with more than 1 expression in body' do expect_no_offenses('something { |x| x.method; something_else }') end it 'accepts block when method in body is not called on block arg' do expect_no_offenses('something { |x| y.method }') end it 'accepts block with a block argument ' do expect_no_offenses('something { |&x| x.call }') end it 'accepts block with splat params' do expect_no_offenses('something { |*x| x.first }') end context 'when the method has arguments' do let(:source) { 'method(one, 2) { |x| x.test }' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) method(one, 2) { |x| x.test } ^^^^^^^^^^^^^^ Pass `&:test` as an argument to `method` instead of a block. RUBY end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq 'method(one, 2, &:test)' end end it 'autocorrects alias with symbols as proc' do corrected = autocorrect_source(['coll.map { |s| s.upcase }']) expect(corrected).to eq 'coll.map(&:upcase)' end it 'autocorrects multiple aliases with symbols as proc' do corrected = autocorrect_source(['coll.map { |s| s.upcase }' \ '.map { |s| s.downcase }']) expect(corrected).to eq 'coll.map(&:upcase).map(&:downcase)' end it 'auto-corrects correctly when there are no arguments in parentheses' do corrected = autocorrect_source(['coll.map( ) { |s| s.upcase }']) expect(corrected).to eq 'coll.map(&:upcase)' end it 'does not crash with a bare method call' do run = -> { inspect_source('coll.map { |s| bare_method }') } expect(&run).not_to raise_error end context 'when `super` has arguments' do let(:source) { 'super(one, two) { |x| x.test }' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) super(one, two) { |x| x.test } ^^^^^^^^^^^^^^ Pass `&:test` as an argument to `super` instead of a block. RUBY end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq 'super(one, two, &:test)' end end context 'when `super` has no arguments' do let(:source) { 'super { |x| x.test }' } it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) super { |x| x.test } ^^^^^^^^^^^^^^ Pass `&:test` as an argument to `super` instead of a block. RUBY end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq 'super(&:test)' end end it 'auto-corrects correctly when args have a trailing comma' do corrected = autocorrect_source(<<-RUBY.strip_indent) mail( to: 'foo', subject: 'bar', ) { |format| format.text } RUBY expect(corrected).to eq(<<-RUBY.strip_indent) mail( to: 'foo', subject: 'bar', &:text ) RUBY end end rubocop-0.52.1/spec/rubocop/cop/style/ternary_parentheses_spec.rb000066400000000000000000000272151322072016200252220ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TernaryParentheses, :config do subject(:cop) { described_class.new(config) } before do inspect_source(source) end let(:redundant_parens_enabled) { false } let(:other_cops) do { 'Style/RedundantParentheses' => { 'Enabled' => redundant_parens_enabled } } end shared_examples 'code with offense' do |code, expected| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq([message]) end if expected it 'auto-corrects' do expect(autocorrect_source(code)).to eq(expected) end it 'claims to auto-correct' do autocorrect_source(code) expect(cop.offenses.last.status).to eq(:corrected) end else it 'does not auto-correct' do expect(autocorrect_source(code)).to eq(code) end it 'does not claim to auto-correct' do autocorrect_source(code) expect(cop.offenses.last.status).to eq(:uncorrected) end end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end shared_examples 'safe assignment disabled' do |style| let(:cop_config) do { 'EnforcedStyle' => style, 'AllowSafeAssignment' => false } end it_behaves_like 'code with offense', 'foo = (bar = find_bar) ? a : b' it_behaves_like 'code with offense', 'foo = bar = (baz = find_baz) ? a : b' it_behaves_like 'code with offense', 'foo = (bar = baz = find_baz) ? a : b' end context 'when configured to enforce parentheses inclusion' do let(:cop_config) { { 'EnforcedStyle' => 'require_parentheses' } } let(:message) { 'Use parentheses for ternary conditions.' } context 'with a simple condition' do it_behaves_like 'code with offense', 'foo = bar? ? a : b', 'foo = (bar?) ? a : b' it_behaves_like 'code with offense', 'foo = yield ? a : b', 'foo = (yield) ? a : b' it_behaves_like 'code with offense', 'foo = bar[:baz] ? a : b', 'foo = (bar[:baz]) ? a : b' end context 'with a complex condition' do it_behaves_like 'code with offense', 'foo = 1 + 1 == 2 ? a : b', 'foo = (1 + 1 == 2) ? a : b' it_behaves_like 'code with offense', 'foo = bar && baz ? a : b', 'foo = (bar && baz) ? a : b' it_behaves_like 'code with offense', 'foo = foo1 == foo2 ? a : b', 'foo = (foo1 == foo2) ? a : b' it_behaves_like 'code with offense', 'foo = bar.baz? ? a : b', 'foo = (bar.baz?) ? a : b' it_behaves_like 'code with offense', 'foo = bar && (baz || bar) ? a : b', 'foo = (bar && (baz || bar)) ? a : b' end context 'with an assignment condition' do it_behaves_like 'code with offense', 'foo = bar = baz ? a : b', 'foo = bar = (baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar = baz = find_baz ? a : b', 'foo = bar = baz = (find_baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar = baz == 1 ? a : b', 'foo = bar = (baz == 1) ? a : b' it_behaves_like 'code without offense', 'foo = (bar = baz = find_baz) ? a : b' end end context 'when configured to enforce parentheses omission' do let(:cop_config) { { 'EnforcedStyle' => 'require_no_parentheses' } } let(:message) { 'Omit parentheses for ternary conditions.' } context 'with a simple condition' do it_behaves_like 'code with offense', 'foo = (bar?) ? a : b', 'foo = bar? ? a : b' it_behaves_like 'code with offense', 'foo = (yield) ? a : b', 'foo = yield ? a : b' it_behaves_like 'code with offense', 'foo = (bar[:baz]) ? a : b', 'foo = bar[:baz] ? a : b' end context 'with a complex condition' do it_behaves_like 'code with offense', 'foo = (1 + 1 == 2) ? a : b', 'foo = 1 + 1 == 2 ? a : b' it_behaves_like 'code with offense', 'foo = (foo1 == foo2) ? a : b' it_behaves_like 'code with offense', 'foo = (bar && baz) ? a : b', 'foo = bar && baz ? a : b' it_behaves_like 'code with offense', 'foo = (bar.baz?) ? a : b', 'foo = bar.baz? ? a : b' it_behaves_like 'code without offense', 'foo = bar && (baz || bar) ? a : b' end context 'with an assignment condition' do it_behaves_like 'code without offense', 'foo = (bar = find_bar) ? a : b' it_behaves_like 'code without offense', 'foo = bar = (baz = find_baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar = (baz == 1) ? a : b', 'foo = bar = baz == 1 ? a : b' it_behaves_like 'code without offense', 'foo = (bar = baz = find_baz) ? a : b' it_behaves_like 'safe assignment disabled', 'require_no_parentheses' end context 'with an unparenthesized method call condition' do it_behaves_like 'code with offense', 'foo = (defined? bar) ? a : b' it_behaves_like 'code with offense', 'foo = (baz? bar) ? a : b' context 'when calling method on a receiver' do it_behaves_like 'code with offense', 'foo = (baz.foo? bar) ? a : b' end context 'when calling method on a literal receiver' do it_behaves_like 'code with offense', 'foo = ("bar".foo? bar) ? a : b' end context 'when calling method on a constant receiver' do it_behaves_like 'code with offense', 'foo = (Bar.foo? bar) ? a : b' end context 'when calling method with multiple arguments' do it_behaves_like 'code with offense', 'foo = (baz.foo? bar, baz) ? a : b' end end context 'with condition including a range' do it_behaves_like 'code without offense', '(foo..bar).include?(baz) ? a : b' end context 'with no space between the parentheses and question mark' do it_behaves_like 'code with offense', '(foo)? a : b', 'foo ? a : b' end end context 'configured for parentheses on complex and there are parens' do let(:cop_config) do { 'EnforcedStyle' => 'require_parentheses_when_complex' } end let(:message) do 'Only use parentheses for ternary expressions with complex conditions.' end context 'with a simple condition' do it_behaves_like 'code with offense', 'foo = (bar?) ? a : b', 'foo = bar? ? a : b' it_behaves_like 'code with offense', 'foo = (yield) ? a : b', 'foo = yield ? a : b' it_behaves_like 'code with offense', 'foo = (bar[:baz]) ? a : b', 'foo = bar[:baz] ? a : b' end context 'with a complex condition' do it_behaves_like 'code with offense', 'foo = (bar.baz?) ? a : b', 'foo = bar.baz? ? a : b' it_behaves_like 'code without offense', 'foo = (bar && (baz || bar)) ? a : b' end context 'with an assignment condition' do it_behaves_like 'code without offense', 'foo = (bar = find_bar) ? a : b' it_behaves_like 'code without offense', 'foo = baz = (bar = find_bar) ? a : b' it_behaves_like 'code without offense', 'foo = bar = (bar == 1) ? a : b' it_behaves_like 'code without offense', 'foo = (bar = baz = find_bar) ? a : b' it_behaves_like 'safe assignment disabled', 'require_parentheses_when_complex' end context 'with method call condition' do it_behaves_like 'code with offense', 'foo = (defined? bar) ? a : b' it_behaves_like 'code with offense', 'foo = (baz? bar) ? a : b' context 'when calling method on a receiver' do it_behaves_like 'code with offense', 'foo = (baz.foo? bar) ? a : b' end end context 'with condition including a range' do it_behaves_like 'code without offense', '(foo..bar).include?(baz) ? a : b' end end context 'configured for parentheses on complex and there are no parens' do let(:cop_config) do { 'EnforcedStyle' => 'require_parentheses_when_complex' } end let(:message) do 'Use parentheses for ternary expressions with complex conditions.' end context 'with complex condition' do it_behaves_like 'code with offense', 'foo = 1 + 1 == 2 ? a : b', 'foo = (1 + 1 == 2) ? a : b' it_behaves_like 'code with offense', 'foo = bar && baz ? a : b', 'foo = (bar && baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar && baz || bar ? a : b', 'foo = (bar && baz || bar) ? a : b' it_behaves_like 'code with offense', 'foo = bar && (baz != bar) ? a : b', 'foo = (bar && (baz != bar)) ? a : b' it_behaves_like 'code with offense', 'foo = 1 < (bar.baz?) ? a : b', 'foo = (1 < (bar.baz?)) ? a : b' it_behaves_like 'code with offense', 'foo = 1 <= (bar ** baz) ? a : b', 'foo = (1 <= (bar ** baz)) ? a : b' it_behaves_like 'code with offense', 'foo = 1 >= bar * baz ? a : b', 'foo = (1 >= bar * baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar + baz ? a : b', 'foo = (bar + baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar - baz ? a : b', 'foo = (bar - baz) ? a : b' it_behaves_like 'code with offense', 'foo = bar < baz ? a : b', 'foo = (bar < baz) ? a : b' end context 'with an assignment condition' do it_behaves_like 'code with offense', 'foo = bar = baz == 1 ? a : b', 'foo = bar = (baz == 1) ? a : b' it_behaves_like 'code without offense', 'foo = (bar = baz == 1) ? a : b' end end context 'when `RedundantParenthesis` would cause an infinite loop' do let(:redundant_parens_enabled) { true } let(:cop_config) do { 'EnforcedStyle' => 'require_parentheses', 'SupportedStyles' => %w[require_parentheses require_no_parentheses] } end it_behaves_like 'code without offense', 'foo = bar? ? a : b' end end rubocop-0.52.1/spec/rubocop/cop/style/trailing_body_on_method_definition_spec.rb000066400000000000000000000113631322072016200302240ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrailingBodyOnMethodDefinition do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end it 'registers an offense when body trails after method definition' do expect_offense(<<-RUBY.strip_indent) def some_method; body ^^^^ Place the first line of a multi-line method definition's body on its own line. end def extra_large; { size: 15 }; ^^^^^^^^^^^^ Place the first line of a multi-line method definition's body on its own line. end def seven_times(stuff) 7.times { do_this(stuff) } ^^^^^^^^^^^^^^^^^^^^^^^^^^ Place the first line of a multi-line method definition's body on its own line. end RUBY end it 'registers when body starts on def line & continues one more line' do expect_offense(<<-RUBY.strip_indent) def some_method; foo = {} ^^^^^^^^ Place the first line of a multi-line method definition's body on its own line. more_body(foo) end RUBY end it 'registers when body starts on def line & continues many more lines' do expect_offense(<<-RUBY.strip_indent) def do_stuff(thing) process(thing) ^^^^^^^^^^^^^^ Place the first line of a multi-line method definition's body on its own line. 8.times { thing + 9 } even_more(thing) end RUBY end it 'accepts a method with one line of body' do expect_no_offenses(<<-RUBY.strip_indent) def some_method body end RUBY end it 'accepts a method with multiple lines of body' do expect_no_offenses(<<-RUBY.strip_indent) def stuff_method stuff 9.times { process(stuff) } more_stuff end RUBY end it 'does not register offense with trailing body on method end' do expect_no_offenses(<<-RUBY.strip_indent) def some_method body foo; end RUBY end it 'auto-corrects body after method definition' do corrected = autocorrect_source([' def some_method; body', ' end'].join("\n")) expect(corrected).to eq [' def some_method ', ' body', ' end'].join("\n") end it 'auto-corrects with comment after body' do corrected = autocorrect_source([' def some_method; body # stuff', ' end'].join("\n")) expect(corrected).to eq [' # stuff', ' def some_method ', ' body ', ' end'].join("\n") end it 'auto-corrects body with method definition with args in parens' do corrected = autocorrect_source([' def some_method(arg1, arg2) body', ' end'].join("\n")) expect(corrected).to eq [' def some_method(arg1, arg2) ', ' body', ' end'].join("\n") end it 'auto-corrects body with method definition with args not in parens' do corrected = autocorrect_source([' def some_method arg1, arg2; body', ' end'].join("\n")) expect(corrected).to eq [' def some_method arg1, arg2 ', ' body', ' end'].join("\n") end it 'auto-correction removes semicolon from method definition but not body' do corrected = autocorrect_source([' def some_method; body; more_body;', ' end'].join("\n")) expect(corrected).to eq [' def some_method ', ' body; more_body;', ' end'].join("\n") end it 'auto-corrects when body continues on one more line' do corrected = autocorrect_source([' def some_method; body', ' more_body', ' end'].join("\n")) expect(corrected).to eq [' def some_method ', ' body', ' more_body', ' end'].join("\n") end it 'auto-corrects when body continues on multiple more line' do corrected = autocorrect_source([' def some_method; []', ' more_body', ' even_more', ' end'].join("\n")) expect(corrected).to eq [' def some_method ', ' []', ' more_body', ' even_more', ' end'].join("\n") end end rubocop-0.52.1/spec/rubocop/cop/style/trailing_comma_in_arguments_spec.rb000066400000000000000000000273731322072016200267020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrailingCommaInArguments, :config do subject(:cop) { described_class.new(config) } shared_examples 'single line lists' do |extra_info| it 'registers an offense for trailing comma in a method call' do inspect_source('some_method(a, b, c, )') expect(cop.messages) .to eq(['Avoid comma after the last parameter of a method ' \ "call#{extra_info}."]) expect(cop.highlights).to eq([',']) end it 'registers an offense for trailing comma in a method call with hash' \ ' parameters at the end' do inspect_source('some_method(a, b, c: 0, d: 1, )') expect(cop.messages) .to eq(['Avoid comma after the last parameter of a method ' \ "call#{extra_info}."]) expect(cop.highlights).to eq([',']) end it 'accepts method call without trailing comma' do expect_no_offenses('some_method(a, b, c)') end it 'accepts method call without trailing comma with single element hash' \ ' parameters at the end' do inspect_source('some_method(a: 1)') expect(cop.offenses.empty?).to be(true) end it 'accepts method call without parameters' do expect_no_offenses('some_method') end it 'accepts chained single-line method calls' do expect_no_offenses(<<-RUBY.strip_indent) target .some_method(a) RUBY end it 'auto-corrects unwanted comma in a method call' do new_source = autocorrect_source('some_method(a, b, c, )') expect(new_source).to eq('some_method(a, b, c )') end it 'auto-corrects unwanted comma in a method call with hash parameters at' \ ' the end' do new_source = autocorrect_source('some_method(a, b, c: 0, d: 1, )') expect(new_source).to eq('some_method(a, b, c: 0, d: 1 )') end end context 'with single line list of values' do context 'when EnforcedStyleForMultiline is no_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } } include_examples 'single line lists', '' end context 'when EnforcedStyleForMultiline is comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } } include_examples 'single line lists', ', unless each item is on its own line' end context 'when EnforcedStyleForMultiline is consistent_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'consistent_comma' } } include_examples 'single line lists', ', unless items are split onto multiple lines' end end context 'with multi-line list of values' do context 'when EnforcedStyleForMultiline is no_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } } it 'registers an offense for trailing comma in a method call with ' \ 'hash parameters at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1,) RUBY expect(cop.highlights).to eq([',']) end it 'accepts a method call with ' \ 'hash parameters at the end and no trailing comma' do inspect_source(<<-RUBY.strip_indent) some_method(a, b, c: 0, d: 1 ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts comma inside a heredoc parameter at the end' do expect_no_offenses(<<-RUBY.strip_indent) route(help: { 'auth' => <<-HELP.chomp , HELP }) RUBY end it 'auto-corrects unwanted comma in a method call with hash parameters' \ ' at the end' do new_source = autocorrect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1,) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1) RUBY end end context 'when EnforcedStyleForMultiline is comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } } context 'when closing bracket is on same line as last value' do it 'accepts a method call with Hash as last parameter split on ' \ 'multiple lines' do inspect_source(<<-RUBY.strip_indent) some_method(a: "b", c: "d") RUBY expect(cop.offenses.empty?).to be(true) end end it 'registers an offense for no trailing comma in a method call with' \ ' hash parameters at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1 ) RUBY expect(cop.messages) .to eq(['Put a comma after the last parameter of a multiline ' \ 'method call.']) expect(cop.highlights).to eq(['d: 1']) end it 'accepts a method call with two parameters on the same line' do expect_no_offenses(<<-RUBY.strip_indent) some_method(a, b ) RUBY end it 'accepts trailing comma in a method call with hash' \ ' parameters at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1, ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts no trailing comma in a method call with a multiline' \ ' braceless hash at the end with more than one parameter on a line' do inspect_source(<<-RUBY.strip_indent) some_method( a, b: 0, c: 0, d: 1 ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a trailing comma in a method call with single ' \ 'line hashes' do inspect_source(<<-RUBY.strip_indent) some_method( { a: 0, b: 1 }, { a: 1, b: 0 }, ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts an empty hash being passed as a method argument' do expect_no_offenses(<<-RUBY.strip_indent) Foo.new([ ]) RUBY end it 'auto-corrects missing comma in a method call with hash parameters' \ ' at the end' do new_source = autocorrect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1 ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1, ) RUBY end it 'accepts a multiline call with a single argument and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) method( 1, ) RUBY end end context 'when EnforcedStyleForMultiline is consistent_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'consistent_comma' } } context 'when closing bracket is on same line as last value' do it 'registers an offense for a method call, with a Hash as the ' \ 'last parameter, split on multiple lines' do inspect_source(<<-RUBY.strip_indent) some_method(a: "b", c: "d") RUBY expect(cop.messages) .to eq(['Put a comma after the last parameter of a ' \ 'multiline method call.']) end end it 'registers an offense for no trailing comma in a method call with' \ ' hash parameters at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1 ) RUBY expect(cop.messages) .to eq(['Put a comma after the last parameter of a multiline ' \ 'method call.']) expect(cop.highlights).to eq(['d: 1']) end it 'registers an offense for no trailing comma in a method call with' \ 'two parameters on the same line' do inspect_source(<<-RUBY.strip_indent) some_method(a, b ) RUBY expect(cop.messages) .to eq(['Put a comma after the last parameter of a multiline ' \ 'method call.']) end it 'accepts trailing comma in a method call with hash' \ ' parameters at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1, ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a trailing comma in a method call with ' \ 'a single hash parameter' do inspect_source(<<-RUBY.strip_indent) some_method( a: 0, b: 1, ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a trailing comma in a method call with single ' \ 'line hashes' do inspect_source(<<-RUBY.strip_indent) some_method( { a: 0, b: 1 }, { a: 1, b: 0 }, ) RUBY expect(cop.offenses.empty?).to be(true) end # this is a sad parse error it 'accepts no trailing comma in a method call with a block' \ ' parameter at the end' do inspect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1, &block ) RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts missing comma after a heredoc' do # A heredoc that's the last item in a literal or parameter list can not # have a trailing comma. It's a syntax error. expect_no_offenses(<<-RUBY.strip_indent) route(1, <<-HELP.chomp ... HELP ) RUBY end it 'auto-corrects missing comma in a method call with hash parameters' \ ' at the end' do new_source = autocorrect_source(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1 ) RUBY expect(new_source).to eq(<<-RUBY.strip_indent) some_method( a, b, c: 0, d: 1, ) RUBY end it 'accepts a multiline call with a single argument and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) method( 1, ) RUBY end it 'accepts a multiline call with arguments on a single line and' \ ' trailing comma' do inspect_source(<<-RUBY.strip_indent) method( 1, 2, ) RUBY expect(cop.offenses.empty?).to be(true) end end end end rubocop-0.52.1/spec/rubocop/cop/style/trailing_comma_in_literal_spec.rb000066400000000000000000000356371322072016200263330ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrailingCommaInLiteral, :config do subject(:cop) { described_class.new(config) } shared_examples 'single line lists' do |extra_info| it 'registers an offense for trailing comma in an Array literal' do inspect_source('VALUES = [1001, 2020, 3333, ]') expect(cop.messages) .to eq(["Avoid comma after the last item of an array#{extra_info}."]) expect(cop.highlights).to eq([',']) end it 'registers an offense for trailing comma in a Hash literal' do inspect_source('MAP = { a: 1001, b: 2020, c: 3333, }') expect(cop.messages) .to eq(["Avoid comma after the last item of a hash#{extra_info}."]) expect(cop.highlights).to eq([',']) end it 'accepts Array literal without trailing comma' do expect_no_offenses('VALUES = [1001, 2020, 3333]') end it 'accepts single element Array literal without trailing comma' do expect_no_offenses('VALUES = [1001]') end it 'accepts empty Array literal' do expect_no_offenses('VALUES = []') end it 'accepts rescue clause' do # The list of rescued classes is an array. expect_no_offenses(<<-RUBY.strip_indent) begin do_something rescue RuntimeError end RUBY end it 'accepts Hash literal without trailing comma' do expect_no_offenses('MAP = { a: 1001, b: 2020, c: 3333 }') end it 'accepts single element Hash literal without trailing comma' do expect_no_offenses('MAP = { a: 10001 }') end it 'accepts empty Hash literal' do expect_no_offenses('MAP = {}') end it 'auto-corrects unwanted comma in an Array literal' do new_source = autocorrect_source('VALUES = [1001, 2020, 3333, ]') expect(new_source).to eq('VALUES = [1001, 2020, 3333 ]') end it 'auto-corrects unwanted comma in a Hash literal' do new_source = autocorrect_source('MAP = { a: 1001, b: 2020, c: 3333, }') expect(new_source).to eq('MAP = { a: 1001, b: 2020, c: 3333 }') end end context 'with single line list of values' do context 'when EnforcedStyleForMultiline is no_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } } include_examples 'single line lists', '' end context 'when EnforcedStyleForMultiline is comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } } include_examples 'single line lists', ', unless each item is on its own line' end context 'when EnforcedStyleForMultiline is consistent_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'consistent_comma' } } include_examples 'single line lists', ', unless items are split onto multiple lines' end end context 'with multi-line list of values' do context 'when EnforcedStyleForMultiline is no_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'no_comma' } } it 'registers an offense for trailing comma in an Array literal' do expect_offense(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333, ^ Avoid comma after the last item of an array. ] RUBY end it 'registers an offense for trailing comma in a Hash literal' do expect_offense(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, ^ Avoid comma after the last item of a hash. } RUBY end it 'accepts an Array literal with no trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY end it 'accepts a Hash literal with no trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 } RUBY end it 'accepts comma inside a heredoc parameters at the end' do expect_no_offenses(<<-RUBY.strip_indent) route(help: { 'auth' => <<-HELP.chomp , HELP }) RUBY end it 'accepts comma in comment after last value item' do expect_no_offenses(<<-RUBY.strip_indent) { foo: 'foo', bar: 'bar'.delete(',')#, } RUBY end it 'auto-corrects unwanted comma in an Array literal' do new_source = autocorrect_source(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333, ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY end it 'auto-corrects unwanted comma in a Hash literal' do new_source = autocorrect_source(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 } RUBY end end context 'when EnforcedStyleForMultiline is comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'comma' } } context 'when closing bracket is on same line as last value' do it 'accepts Array literal with no trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333] RUBY end it 'accepts a Hash literal with no trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = { a: "b", c: "d", e: "f"} RUBY end end it 'accepts Array literal with two of the values on the same line' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY end it 'registers an offense for an Array literal with two of the values ' \ 'on the same line and a trailing comma' do inspect_source(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333, ] RUBY expect(cop.messages) .to eq(['Avoid comma after the last item of an array, unless each ' \ 'item is on its own line.']) end it 'registers an offense for no trailing comma in a Hash literal' do expect_offense(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 ^^^^^^^ Put a comma after the last item of a multiline hash. } RUBY end it 'registers an offense for trailing comma in a comment in Hash' do expect_offense(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 # , ^^^^^^^ Put a comma after the last item of a multiline hash. } RUBY end it 'accepts trailing comma in an Array literal' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [1001, 2020, 3333, ] RUBY end it 'accepts trailing comma in a Hash literal' do expect_no_offenses(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, } RUBY end it 'accepts a multiline word array' do expect_no_offenses(<<-RUBY.strip_indent) ingredients = %w( sausage anchovies olives ) RUBY end it 'accepts missing comma after a heredoc' do # A heredoc that's the last item in a literal or parameter list can not # have a trailing comma. It's a syntax error. expect_no_offenses(<<-RUBY.strip_indent) route(help: { 'auth' => <<-HELP.chomp ... HELP }) RUBY end it 'accepts an empty hash being passed as a method argument' do expect_no_offenses(<<-RUBY.strip_indent) Foo.new([ ]) RUBY end it 'auto-corrects an Array literal with two of the values on the same' \ ' line and a trailing comma' do new_source = autocorrect_source(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY end it 'auto-corrects missing comma in a Hash literal' do new_source = autocorrect_source(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, } RUBY end it 'accepts a multiline array with a single item and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) foo = [ 1, ] RUBY end it 'accepts a multiline hash with a single pair and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) bar = { a: 123, } RUBY end end context 'when EnforcedStyleForMultiline is consistent_comma' do let(:cop_config) { { 'EnforcedStyleForMultiline' => 'consistent_comma' } } context 'when closing bracket is on same line as last value' do it 'registers an offense for an Array literal with no trailing comma' do expect_offense(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333] ^^^^ Put a comma after the last item of a multiline array. RUBY end it 'registers an offense for a Hash literal with no trailing comma' do expect_offense(<<-RUBY.strip_indent) VALUES = { a: "b", b: "c", d: "e"} ^^^^^^ Put a comma after the last item of a multiline hash. RUBY end it 'auto-corrects a missing comma in a Hash literal' do new_source = autocorrect_source(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333} RUBY expect(new_source).to eq(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333,} RUBY end end it 'accepts Array literal with two of the values on the same line' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333, ] RUBY end it 'registers an offense for an Array literal with two of the values ' \ 'on the same line and no trailing comma' do inspect_source(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY expect(cop.messages) .to eq(['Put a comma after the last item of a multiline array.']) end it 'registers an offense for no trailing comma in a Hash literal' do expect_offense(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 ^^^^^^^ Put a comma after the last item of a multiline hash. } RUBY end it 'accepts trailing comma in an Array literal' do expect_no_offenses(<<-RUBY.strip_indent) VALUES = [1001, 2020, 3333, ] RUBY end it 'accepts trailing comma in a Hash literal' do expect_no_offenses(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, } RUBY end it 'accepts a multiline word array' do expect_no_offenses(<<-RUBY.strip_indent) ingredients = %w( sausage anchovies olives ) RUBY end it 'accepts missing comma after a heredoc' do # A heredoc that's the last item in a literal or parameter list can not # have a trailing comma. It's a syntax error. expect_no_offenses(<<-RUBY.strip_indent) route(help: { 'auth' => <<-HELP.chomp ... HELP }) RUBY end it 'auto-corrects an Array literal with two of the values on the same' \ ' line and a trailing comma' do new_source = autocorrect_source(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333 ] RUBY expect(new_source).to eq(<<-RUBY.strip_indent) VALUES = [ 1001, 2020, 3333, ] RUBY end it 'auto-corrects missing comma in a Hash literal' do new_source = autocorrect_source(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333 } RUBY expect(new_source).to eq(<<-RUBY.strip_indent) MAP = { a: 1001, b: 2020, c: 3333, } RUBY end it 'accepts a multiline array with a single item and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) foo = [ 1, ] RUBY end it 'accepts a multiline hash with a single pair and trailing comma' do expect_no_offenses(<<-RUBY.strip_indent) bar = { a: 123, } RUBY end it 'accepts a multiline array with items on a single line and' \ 'trailing comma' do inspect_source(<<-RUBY.strip_indent) foo = [ 1, 2, ] RUBY expect(cop.offenses.empty?).to be(true) end it 'accepts a multiline hash with pairs on a single line and' \ 'trailing comma' do inspect_source(<<-RUBY.strip_indent) bar = { a: 1001, b: 2020, } RUBY expect(cop.offenses.empty?).to be(true) end end end end rubocop-0.52.1/spec/rubocop/cop/style/trailing_method_end_statement_spec.rb000066400000000000000000000062211322072016200272120ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrailingMethodEndStatement do subject(:cop) { described_class.new(config) } let(:config) do RuboCop::Config.new('Layout/IndentationWidth' => { 'Width' => 2 }) end it 'register offense with trailing end on 2 line method' do expect_offense(<<-RUBY.strip_indent) def some_method foo; end ^^^ Place the end statement of a multi-line method on its own line. RUBY end it 'register offense with trailing end on 3 line method' do expect_offense(<<-RUBY.strip_indent) def a b { foo: bar }; end ^^^ Place the end statement of a multi-line method on its own line. RUBY end it 'register offense with trailing end on method with comment' do expect_offense(<<-RUBY.strip_indent) def c b = calculation [b] end # because b ^^^ Place the end statement of a multi-line method on its own line. RUBY end it 'register offense with trailing end on method with block' do expect_offense(<<-RUBY.strip_indent) def d block do foo end end ^^^ Place the end statement of a multi-line method on its own line. RUBY end it 'does not register on single line no op' do expect_no_offenses(<<-RUBY.strip_indent) def no_op; end RUBY end it 'does not register on single line method' do expect_no_offenses(<<-RUBY.strip_indent) def something; do_stuff; end RUBY end it 'auto-corrects trailing end in 2 line method' do corrected = autocorrect_source([' def some_method', ' []; end'].join("\n")) expect(corrected).to eq [' def some_method', ' [] ', ' end'].join("\n") end it 'auto-corrects trailing end in 3 line method' do corrected = autocorrect_source([' def do_this(x)', ' y = x + 5', ' y / 2; end'].join("\n")) expect(corrected).to eq [' def do_this(x)', ' y = x + 5', ' y / 2 ', ' end'].join("\n") end it 'auto-corrects trailing end with comment' do corrected = autocorrect_source([' def f(x, y)', ' process(x)', ' process(y) end # comment'].join("\n")) expect(corrected).to eq [' def f(x, y)', ' process(x)', ' process(y) ', ' end # comment'].join("\n") end it 'auto-corrects trailing end on method with block' do corrected = autocorrect_source([' def d', ' block do', ' foo', ' end end'].join("\n")) expect(corrected).to eq [' def d', ' block do', ' foo', ' end ', ' end'].join("\n") end end rubocop-0.52.1/spec/rubocop/cop/style/trailing_underscore_variable_spec.rb000066400000000000000000000251311322072016200270370ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrailingUnderscoreVariable do subject(:cop) { described_class.new(config) } shared_examples 'common functionality' do it 'registers an offense when the last variable of parallel assignment ' \ 'is an underscore' do expect_offense(<<-RUBY.strip_indent) a, b, _ = foo() ^^ Do not use trailing `_`s in parallel assignment. Prefer `a, b, = foo()`. RUBY end it 'registers an offense when multiple underscores are used '\ 'as the last variables of parallel assignment ' do expect_offense(<<-RUBY.strip_indent) a, _, _ = foo() ^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'registers an offense for splat underscore as the last variable' do expect_offense(<<-RUBY.strip_indent) a, *_ = foo() ^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'registers an offense when underscore is the second to last variable ' \ 'and blank is the last variable' do expect_offense(<<-RUBY.strip_indent) a, _, = foo() ^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'registers an offense when underscore is the only variable ' \ 'in parallel assignment' do expect_offense(<<-RUBY.strip_indent) _, = foo() ^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `foo()`. RUBY end it 'registers an offense for an underscore as the last param ' \ 'when there is also an underscore as the first param' do expect_offense(<<-RUBY.strip_indent) _, b, _ = foo() ^^ Do not use trailing `_`s in parallel assignment. Prefer `_, b, = foo()`. RUBY end it 'does not register an offense when there are no underscores' do expect_no_offenses('a, b, c = foo()') end it 'does not register an offense for underscores at the beginning' do expect_no_offenses('_, a, b = foo()') end it 'does not register an offense for an underscore preceded by a ' \ 'splat variable anywhere in the argument chain' do expect_no_offenses('*a, b, _ = foo()') end it 'does not register an offense for an underscore preceded by a ' \ 'splat variable' do expect_no_offenses('a, *b, _ = foo()') end it 'does not register an offense for an underscore preceded by a ' \ 'splat variable and another underscore' do expect_no_offenses('_, *b, _ = *foo') end it 'does not register an offense for multiple underscores preceded by a ' \ 'splat variable' do expect_no_offenses('a, *b, _, _ = foo()') end it 'does not register an offense for multiple named underscores ' \ 'preceded by a splat variable' do expect_no_offenses('a, *b, _c, _d = foo()') end it 'registers an offense for multiple underscore variables preceded by ' \ 'a splat underscore variable' do expect_offense(<<-RUBY.strip_indent) a, *_, _, _ = foo() ^^^^^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'registers an offense for nested assignments with trailing ' \ 'underscores' do expect_offense(<<-RUBY.strip_indent) a, (b, _) = foo() ^^ Do not use trailing `_`s in parallel assignment. Prefer `a, (b,) = foo()`. RUBY end it 'registers an offense for complex nested assignments with trailing ' \ 'underscores' do expect_offense(<<-RUBY.strip_indent) a, (_, (b, _), *_) = foo() ^^ Do not use trailing `_`s in parallel assignment. Prefer `a, (_, (b,), *_) = foo()`. ^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, (_, (b, _),) = foo()`. RUBY end it 'does not register an offense for a named underscore variable ' \ 'preceded by a splat variable' do expect_no_offenses('a, *b, _c = foo()') end it 'does not register an offense for a named variable preceded by a ' \ 'names splat underscore variable' do expect_no_offenses('a, *b, _c = foo()') end it 'does not register an offense for nested assignments without ' \ 'trailing underscores' do expect_no_offenses('a, (_, b) = foo()') end it 'does not register an offense for complex nested assignments without ' \ 'trailing underscores' do expect_no_offenses('a, (_, (b,), c, (d, e),) = foo()') end describe 'autocorrect' do it 'removes trailing underscores automatically' do new_source = autocorrect_source('a, b, _ = foo()') expect(new_source).to eq('a, b, = foo()') end it 'removes trailing underscores and commas' do new_source = autocorrect_source('a, b, _, = foo()') expect(new_source).to eq('a, b, = foo()') end it 'removes multiple trailing underscores' do new_source = autocorrect_source('a, _, _ = foo()') expect(new_source).to eq('a, = foo()') end it 'removes trailing underscores and commas and preserves assignments' do new_source = autocorrect_source('a, _, _, = foo()') expect(new_source).to eq('a, = foo()') end it 'removes trailing comma when it is the only variable' do new_source = autocorrect_source('_, = foo()') expect(new_source).to eq('foo()') end it 'removes all assignments when every assignment is to `_`' do new_source = autocorrect_source('_, _, _, = foo()') expect(new_source).to eq('foo()') end it 'remove splat underscore' do new_source = autocorrect_source('a, *_ = foo()') expect(new_source).to eq('a, = foo()') end it 'removes underscores inside nested assignments' do new_source = autocorrect_source('a, (b, _) = foo()') expect(new_source).to eq('a, (b,) = foo()') end it 'removes trailing underscores inside complex nested assignments ' do new_source = autocorrect_source('a, (_, (b, _), *_) = foo()') expect(new_source).to eq('a, (_, (b,),) = foo()') end context 'with parentheses' do it 'leaves parentheses but removes trailing underscores' do new_source = autocorrect_source('(a, b, _) = foo()') expect(new_source).to eq('(a, b,) = foo()') end it 'removes assignment part when every assignment is to `_`' do new_source = autocorrect_source('(_, _, _,) = foo()') expect(new_source).to eq('foo()') end it 'removes assignment part when it is the only variable' do new_source = autocorrect_source('(_,) = foo()') expect(new_source).to eq('foo()') end it 'leaves parentheses but removes trailing underscores and commas' do new_source = autocorrect_source('(a, _, _,) = foo()') expect(new_source).to eq('(a,) = foo()') end end end end context 'configured to allow named underscore variables' do let(:config) do RuboCop::Config.new( 'Style/TrailingUnderscoreVariable' => { 'Enabled' => true, 'AllowNamedUnderscoreVariables' => true } ) end include_examples 'common functionality' it 'does not register an offense for named variables ' \ 'that start with an underscore' do expect_no_offenses('a, b, _c = foo()') end it 'does not register an offense for a named splat underscore ' \ 'as the last variable' do expect_no_offenses('a, *_b = foo()') end it 'does not register an offense for an underscore variable preceded ' \ 'by a named splat underscore variable' do expect_no_offenses('a, *_b, _ = foo()') end it 'does not register an offense for multiple underscore variables ' \ 'preceded by a named splat underscore variable' do expect_no_offenses('a, *_b, _, _ = foo()') end end context 'configured to not allow named underscore variables' do let(:config) do RuboCop::Config.new( 'Style/TrailingUnderscoreVariable' => { 'Enabled' => true, 'AllowNamedUnderscoreVariables' => false } ) end include_examples 'common functionality' it 'registers an offense for named variables ' \ 'that start with an underscore' do expect_offense(<<-RUBY.strip_indent) a, b, _c = foo() ^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, b, = foo()`. RUBY end it 'registers an offense for a named splat underscore ' \ 'as the last variable' do expect_offense(<<-RUBY.strip_indent) a, *_b = foo() ^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'does not register an offense for a named underscore preceded by a ' \ 'splat variable' do expect_no_offenses('a, *b, _c = foo()') end it 'registers an offense for an underscore variable preceded ' \ 'by a named splat underscore variable' do expect_offense(<<-RUBY.strip_indent) a, *_b, _ = foo() ^^^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end it 'registers an offense for an underscore preceded by ' \ 'a named splat underscore' do expect_offense(<<-RUBY.strip_indent) a, b, *_c, _ = foo() ^^^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, b, = foo()`. RUBY end it 'registers an offense for multiple underscore variables ' \ 'preceded by a named splat underscore variable' do expect_offense(<<-RUBY.strip_indent) a, *_b, _, _ = foo() ^^^^^^^^^^ Do not use trailing `_`s in parallel assignment. Prefer `a, = foo()`. RUBY end context 'autocorrect' do it 'removes named underscore variables' do new_source = autocorrect_source('a, _b = foo()') expect(new_source).to eq('a, = foo()') end it 'removes named splat underscore variables' do new_source = autocorrect_source('a, *_b = foo()') expect(new_source).to eq('a, = foo()') end it 'removes named splat underscore and named underscore variables' do new_source = autocorrect_source('a, *_b, _c = foo()') expect(new_source).to eq('a, = foo()') end it 'works when last underscore is followed by a comma' do new_source = autocorrect_source('a, _, = foo()') expect(new_source).to eq('a, = foo()') end end end end rubocop-0.52.1/spec/rubocop/cop/style/trivial_accessors_spec.rb000066400000000000000000000257611322072016200246600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::TrivialAccessors, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { {} } let(:trivial_reader) do <<-RUBY.strip_indent def foo @foo end RUBY end let(:trivial_writer) do <<-RUBY.strip_indent def foo=(val) @foo = val end RUBY end it 'registers an offense on instance reader' do expect_offense(<<-RUBY.strip_indent) def foo ^^^ Use `attr_reader` to define trivial reader methods. @foo end RUBY end it 'registers an offense on instance writer' do expect_offense(<<-RUBY.strip_indent) def foo=(val) ^^^ Use `attr_writer` to define trivial writer methods. @foo = val end RUBY end it 'show correct message on reader' do inspect_source(trivial_reader) expect(cop.messages.first) .to eq('Use `attr_reader` to define trivial reader methods.') end it 'show correct message on writer' do inspect_source(trivial_writer) expect(cop.messages.first) .to eq('Use `attr_writer` to define trivial writer methods.') end it 'registers an offense on class reader' do expect_offense(<<-RUBY.strip_indent) def self.foo ^^^ Use `attr_reader` to define trivial reader methods. @foo end RUBY end it 'registers an offense on class writer' do expect_offense(<<-RUBY.strip_indent) def self.foo(val) ^^^ Use `attr_writer` to define trivial writer methods. @foo = val end RUBY end it 'registers an offense on reader with braces' do expect_offense(<<-RUBY.strip_indent) def foo() ^^^ Use `attr_reader` to define trivial reader methods. @foo end RUBY end it 'registers an offense on writer without braces' do expect_offense(<<-RUBY.strip_indent) def foo= val ^^^ Use `attr_writer` to define trivial writer methods. @foo = val end RUBY end it 'registers an offense on one-liner reader' do expect_offense(<<-RUBY.strip_indent) def foo; @foo; end ^^^ Use `attr_reader` to define trivial reader methods. RUBY end it 'registers an offense on one-liner writer' do expect_offense(<<-RUBY.strip_indent) def foo(val); @foo=val; end ^^^ Use `attr_writer` to define trivial writer methods. RUBY end it 'register an offense on DSL-style trivial writer' do expect_offense(<<-RUBY.strip_indent) def foo(val) ^^^ Use `attr_writer` to define trivial writer methods. @foo = val end RUBY end it 'accepts non-trivial reader' do expect_no_offenses(<<-RUBY.strip_indent) def test some_function_call @test end RUBY end it 'accepts non-trivial writer' do expect_no_offenses(<<-RUBY.strip_indent) def test(val) some_function_call(val) @test = val log(val) end RUBY end it 'accepts splats' do expect_no_offenses(<<-RUBY.strip_indent) def splatomatic(*values) @splatomatic = values end RUBY end it 'accepts blocks' do expect_no_offenses(<<-RUBY.strip_indent) def something(&block) @b = block end RUBY end it 'accepts expressions within reader' do expect_no_offenses(<<-RUBY.strip_indent) def bar @bar + foo end RUBY end it 'accepts expressions within writer' do expect_no_offenses(<<-RUBY.strip_indent) def bar(val) @bar = val + foo end RUBY end it 'accepts an initialize method looking like a writer' do expect_no_offenses(<<-RUBY.strip_indent) def initialize(value) @top = value end RUBY end it 'accepts reader with different ivar name' do expect_no_offenses(<<-RUBY.strip_indent) def foo @fo end RUBY end it 'accepts writer with different ivar name' do expect_no_offenses(<<-RUBY.strip_indent) def foo(val) @fo = val end RUBY end it 'accepts writer in a module' do expect_no_offenses(<<-RUBY.strip_indent) module Foo def bar=(bar) @bar = bar end end RUBY end it 'accepts writer nested within a module' do expect_no_offenses(<<-RUBY.strip_indent) module Foo begin def bar=(bar) @bar = bar end end end RUBY end it 'accepts reader nested within a module' do expect_no_offenses(<<-RUBY.strip_indent) module Foo begin def bar @bar end end end RUBY end it 'accepts writer nested within an instance_eval call' do expect_no_offenses(<<-RUBY.strip_indent) something.instance_eval do begin def bar=(bar) @bar = bar end end end RUBY end it 'accepts reader nested within an instance_eval calll' do expect_no_offenses(<<-RUBY.strip_indent) something.instance_eval do begin def bar @bar end end end RUBY end it 'flags a reader inside a class, inside an instance_eval call' do expect_offense(<<-RUBY.strip_indent) something.instance_eval do class << @blah begin def bar ^^^ Use `attr_reader` to define trivial reader methods. @bar end end end end RUBY end context 'exact name match disabled' do let(:cop_config) { { 'ExactNameMatch' => false } } it 'registers an offense when names mismatch in writer' do expect_offense(<<-RUBY.strip_indent) def foo(val) ^^^ Use `attr_writer` to define trivial writer methods. @f = val end RUBY end it 'registers an offense when names mismatch in reader' do expect_offense(<<-RUBY.strip_indent) def foo ^^^ Use `attr_reader` to define trivial reader methods. @f end RUBY end end context 'disallow predicates' do let(:cop_config) { { 'AllowPredicates' => false } } it 'does not accept predicate-like reader' do expect_offense(<<-RUBY.strip_indent) def foo? ^^^ Use `attr_reader` to define trivial reader methods. @foo end RUBY end end context 'allow predicates' do let(:cop_config) { { 'AllowPredicates' => true } } it 'accepts predicate-like reader' do expect_no_offenses(<<-RUBY.strip_indent) def foo? @foo end RUBY end end context 'with whitelist' do let(:cop_config) { { 'Whitelist' => ['to_foo', 'bar='] } } it 'accepts whitelisted reader' do expect_no_offenses(<<-RUBY.strip_indent) def to_foo @foo end RUBY end it 'accepts whitelisted writer' do expect_no_offenses(<<-RUBY.strip_indent) def bar=(bar) @bar = bar end RUBY end context 'with AllowPredicates: false' do let(:cop_config) do { 'AllowPredicates' => false, 'Whitelist' => ['foo?'] } end it 'accepts whitelisted predicate' do expect_no_offenses(<<-RUBY.strip_indent) def foo? @foo end RUBY end end end context 'with DSL allowed' do let(:cop_config) { { 'AllowDSLWriters' => true } } it 'accepts DSL-style writer' do expect_no_offenses(<<-RUBY.strip_indent) def foo(val) @foo = val end RUBY end end context 'ignore class methods' do let(:cop_config) { { 'IgnoreClassMethods' => true } } it 'accepts class reader' do expect_no_offenses(<<-RUBY.strip_indent) def self.foo @foo end RUBY end it 'accepts class writer' do expect_no_offenses(<<-RUBY.strip_indent) def self.foo(val) @foo = val end RUBY end end describe '#autocorrect' do context 'trivial reader' do let(:source) { trivial_reader } let(:corrected_source) { "attr_reader :foo\n" } it 'autocorrects' do expect(autocorrect_source(source)).to eq(corrected_source) end end context 'non-matching reader' do let(:cop_config) { { 'ExactNameMatch' => false } } let(:source) do <<-RUBY.strip_indent def foo @bar end RUBY end it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'predicate reader, with AllowPredicates: false' do let(:cop_config) { { 'AllowPredicates' => false } } let(:source) do <<-RUBY.strip_indent def foo? @foo end RUBY end it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'trivial writer' do let(:source) { trivial_writer } let(:corrected_source) { "attr_writer :foo\n" } it 'autocorrects' do expect(autocorrect_source(source)).to eq(corrected_source) end end context 'matching DSL-style writer' do let(:source) do <<-RUBY.strip_indent def foo(f) @foo=f end RUBY end it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'explicit receiver writer' do let(:source) do <<-RUBY.strip_indent def derp.foo=(f) @foo=f end RUBY end it 'does not autocorrect' do expect(autocorrect_source(source)).to eq(source) expect(cop.offenses.map(&:corrected?)).to eq [false] end end context 'class receiver reader' do let(:source) do <<-RUBY.strip_indent class Foo def self.foo @foo end end RUBY end let(:corrected_source) do <<-RUBY.strip_indent class Foo class << self attr_reader :foo end end RUBY end it 'autocorrects with class-level attr_reader' do expect(autocorrect_source(source)).to eq(corrected_source) end end context 'class receiver writer' do let(:source) do <<-RUBY.strip_indent class Foo def self.foo=(f) @foo = f end end RUBY end let(:corrected_source) do <<-RUBY.strip_indent class Foo class << self attr_writer :foo end end RUBY end it 'autocorrects with class-level attr_writer' do expect(autocorrect_source(source)).to eq(corrected_source) end end end end rubocop-0.52.1/spec/rubocop/cop/style/unless_else_spec.rb000066400000000000000000000032031322072016200234450ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::UnlessElse do subject(:cop) { described_class.new } context 'unless with else' do let(:source) do <<-RUBY.strip_indent unless x # negative 1 a = 1 # negative 2 else # positive 1 a = 0 # positive 2 end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) if x # positive 1 a = 0 # positive 2 else # negative 1 a = 1 # negative 2 end RUBY end end context 'unless with nested if-else' do let(:source) do <<-RUBY.strip_indent unless(x) if(y == 0) a = 0 elsif(z == 0) a = 1 else a = 2 end else a = 3 end RUBY end it 'registers an offense' do inspect_source(source) expect(cop.offenses.size).to eq(1) end it 'auto-corrects' do corrected = autocorrect_source(source) expect(corrected).to eq(<<-RUBY.strip_indent) if(x) a = 3 else if(y == 0) a = 0 elsif(z == 0) a = 1 else a = 2 end end RUBY end end context 'unless without else' do it 'does not register an offense' do expect_no_offenses(<<-RUBY.strip_indent) unless x a = 1 end RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/unneeded_capital_w_spec.rb000066400000000000000000000043271322072016200247460ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::UnneededCapitalW do subject(:cop) { described_class.new } it 'registers no offense for normal arrays of strings' do expect_no_offenses('["one", "two", "three"]') end it 'registers no offense for normal arrays of strings with interpolation' do expect_no_offenses('["one", "two", "th#{?r}ee"]') end it 'registers an offense for misused %W' do expect_offense(<<-RUBY.strip_indent) %W(cat dog) ^^^^^^^^^^^ Do not use `%W` unless interpolation is needed. If not, use `%w`. RUBY end it 'registers no offense for %W with interpolation' do expect_no_offenses('%W(c#{?a}t dog)') end it 'registers no offense for %W with special characters' do expect_no_offenses(<<-'RUBY'.strip_indent) def dangerous_characters %W(\000) + %W(\001) + %W(\027) + %W(\002) + %W(\003) + %W(\004) + %W(\005) + %W(\006) + %W(\007) + %W(\00) + %W(\a) %W(\s) %W(\n) %W(\!) end RUBY end it 'registers no offense for %w without interpolation' do expect_no_offenses('%w(cat dog)') end it 'registers no offense for %w with interpolation-like syntax' do expect_no_offenses('%w(c#{?a}t dog)') end it 'registers no offense for arrays with character constants' do expect_no_offenses('["one", ?\n]') end it 'does not register an offense for array of non-words' do expect_no_offenses('["one space", "two", "three"]') end it 'does not register an offense for array containing non-string' do expect_no_offenses('["one", "two", 3]') end it 'does not register an offense for array with one element' do expect_no_offenses('["three"]') end it 'does not register an offense for array with empty strings' do expect_no_offenses('["", "two", "three"]') end it 'auto-corrects an array of words' do new_source = autocorrect_source('%W(one two three)') expect(new_source).to eq('%w(one two three)') end it 'auto-corrects an array of words with different bracket' do new_source = autocorrect_source('%W[one two three]') expect(new_source).to eq('%w[one two three]') end end rubocop-0.52.1/spec/rubocop/cop/style/unneeded_interpolation_spec.rb000066400000000000000000000100651322072016200256660ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::UnneededInterpolation do subject(:cop) { described_class.new } it 'registers an offense for "#{1 + 1}"' do expect_offense(<<-'RUBY'.strip_indent) "#{1 + 1}" ^^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "%|#{1 + 1}|"' do expect_offense(<<-'RUBY'.strip_indent) %|#{1 + 1}| ^^^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "%Q(#{1 + 1})"' do expect_offense(<<-'RUBY'.strip_indent) %Q(#{1 + 1}) ^^^^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{1 + 1; 2 + 2}"' do expect_offense(<<-'RUBY'.strip_indent) "#{1 + 1; 2 + 2}" ^^^^^^^^^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{@var}"' do expect_offense(<<-'RUBY'.strip_indent) "#{@var}" ^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#@var"' do expect_offense(<<-'RUBY'.strip_indent) "#@var" ^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{@@var}"' do expect_offense(<<-'RUBY'.strip_indent) "#{@@var}" ^^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#@@var"' do expect_offense(<<-'RUBY'.strip_indent) "#@@var" ^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{$var}"' do expect_offense(<<-'RUBY'.strip_indent) "#{$var}" ^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#$var"' do expect_offense(<<-'RUBY'.strip_indent) "#$var" ^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{$1}"' do expect_offense(<<-'RUBY'.strip_indent) "#{$1}" ^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#$1"' do expect_offense(<<-'RUBY'.strip_indent) "#$1" ^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{$+}"' do expect_offense(<<-'RUBY'.strip_indent) "#{$+}" ^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#$+"' do expect_offense(<<-'RUBY'.strip_indent) "#$+" ^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for "#{var}"' do expect_offense(<<-'RUBY'.strip_indent) var = 1; "#{var}" ^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'registers an offense for ["#{@var}"]' do expect_offense(<<-'RUBY'.strip_indent) ["#{@var}", 'foo'] ^^^^^^^^^ Prefer `to_s` over string interpolation. RUBY end it 'accepts strings with characters before the interpolation' do expect_no_offenses('"this is #{@sparta}"') end it 'accepts strings with characters after the interpolation' do expect_no_offenses('"#{@sparta} this is"') end it 'accepts strings implicitly concatenated with a later string' do expect_no_offenses(%q("#{sparta}" ' this is')) end it 'accepts strings implicitly concatenated with an earlier string' do expect_no_offenses(%q('this is ' "#{sparta}")) end it 'accepts strings that are part of a %W()' do expect_no_offenses('%W(#{@var} foo)') end it 'autocorrects "#{1 + 1; 2 + 2}"' do corrected = autocorrect_source(['"#{1 + 1; 2 + 2}"']) expect(corrected).to eq '(1 + 1; 2 + 2).to_s' end it 'autocorrects "#@var"' do corrected = autocorrect_source(['"#@var"']) expect(corrected).to eq '@var.to_s' end it 'autocorrects "#{var}"' do corrected = autocorrect_source(['var = 1; "#{var}"']) expect(corrected).to eq 'var = 1; var.to_s' end it 'autocorrects "#{@var}"' do corrected = autocorrect_source(['"#{@var}"']) expect(corrected).to eq '@var.to_s' end end rubocop-0.52.1/spec/rubocop/cop/style/unneeded_percent_q_spec.rb000066400000000000000000000131711322072016200247600ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::UnneededPercentQ do subject(:cop) { described_class.new } context 'with %q strings' do it 'registers an offense for only single quotes' do expect_offense(<<-RUBY.strip_indent) %q('hi') ^^^^^^^^ Use `%q` only for strings that contain both single quotes and double quotes. RUBY end it 'registers an offense for only double quotes' do expect_offense(<<-RUBY.strip_indent) %q("hi") ^^^^^^^^ Use `%q` only for strings that contain both single quotes and double quotes. RUBY end it 'registers an offense for no quotes' do expect_offense(<<-RUBY.strip_indent) %q(hi) ^^^^^^ Use `%q` only for strings that contain both single quotes and double quotes. RUBY end it 'accepts a string with single quotes and double quotes' do expect_no_offenses("%q('\"hi\"')") end it 'registers an offfense for a string containing escaped backslashes' do inspect_source('%q(\\\\foo\\\\)') expect(cop.messages.length).to eq 1 end it 'accepts a string with escaped non-backslash characters' do expect_no_offenses("%q(\\'foo\\')") end it 'accepts a string with escaped backslash and non-backslash characters' do expect_no_offenses("%q(\\\\ \\'foo\\' \\\\)") end it 'accepts regular expressions starting with %q' do expect_no_offenses('/%q?/') end context 'auto-correct' do it 'registers an offense for only single quotes' do new_source = autocorrect_source("%q('hi')") expect(new_source).to eq(%q("'hi'")) end it 'registers an offense for only double quotes' do new_source = autocorrect_source('%q("hi")') expect(new_source).to eq(%q('"hi"')) end it 'registers an offense for no quotes' do new_source = autocorrect_source('%q(hi)') expect(new_source).to eq("'hi'") end it 'auto-corrects for strings that is concated with backslash' do new_source = autocorrect_source(<<-RUBY.strip_indent) %q(foo bar baz) \ 'boogers' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) 'foo bar baz' \ 'boogers' RUBY end end end context 'with %Q strings' do it 'registers an offense for static string without quotes' do expect_offense(<<-RUBY.strip_indent) %Q(hi) ^^^^^^ Use `%Q` only for strings that contain both single quotes and double quotes, or for dynamic strings that contain double quotes. RUBY end it 'registers an offense for static string with only double quotes' do expect_offense(<<-RUBY.strip_indent) %Q("hi") ^^^^^^^^ Use `%Q` only for strings that contain both single quotes and double quotes, or for dynamic strings that contain double quotes. RUBY end it 'registers an offense for dynamic string without quotes' do expect_offense(<<-'RUBY'.strip_indent) %Q(hi#{4}) ^^^^^^^^^^ Use `%Q` only for strings that contain both single quotes and double quotes, or for dynamic strings that contain double quotes. RUBY end it 'accepts a string with single quotes and double quotes' do expect_no_offenses("%Q('\"hi\"')") end it 'accepts a string with double quotes and an escaped special character' do expect_no_offenses('%Q("\\thi")') end it 'accepts a string with double quotes and an escaped normal character' do expect_no_offenses('%Q("\\!thi")') end it 'accepts a dynamic %Q string with double quotes' do expect_no_offenses("%Q(\"hi\#{4}\")") end it 'accepts regular expressions starting with %Q' do expect_no_offenses('/%Q?/') end context 'auto-correct' do it 'corrects a static string without quotes' do new_source = autocorrect_source('%Q(hi)') expect(new_source).to eq('"hi"') end it 'corrects a static string with only double quotes' do new_source = autocorrect_source('%Q("hi")') expect(new_source).to eq(%q('"hi"')) end it 'corrects a dynamic string without quotes' do new_source = autocorrect_source("%Q(hi\#{4})") expect(new_source).to eq(%("hi\#{4}")) end it 'auto-corrects for strings that is concated with backslash' do new_source = autocorrect_source(<<-RUBY.strip_indent) %Q(foo bar baz) \ 'boogers' RUBY expect(new_source).to eq(<<-RUBY.strip_indent) "foo bar baz" \ 'boogers' RUBY end end end it 'accepts a heredoc string that contains %q' do expect_no_offenses(<<-RUBY.strip_indent) s = < { 'Max' => 80 } } RuboCop::Config.new(hash) end it "accepts multiline unless that doesn't fit on one line" do check_too_long(cop, 'unless') end it 'accepts multiline unless whose body is more than one line' do check_short_multiline(cop, 'unless') end context 'multiline while that fits on one line' do it 'registers an offense' do check_really_short(cop, 'while') end it 'does auto-correction' do autocorrect_really_short('while') end end it "accepts multiline while that doesn't fit on one line" do check_too_long(cop, 'while') end it 'accepts multiline while whose body is more than one line' do check_short_multiline(cop, 'while') end it 'accepts oneline while when condition has local variable assignment' do expect_no_offenses(<<-RUBY.strip_indent) lines = %w{first second third} while (line = lines.shift) puts line end RUBY end context 'oneline while when assignment is in body' do let(:source) do <<-RUBY.strip_indent while true x = 0 end RUBY end it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) while true ^^^^^ Favor modifier `while` usage when having a single-line body. x = 0 end RUBY end it 'does auto-correction' do corrected = autocorrect_source(source) expect(corrected).to eq "x = 0 while true\n" end end context 'multiline until that fits on one line' do it 'registers an offense' do check_really_short(cop, 'until') end it 'does auto-correction' do autocorrect_really_short('until') end end it "accepts multiline until that doesn't fit on one line" do check_too_long(cop, 'until') end it 'accepts multiline until whose body is more than one line' do check_short_multiline(cop, 'until') end it 'accepts an empty condition' do check_empty(cop, 'while') check_empty(cop, 'until') end it 'accepts modifier while' do expect_no_offenses('ala while bala') end it 'accepts modifier until' do expect_no_offenses('ala until bala') end # Regression: https://github.com/bbatsov/rubocop/issues/4006 context 'when the modifier condition is multiline' do it 'registers an offense' do expect_offense(<<-RUBY.strip_indent) foo while bar || ^^^^^ Favor modifier `while` usage when having a single-line body. baz RUBY end end end rubocop-0.52.1/spec/rubocop/cop/style/word_array_spec.rb000066400000000000000000000244011322072016200233000ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::WordArray, :config do subject(:cop) { described_class.new(config) } before do # Reset data which is shared by all instances of WordArray described_class.largest_brackets = -Float::INFINITY end let(:other_cops) do { 'Style/PercentLiteralDelimiters' => { 'PreferredDelimiters' => { 'default' => '()' } } } end context 'when EnforcedStyle is percent' do let(:cop_config) do { 'MinSize' => 0, 'WordRegex' => /\A[\p{Word}\n\t]+\z/, 'EnforcedStyle' => 'percent' } end it 'registers an offense for arrays of single quoted strings' do inspect_source("['one', 'two', 'three']") expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%w` or `%W` for an array of words.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'brackets') end it 'registers an offense for arrays of double quoted strings' do expect_offense(<<-RUBY.strip_indent) ["one", "two", "three"] ^^^^^^^^^^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'registers an offense for arrays of unicode word characters' do expect_offense(<<-RUBY.strip_indent) ["ВУЗ", "вуз", "中文网"] ^^^^^^^^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'registers an offense for arrays with character constants' do expect_offense(<<-'RUBY'.strip_indent) ["one", ?\n] ^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'registers an offense for strings with embedded newlines and tabs' do inspect_source(%(["one\n", "hi\tthere"])) expect(cop.offenses.size).to eq(1) end it 'registers an offense for strings with newline and tab escapes' do expect_offense(<<-'RUBY'.strip_indent) ["one\n", "hi\tthere"] ^^^^^^^^^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'uses %W when autocorrecting strings with newlines and tabs' do new_source = autocorrect_source(%(["one\\n", "hi\\tthere"])) expect(new_source).to eq('%W(one\\n hi\\tthere)') end it 'does not register an offense for array of non-words' do expect_no_offenses('["one space", "two", "three"]') end it 'does not register an offense for array containing non-string' do expect_no_offenses('["one", "two", 3]') end it 'does not register an offense for array starting with %w' do expect_no_offenses('%w(one two three)') end it 'does not register an offense for array with one element' do expect_no_offenses('["three"]') end it 'does not register an offense for array with empty strings' do expect_no_offenses('["", "two", "three"]') end # Bug: https://github.com/bbatsov/rubocop/issues/4481 it 'does not register an offense in an ambiguous block context' do expect_no_offenses('foo ["bar", "baz"] { qux }') end it 'registers an offense in a non-ambiguous block context' do expect_offense(<<-RUBY.strip_indent) foo(['bar', 'baz']) { qux } ^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'does not register offense for array with allowed number of strings' do cop_config['MinSize'] = 4 expect_no_offenses('["one", "two", "three"]') end it 'does not register an offense for an array with comments in it' do expect_no_offenses(<<-RUBY.strip_indent) [ "foo", # comment here "bar", # this thing was done because of a bug "baz" # do not delete this line ] RUBY end it 'registers an offense for an array with comments outside of it' do inspect_source(<<-RUBY.strip_indent) [ "foo", "bar", "baz" ] # test RUBY expect(cop.offenses.size).to eq(1) end it 'auto-corrects an array of words' do new_source = autocorrect_source("['one', %q(two), 'three']") expect(new_source).to eq('%w(one two three)') end it 'auto-corrects an array of words and character constants' do new_source = autocorrect_source('[%|one|, %Q(two), ?\n, ?\t]') expect(new_source).to eq('%W(one two \n \t)') end it 'keeps the line breaks in place after auto-correct' do new_source = autocorrect_source(["['one',", "'two', 'three']"]) expect(new_source).to eq(['%w(one ', 'two three)'].join("\n")) end it 'detects right value of MinSize to use for --auto-gen-config' do inspect_source(<<-RUBY.strip_indent) ['one', 'two', 'three'] %w(a b c d) RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%w` or `%W` for an array of words.']) expect(cop.config_to_allow_offenses).to eq('EnforcedStyle' => 'percent', 'MinSize' => 4) end it 'detects when the cop must be disabled to avoid offenses' do inspect_source(<<-RUBY.strip_indent) ['one', 'two', 'three'] %w(a b) RUBY expect(cop.offenses.size).to eq(1) expect(cop.messages).to eq(['Use `%w` or `%W` for an array of words.']) expect(cop.config_to_allow_offenses).to eq('Enabled' => false) end it "doesn't fail in wacky ways when multiple cop instances are used" do # Regression test for GH issue #2740 cop1 = described_class.new(config) cop2 = described_class.new(config) RuboCop::Formatter::DisabledConfigFormatter.config_to_allow_offenses = {} RuboCop::Formatter::DisabledConfigFormatter.detected_styles = {} # Don't use `inspect_source`; it resets `config_to_allow_offenses` each # time, which suppresses the bug we are checking for _investigate(cop1, parse_source("['g', 'h']")) _investigate(cop2, parse_source('%w(a b c)')) expect(cop2.config_to_allow_offenses).to eq('EnforcedStyle' => 'percent', 'MinSize' => 3) end end context 'when EnforcedStyle is array' do let(:cop_config) do { 'MinSize' => 0, 'WordRegex' => /\A[\p{Word}]+\z/, 'EnforcedStyle' => 'brackets' } end it 'does not register an offense for arrays of single quoted strings' do expect_no_offenses("['one', 'two', 'three']") end it 'does not register an offense for arrays of double quoted strings' do expect_no_offenses('["one", "two", "three"]') end it 'registers an offense for a %w() array' do expect_offense(<<-RUBY.strip_indent) %w(one two three) ^^^^^^^^^^^^^^^^^ Use `[]` for an array of words. RUBY end it 'auto-corrects a %w() array' do new_source = autocorrect_source('%w(one two three)') expect(new_source).to eq("['one', 'two', 'three']") end it 'autocorrects a %w() array which uses single quotes' do new_source = autocorrect_source("%w(one's two's three's)") expect(new_source).to eq('["one\'s", "two\'s", "three\'s"]') end it 'autocorrects a %W() array which uses escapes' do new_source = autocorrect_source('%W(\\n \\t \\b \\v \\f)') expect(new_source).to eq('["\n", "\t", "\b", "\v", "\f"]') end it "doesn't fail on strings which are not valid UTF-8" do # Regression test, see GH issue 2671 expect_no_offenses(<<-'RUBY'.strip_indent) ["\xC0", "\xC2\x4a", "\xC2\xC2", "\x4a\x82", "\x82\x82", "\xe1\x82\x4a", ] RUBY end it "doesn't fail on strings which are not valid UTF-8" \ 'and encoding: binary is specified' do expect_no_offenses(<<-'RUBY'.strip_indent) # -*- encoding: binary -*- ["\xC0", "\xC2\x4a", "\xC2\xC2", "\x4a\x82", "\x82\x82", "\xe1\x82\x4a", ] RUBY end end context 'with a custom WordRegex configuration' do let(:cop_config) { { 'MinSize' => 0, 'WordRegex' => /\A[\w@.]+\z/ } } it 'registers an offense for arrays of email addresses' do expect_offense(<<-RUBY.strip_indent) ['a@example.com', 'b@example.com'] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `%w` or `%W` for an array of words. RUBY end it 'auto-corrects an array of email addresses' do new_source = autocorrect_source("['a@example.com', 'b@example.com']") expect(new_source).to eq('%w(a@example.com b@example.com)') end end context 'when the WordRegex configuration is not a Regexp' do let(:cop_config) { { 'WordRegex' => 'just_a_string' } } it 'still parses the code without raising an error' do expect { inspect_source('') }.not_to raise_error end end context 'with a WordRegex configuration which accepts almost anything' do let(:cop_config) { { 'MinSize' => 0, 'WordRegex' => /\S+/ } } it 'uses %W when autocorrecting strings with non-printable chars' do new_source = autocorrect_source('["\x1f\x1e", "hello"]') expect(new_source).to eq('%W(\u001F\u001E hello)') end it 'uses %w for strings which only appear to have an escape' do new_source = autocorrect_source("['hi\\tthere', 'again\\n']") expect(new_source).to eq('%w(hi\\tthere again\\n)') end end context 'with a treacherous WordRegex configuration' do let(:cop_config) { { 'MinSize' => 0, 'WordRegex' => /[\w \[\]\(\)]/ } } it "doesn't break when words contain whitespace" do new_source = autocorrect_source("['hi there', 'something\telse']") expect(new_source).to eq("['hi there', 'something\telse']") end it "doesn't break when words contain delimiters" do new_source = autocorrect_source("[')', ']', '(']") expect(new_source).to eq('%w(\\) ] \\()') end context 'when PreferredDelimiters is specified' do let(:other_cops) do { 'Style/PercentLiteralDelimiters' => { 'PreferredDelimiters' => { 'default' => '[]' } } } end it 'autocorrects an array with delimiters' do new_source = autocorrect_source("[')', ']', '(', '[']") expect(new_source).to eq('%w[) \\] ( \\[]') end end end end rubocop-0.52.1/spec/rubocop/cop/style/yoda_condition_spec.rb000066400000000000000000000056401322072016200241350ustar00rootroot00000000000000# frozen_string_literal: true require 'spec_helper' RSpec.describe RuboCop::Cop::Style::YodaCondition, :config do subject(:cop) { described_class.new(config) } let(:cop_config) { { 'EnforcedStyle' => 'all_comparison_operators' } } let(:error_message) { 'Reverse the order of the operands `%s`.' } # needed because of usage of safe navigation operator let(:ruby_version) { 2.3 } before { inspect_source(source) } shared_examples 'accepts' do |code| let(:source) { code } it 'does not register an offense' do expect(cop.offenses.empty?).to be(true) end end shared_examples 'offense' do |code| let(:source) { code } it "registers an offense for #{code}" do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to( eq(format(error_message, code)) ) end end shared_examples 'autocorrect' do |code, corrected| let(:source) { code } it 'autocorrects code' do expect(autocorrect_source(source)).to eq(corrected) end end it_behaves_like 'accepts', 'b.value == 2' it_behaves_like 'accepts', 'b&.value == 2' it_behaves_like 'accepts', '@value == 2' it_behaves_like 'accepts', '@@value == 2' it_behaves_like 'accepts', 'b = 1; b == 2' it_behaves_like 'accepts', '$var == 5' it_behaves_like 'accepts', 'foo == "bar"' it_behaves_like 'accepts', 'foo[0] > "bar" || baz != "baz"' it_behaves_like 'accepts', 'node = last_node.parent' it_behaves_like 'accepts', '(first_line - second_line) > 0' it_behaves_like 'accepts', '5 == 6' it_behaves_like 'accepts', '[1, 2, 3] <=> [4, 5, 6]' it_behaves_like 'accepts', '!true' it_behaves_like 'accepts', 'not true' it_behaves_like 'accepts', '0 <=> val' it_behaves_like 'accepts', '"foo" === bar' it_behaves_like 'offense', '"foo" == bar' it_behaves_like 'offense', 'nil == bar' it_behaves_like 'offense', 'false == active?' it_behaves_like 'offense', '15 != @foo' it_behaves_like 'offense', '42 < bar' context 'autocorrection' do it_behaves_like( 'autocorrect', 'if 10 == my_var; end', 'if my_var == 10; end' ) it_behaves_like( 'autocorrect', 'if 2 < bar;end', 'if bar > 2;end' ) it_behaves_like( 'autocorrect', 'foo = 42 if 42 > bar', 'foo = 42 if bar < 42' ) it_behaves_like( 'autocorrect', '42 <= foo ? bar : baz', 'foo >= 42 ? bar : baz' ) it_behaves_like( 'autocorrect', '42 >= foo ? bar : baz', 'foo <= 42 ? bar : baz' ) it_behaves_like( 'autocorrect', 'nil != foo ? bar : baz', 'foo != nil ? bar : baz' ) end context 'with EnforcedStyle: equality_operators_only' do let(:cop_config) { { 'EnforcedStyle' => 'equality_operators_only' } } it_behaves_like 'accepts', '42 < bar' it_behaves_like 'accepts', 'nil >= baz' it_behaves_like 'accepts', '3 < a && a < 5' it_behaves_like 'offense', '42 != answer' it_behaves_like 'offense', 'false == foo' end end rubocop-0.52.1/spec/rubocop/cop/style/zero_length_predicate_spec.rb000066400000000000000000000143271322072016200254750ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Style::ZeroLengthPredicate do subject(:cop) { described_class.new } before do inspect_source(source) end shared_examples 'code with offense' do |code, message, expected| context "when checking #{code}" do let(:source) { code } it 'registers an offense' do expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.message).to eq(message) expect(cop.highlights).to eq([code]) end it 'auto-corrects' do expect(autocorrect_source(code)).to eq expected end end end shared_examples 'code without offense' do |code| let(:source) { code } it 'does not register any offense' do expect(cop.offenses.empty?).to be(true) end end context 'with arrays' do it_behaves_like 'code with offense', '[1, 2, 3].length == 0', 'Use `empty?` instead of `length == 0`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].size == 0', 'Use `empty?` instead of `size == 0`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '0 == [1, 2, 3].length', 'Use `empty?` instead of `0 == length`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '0 == [1, 2, 3].size', 'Use `empty?` instead of `0 == size`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].length < 1', 'Use `empty?` instead of `length < 1`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].size < 1', 'Use `empty?` instead of `size < 1`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '1 > [1, 2, 3].length', 'Use `empty?` instead of `1 > length`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '1 > [1, 2, 3].size', 'Use `empty?` instead of `1 > size`.', '[1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].length > 0', 'Use `!empty?` instead of `length > 0`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].size > 0', 'Use `!empty?` instead of `size > 0`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].length != 0', 'Use `!empty?` instead of `length != 0`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '[1, 2, 3].size != 0', 'Use `!empty?` instead of `size != 0`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '0 < [1, 2, 3].length', 'Use `!empty?` instead of `0 < length`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '0 < [1, 2, 3].size', 'Use `!empty?` instead of `0 < size`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '0 != [1, 2, 3].length', 'Use `!empty?` instead of `0 != length`.', '![1, 2, 3].empty?' it_behaves_like 'code with offense', '0 != [1, 2, 3].size', 'Use `!empty?` instead of `0 != size`.', '![1, 2, 3].empty?' end context 'with hashes' do it_behaves_like 'code with offense', '{ a: 1, b: 2 }.size == 0', 'Use `empty?` instead of `size == 0`.', '{ a: 1, b: 2 }.empty?' it_behaves_like 'code with offense', '0 == { a: 1, b: 2 }.size', 'Use `empty?` instead of `0 == size`.', '{ a: 1, b: 2 }.empty?' it_behaves_like 'code with offense', '{ a: 1, b: 2 }.size != 0', 'Use `!empty?` instead of `size != 0`.', '!{ a: 1, b: 2 }.empty?' it_behaves_like 'code with offense', '0 != { a: 1, b: 2 }.size', 'Use `!empty?` instead of `0 != size`.', '!{ a: 1, b: 2 }.empty?' end context 'with strings' do it_behaves_like 'code with offense', '"string".size == 0', 'Use `empty?` instead of `size == 0`.', '"string".empty?' it_behaves_like 'code with offense', '0 == "string".size', 'Use `empty?` instead of `0 == size`.', '"string".empty?' it_behaves_like 'code with offense', '"string".size != 0', 'Use `!empty?` instead of `size != 0`.', '!"string".empty?' it_behaves_like 'code with offense', '0 != "string".size', 'Use `!empty?` instead of `0 != size`.', '!"string".empty?' end context 'with collection variables' do it_behaves_like 'code with offense', 'collection.size == 0', 'Use `empty?` instead of `size == 0`.', 'collection.empty?' it_behaves_like 'code with offense', '0 == collection.size', 'Use `empty?` instead of `0 == size`.', 'collection.empty?' it_behaves_like 'code with offense', 'collection.size != 0', 'Use `!empty?` instead of `size != 0`.', '!collection.empty?' it_behaves_like 'code with offense', '0 != collection.size', 'Use `!empty?` instead of `0 != size`.', '!collection.empty?' end context 'when name of the variable is `size` or `length`' do it_behaves_like 'code without offense', 'size == 0' it_behaves_like 'code without offense', 'length == 0' it_behaves_like 'code without offense', '0 == size' it_behaves_like 'code without offense', '0 == length' it_behaves_like 'code without offense', 'size <= 0' it_behaves_like 'code without offense', 'length > 0' it_behaves_like 'code without offense', '0 <= size' it_behaves_like 'code without offense', '0 > length' it_behaves_like 'code without offense', 'size != 0' it_behaves_like 'code without offense', 'length != 0' it_behaves_like 'code without offense', '0 != size' it_behaves_like 'code without offense', '0 != length' end end rubocop-0.52.1/spec/rubocop/cop/team_spec.rb000066400000000000000000000141031322072016200207130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Team do subject(:team) { described_class.new(cop_classes, config, options) } let(:cop_classes) { RuboCop::Cop::Cop.non_rails } let(:config) { RuboCop::ConfigLoader.default_configuration } let(:options) { nil } let(:ruby_version) { RuboCop::Config::KNOWN_RUBIES.last } before do RuboCop::ConfigLoader.default_configuration = nil end context 'when incompatible cops are correcting together' do include FileHelper let(:options) { { formatters: [], auto_correct: true } } let(:runner) { RuboCop::Runner.new(options, RuboCop::ConfigStore.new) } let(:file_path) { 'example.rb' } it 'auto corrects without SyntaxError', :isolated_environment do source = <<-'RUBY'.strip_indent foo.map{ |a| a.nil? } 'foo' + 'bar' + "#{baz}" i=i+1 def a self::b end RUBY corrected = <<-'RUBY'.strip_indent foo.map(&:nil?) 'foo' \ 'bar' \ "#{baz}" i += 1 def a b end RUBY create_file(file_path, source) runner.run([]) expect(File.read(file_path)).to eq(corrected) end end describe '#autocorrect?' do subject { team.autocorrect? } context 'when the option argument of .new is omitted' do subject { described_class.new(cop_classes, config).autocorrect? } it { is_expected.to be_falsey } end context 'when { auto_correct: true } is passed to .new' do let(:options) { { auto_correct: true } } it { is_expected.to be_truthy } end end describe '#debug?' do subject { team.debug? } context 'when the option argument of .new is omitted' do subject { described_class.new(cop_classes, config).debug? } it { is_expected.to be_falsey } end context 'when { debug: true } is passed to .new' do let(:options) { { debug: true } } it { is_expected.to be_truthy } end end describe '#inspect_file', :isolated_environment do include FileHelper let(:file_path) { '/tmp/example.rb' } let(:offenses) do source = RuboCop::ProcessedSource.from_file(file_path, ruby_version) team.inspect_file(source) end before do create_file(file_path, [ '#' * 90, 'puts test;' ]) end it 'returns offenses' do expect(offenses.empty?).to be(false) expect(offenses.all? { |o| o.is_a?(RuboCop::Cop::Offense) }).to be_truthy end context 'when Parser reports non-fatal warning for the file' do before do create_file(file_path, ['#' * 90, 'puts *test']) end let(:cop_names) { offenses.map(&:cop_name) } it 'returns Parser warning offenses' do expect(cop_names).to include('Lint/AmbiguousOperator') end it 'returns offenses from cops' do expect(cop_names).to include('Metrics/LineLength') end end context 'when autocorrection is enabled' do let(:options) { { auto_correct: true } } before do create_file(file_path, 'puts "string"') end it 'does autocorrection' do source = RuboCop::ProcessedSource.from_file(file_path, ruby_version) team.inspect_file(source) corrected_source = File.read(file_path) expect(corrected_source).to eq("puts 'string'\n") end it 'still returns offenses' do expect(offenses.first.cop_name).to eq('Style/StringLiterals') end end end describe '#cops' do subject(:cops) { team.cops } it 'returns cop instances' do expect(cops.empty?).to be(false) expect(cops.all? { |c| c.is_a?(RuboCop::Cop::Cop) }).to be_truthy end context 'when only some cop classes are passed to .new' do let(:cop_classes) do RuboCop::Cop::Registry.new( [RuboCop::Cop::Lint::Void, RuboCop::Cop::Metrics::LineLength] ) end it 'returns only instances of the classes' do expect(cops.size).to eq(2) cops.sort! { |a, b| a.name <=> b.name } expect(cops[0].name).to eq('Lint/Void') expect(cops[1].name).to eq('Metrics/LineLength') end end context 'when some classes are disabled with config' do let(:disabled_config) do %w[ Lint/Void Metrics/LineLength ].each_with_object(RuboCop::Config.new) do |cop_name, accum| accum[cop_name] = { 'Enabled' => false } end end let(:config) do RuboCop::ConfigLoader.merge_with_default(disabled_config, '') end let(:cop_names) { cops.map(&:name) } it 'does not return instances of the classes' do expect(cops.empty?).to be(false) expect(cop_names).not_to include('Lint/Void') expect(cop_names).not_to include('Metrics/LineLength') end end end describe '#forces' do subject(:forces) { team.forces } let(:cop_classes) { RuboCop::Cop::Cop.non_rails } it 'returns force instances' do expect(forces.empty?).to be(false) forces.each do |force| expect(force.is_a?(RuboCop::Cop::Force)).to be(true) end end context 'when a cop joined a force' do let(:cop_classes) do RuboCop::Cop::Registry.new([RuboCop::Cop::Lint::UselessAssignment]) end it 'returns the force' do expect(forces.size).to eq(1) expect(forces.first.is_a?(RuboCop::Cop::VariableForce)).to be(true) end end context 'when multiple cops joined a same force' do let(:cop_classes) do RuboCop::Cop::Registry.new( [ RuboCop::Cop::Lint::UselessAssignment, RuboCop::Cop::Lint::ShadowingOuterLocalVariable ] ) end it 'returns only one force instance' do expect(forces.size).to eq(1) end end context 'when no cops joined force' do let(:cop_classes) do RuboCop::Cop::Registry.new([RuboCop::Cop::Style::For]) end it 'returns nothing' do expect(forces.empty?).to be(true) end end end end rubocop-0.52.1/spec/rubocop/cop/util_spec.rb000066400000000000000000000152251322072016200207500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::Util do class TestUtil include RuboCop::Cop::Util end describe '#line_range' do let(:source) do <<-RUBY foo = 1 bar = 2 class Test def some_method do_something end end baz = 8 RUBY end let(:processed_source) { parse_source(source) } let(:ast) { processed_source.ast } let(:node) { ast.each_node.find(&:class_type?) } context 'when Source::Range object is passed' do it 'returns line range of that' do line_range = described_class.line_range(node.loc.expression) expect(line_range).to eq(3..7) end end context 'when AST::Node object is passed' do it 'returns line range of the expression' do line_range = described_class.line_range(node) expect(line_range).to eq(3..7) end end end describe 'source indicated by #range_with_surrounding_comma' do subject do obj = TestUtil.new obj.instance_exec(processed_source) { |src| @processed_source = src } r = obj.send(:range_with_surrounding_comma, input_range, side) processed_source.buffer.source[r.begin_pos...r.end_pos] end let(:source) { 'raise " ,Error, "' } let(:processed_source) { parse_source(source) } let(:input_range) do Parser::Source::Range.new(processed_source.buffer, 9, 14) end context 'when side is :both' do let(:side) { :both } it { is_expected.to eq(',Error,') } end context 'when side is :left' do let(:side) { :left } it { is_expected.to eq(',Error') } end context 'when side is :right' do let(:side) { :right } it { is_expected.to eq('Error,') } end end describe 'source indicated by #range_with_surrounding_space' do subject do obj = TestUtil.new obj.instance_exec(processed_source) { |src| @processed_source = src } r = obj.send(:range_with_surrounding_space, range: input_range, side: side) processed_source.buffer.source[r.begin_pos...r.end_pos] end let(:source) { 'f { a(2) }' } let(:processed_source) { parse_source(source) } let(:input_range) do Parser::Source::Range.new(processed_source.buffer, 5, 9) end context 'when side is :both' do let(:side) { :both } it { is_expected.to eq(' a(2) ') } end context 'when side is :left' do let(:side) { :left } it { is_expected.to eq(' a(2)') } end context 'when side is :right' do let(:side) { :right } it { is_expected.to eq('a(2) ') } end end describe 'source indicated by #range_by_whole_lines' do subject do r = output_range processed_source.buffer.source[r.begin_pos...r.end_pos] end let(:source) { <<-RUBY.strip_indent } puts 'example' puts 'another example' something_else RUBY let(:processed_source) { parse_source(source) } # `input_source` defined in contexts let(:begin_pos) { source.index(input_source) } let(:end_pos) { begin_pos + input_source.length } let(:input_range) do Parser::Source::Range.new(processed_source.buffer, begin_pos, end_pos) end let(:output_range) do obj = TestUtil.new obj.instance_exec(processed_source) { |src| @processed_source = src } obj.send(:range_by_whole_lines, input_range, include_final_newline: include_final_newline) end shared_examples 'final newline behavior' do context 'without include_final_newline' do let(:include_final_newline) { false } it { is_expected.to eq(expected) } end context 'with include_final_newline' do let(:include_final_newline) { true } it { is_expected.to eq(expected + "\n") } end end context 'when part of a single line is selected' do let(:input_source) { "'example'" } let(:expected) { "puts 'example'" } include_examples 'final newline behavior' end context 'with a whole line except newline selected' do let(:input_source) { "puts 'example'" } let(:expected) { "puts 'example'" } include_examples 'final newline behavior' end context 'with a whole line plus beginning of next line' do let(:input_source) { "puts 'example'\n" } let(:expected) { "puts 'example'\nputs 'another example'" } include_examples 'final newline behavior' end context 'with end of one line' do let(:begin_pos) { 14 } let(:end_pos) { 14 } let(:expected) { "puts 'example'" } include_examples 'final newline behavior' end context 'with beginning of one line' do let(:begin_pos) { 15 } let(:end_pos) { 15 } let(:expected) { "puts 'another example'" } include_examples 'final newline behavior' end context 'with parts of two lines' do let(:input_source) { "'example'\nputs 'another" } let(:expected) { "puts 'example'\nputs 'another example'" } include_examples 'final newline behavior' end context 'with parts of four lines' do let(:input_source) { "'example'\nputs 'another example'\n\nso" } let(:expected) { source.chomp } include_examples 'final newline behavior' end context "when source doesn't end with a newline" do let(:source) { "example\nwith\nno\nnewline_at_end" } let(:input_source) { 'line_at_e' } context 'without include_final_newline' do let(:include_final_newline) { false } it { is_expected.to eq('newline_at_end') } end context 'with include_final_newline' do let(:include_final_newline) { true } it { is_expected.to eq('newline_at_end') } end end end describe '#to_symbol_literal' do [ ['foo', ':foo'], ['foo?', ':foo?'], ['foo!', ':foo!'], ['@foo', ':@foo'], ['@@foo', ':@@foo'], ['$\\', ':$\\'], ['$a', ':$a'], ['==', ':=='], ['a-b', ":'a-b'"] ].each do |string, expectation| context "when #{string}" do it "returns #{expectation}" do expect(described_class.to_symbol_literal(string)).to eq(expectation) end end end end describe '#to_supported_styles' do subject { described_class.to_supported_styles(enforced_style) } context 'when EnforcedStyle' do let(:enforced_style) { 'EnforcedStyle' } it { is_expected.to eq('SupportedStyles') } end context 'when EnforcedStyleInsidePipes' do let(:enforced_style) { 'EnforcedStyleInsidePipes' } it { is_expected.to eq('SupportedStylesInsidePipes') } end end end rubocop-0.52.1/spec/rubocop/cop/variable_force/000077500000000000000000000000001322072016200213725ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/cop/variable_force/assignment_spec.rb000066400000000000000000000102351322072016200251020ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::VariableForce::Assignment do include RuboCop::AST::Sexp let(:ast) do RuboCop::ProcessedSource.new(source, ruby_version).ast end let(:source) do <<-RUBY class SomeClass def some_method(flag) puts 'Hello World!' if flag > 0 foo = 1 end end end RUBY end let(:def_node) { ast.each_node.find(&:def_type?) } let(:lvasgn_node) { ast.each_node.find(&:lvasgn_type?) } let(:name) { lvasgn_node.children.first } let(:scope) { RuboCop::Cop::VariableForce::Scope.new(def_node) } let(:variable) do RuboCop::Cop::VariableForce::Variable.new(name, lvasgn_node, scope) end let(:assignment) { described_class.new(lvasgn_node, variable) } describe '.new' do let(:variable) { double('variable') } context 'when an assignment node is passed' do it 'does not raise error' do node = s(:lvasgn, :foo) expect { described_class.new(node, variable) }.not_to raise_error end end context 'when an argument declaration node is passed' do it 'raises error' do node = s(:arg, :foo) expect { described_class.new(node, variable) } .to raise_error(ArgumentError) end end context 'when any other type node is passed' do it 'raises error' do node = s(:def) expect { described_class.new(node, variable) } .to raise_error(ArgumentError) end end end describe '#name' do it 'returns the variable name' do expect(assignment.name).to eq(:foo) end end describe '#meta_assignment_node' do context 'when it is += operator assignment' do let(:source) do <<-RUBY def some_method foo += 1 end RUBY end it 'returns op_asgn node' do expect(assignment.meta_assignment_node.type).to eq(:op_asgn) end end context 'when it is ||= operator assignment' do let(:source) do <<-RUBY def some_method foo ||= 1 end RUBY end it 'returns or_asgn node' do expect(assignment.meta_assignment_node.type).to eq(:or_asgn) end end context 'when it is &&= operator assignment' do let(:source) do <<-RUBY def some_method foo &&= 1 end RUBY end it 'returns and_asgn node' do expect(assignment.meta_assignment_node.type).to eq(:and_asgn) end end context 'when it is multiple assignment' do let(:source) do <<-RUBY def some_method foo, bar = [1, 2] end RUBY end it 'returns masgn node' do expect(assignment.meta_assignment_node.type).to eq(:masgn) end end end describe '#operator' do context 'when it is normal assignment' do let(:source) do <<-RUBY def some_method foo = 1 end RUBY end it 'returns =' do expect(assignment.operator).to eq('=') end end context 'when it is += operator assignment' do let(:source) do <<-RUBY def some_method foo += 1 end RUBY end it 'returns +=' do expect(assignment.operator).to eq('+=') end end context 'when it is ||= operator assignment' do let(:source) do <<-RUBY def some_method foo ||= 1 end RUBY end it 'returns ||=' do expect(assignment.operator).to eq('||=') end end context 'when it is &&= operator assignment' do let(:source) do <<-RUBY def some_method foo &&= 1 end RUBY end it 'returns &&=' do expect(assignment.operator).to eq('&&=') end end context 'when it is multiple assignment' do let(:source) do <<-RUBY def some_method foo, bar = [1, 2] end RUBY end it 'returns =' do expect(assignment.operator).to eq('=') end end end end rubocop-0.52.1/spec/rubocop/cop/variable_force/reference_spec.rb000066400000000000000000000007201322072016200246660ustar00rootroot00000000000000# frozen_string_literal: true require 'rubocop/ast/sexp' RSpec.describe RuboCop::Cop::VariableForce::Reference do include RuboCop::AST::Sexp describe '.new' do context 'when non variable reference node is passed' do it 'raises error' do node = s(:def) scope = RuboCop::Cop::VariableForce::Scope.new(s(:class)) expect { described_class.new(node, scope) } .to raise_error(ArgumentError) end end end end rubocop-0.52.1/spec/rubocop/cop/variable_force/scope_spec.rb000066400000000000000000000177351322072016200240570ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::VariableForce::Scope do include RuboCop::AST::Sexp subject(:scope) { described_class.new(scope_node) } let(:ast) do RuboCop::ProcessedSource.new(source, ruby_version).ast end let(:scope_node) { ast.each_node(scope_node_type).first } describe '.new' do context 'when lvasgn node is passed' do it 'accepts that as top level scope' do node = s(:lvasgn) expect { described_class.new(node) }.not_to raise_error end end context 'when begin node is passed' do it 'accepts that as top level scope' do node = s(:begin) expect { described_class.new(node) }.not_to raise_error end end end describe '#name' do context 'when the scope is instance method definition' do let(:source) { <<-RUBY } def some_method end RUBY let(:scope_node_type) { :def } it 'returns the method name' do expect(scope.name).to eq(:some_method) end end context 'when the scope is singleton method definition' do let(:source) { <<-RUBY } def self.some_method end RUBY let(:scope_node_type) { :defs } it 'returns the method name' do expect(scope.name).to eq(:some_method) end end end describe '#body_node' do shared_examples 'returns the body node' do it 'returns the body node' do expect(scope.body_node.children[1]).to eq(:this_is_target) end end context 'when the scope is instance method' do let(:source) do <<-RUBY def some_method this_is_target end RUBY end let(:scope_node_type) { :def } include_examples 'returns the body node' end context 'when the scope is singleton method' do let(:source) do <<-RUBY def self.some_method this_is_target end RUBY end let(:scope_node_type) { :defs } include_examples 'returns the body node' end context 'when the scope is module' do let(:source) do <<-RUBY module SomeModule this_is_target end RUBY end let(:scope_node_type) { :module } include_examples 'returns the body node' end context 'when the scope is class' do let(:source) do <<-RUBY class SomeClass this_is_target end RUBY end let(:scope_node_type) { :class } include_examples 'returns the body node' end context 'when the scope is singleton class' do let(:source) do <<-RUBY class << self this_is_target end RUBY end let(:scope_node_type) { :sclass } include_examples 'returns the body node' end context 'when the scope is block' do let(:source) do <<-RUBY 1.times do this_is_target end RUBY end let(:scope_node_type) { :block } include_examples 'returns the body node' end context 'when the scope is top level' do let(:source) do <<-RUBY this_is_target RUBY end let(:scope_node_type) { :send } include_examples 'returns the body node' end end describe '#include?' do subject do scope.include?(target_node) end let(:source) { <<-RUBY } class SomeClass def self.some_method(arg1, arg2) do_something 1.times do foo = 1 end end end RUBY let(:scope_node_type) { :defs } context 'with ancestor node the scope does not include' do let(:target_node) do ast end it { is_expected.to be false } end context 'with node of the scope itself' do let(:target_node) do ast.each_node.find(&:defs_type?) end it { is_expected.to be false } end context 'with child node the scope does not include' do let(:target_node) do ast.each_node.find(&:self_type?) end it { is_expected.to be false } end context 'with child node the scope includes' do let(:target_node) do ast.each_node.find(&:send_type?) end it { is_expected.to be true } end context 'with descendant node the scope does not include' do let(:target_node) do ast.each_node.find(&:lvasgn_type?) end it { is_expected.to be false } end end describe '#each_node' do shared_examples 'yields' do |description| it "yields #{description}" do yielded_types = [] scope.each_node do |node| yielded_types << node.type end expect(yielded_types).to eq(expected_types.map(&:to_sym)) end end describe 'outer scope boundary handling' do context 'when the scope is instance method' do let(:source) { <<-RUBY } def some_method(arg1, arg2) :body end RUBY let(:scope_node_type) { :def } let(:expected_types) { %w[args arg arg sym] } include_examples 'yields', 'the argument and the body nodes' end context 'when the scope is singleton method' do let(:source) { <<-RUBY } def self.some_method(arg1, arg2) :body end RUBY let(:scope_node_type) { :defs } let(:expected_types) { %w[args arg arg sym] } include_examples 'yields', 'the argument and the body nodes' end context 'when the scope is module' do let(:source) { <<-RUBY } module SomeModule :body end RUBY let(:scope_node_type) { :module } let(:expected_types) { %w[sym] } include_examples 'yields', 'the body nodes' end context 'when the scope is class' do let(:source) { <<-RUBY } some_super_class = Class.new class SomeClass < some_super_class :body end RUBY let(:scope_node_type) { :class } let(:expected_types) { %w[sym] } include_examples 'yields', 'the body nodes' end context 'when the scope is singleton class' do let(:source) { <<-RUBY } some_object = Object.new class << some_object :body end RUBY let(:scope_node_type) { :sclass } let(:expected_types) { %w[sym] } include_examples 'yields', 'the body nodes' end context 'when the scope is block' do let(:source) { <<-RUBY } 1.times do |arg1, arg2| :body end RUBY let(:scope_node_type) { :block } let(:expected_types) { %w[args arg arg sym] } include_examples 'yields', 'the argument and the body nodes' end context 'when the scope is top level' do let(:source) { <<-RUBY } :body RUBY let(:scope_node_type) { :sym } let(:expected_types) { %w[sym] } include_examples 'yields', 'the body nodes' end end describe 'inner scope boundary handling' do context "when there's a method invocation with block" do let(:source) { <<-RUBY } foo = 1 do_something(1, 2) do |arg| :body end foo RUBY let(:scope_node_type) { :begin } let(:expected_types) { %w[begin lvasgn int block send int int lvar] } include_examples 'yields', 'only the block node and the child send node' end context "when there's a singleton method definition" do let(:source) { <<-RUBY } foo = 1 def self.some_method(arg1, arg2) :body end foo RUBY let(:scope_node_type) { :begin } let(:expected_types) { %w[begin lvasgn int defs self lvar] } include_examples 'yields', 'only the defs node and the method host node' end end end end rubocop-0.52.1/spec/rubocop/cop/variable_force/variable_spec.rb000066400000000000000000000027041322072016200245210ustar00rootroot00000000000000# frozen_string_literal: true require 'rubocop/ast/sexp' RSpec.describe RuboCop::Cop::VariableForce::Variable do include RuboCop::AST::Sexp describe '.new' do context 'when non variable declaration node is passed' do it 'raises error' do name = :foo declaration_node = s(:def) scope = RuboCop::Cop::VariableForce::Scope.new(s(:class)) expect { described_class.new(name, declaration_node, scope) } .to raise_error(ArgumentError) end end end describe '#referenced?' do subject { variable.referenced? } let(:name) { :foo } let(:declaration_node) { s(:arg, name) } let(:scope) { double('scope').as_null_object } let(:variable) { described_class.new(name, declaration_node, scope) } context 'when the variable is not assigned' do it { is_expected.to be_falsey } context 'and the variable is referenced' do before do variable.reference!(s(:lvar, name)) end it { is_expected.to be_truthy } end end context 'when the variable has an assignment' do before do variable.assign(s(:lvasgn, name)) end context 'and the variable is not yet referenced' do it { is_expected.to be_falsey } end context 'and the variable is referenced' do before do variable.reference!(s(:lvar, name)) end it { is_expected.to be_truthy } end end end end rubocop-0.52.1/spec/rubocop/cop/variable_force/variable_table_spec.rb000066400000000000000000000206051322072016200256700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Cop::VariableForce::VariableTable do include RuboCop::AST::Sexp subject(:variable_table) { described_class.new } describe '#push_scope' do it 'returns pushed scope object' do node = s(:def) scope = variable_table.push_scope(node) expect(scope).to equal(variable_table.current_scope) expect(scope.node).to equal(node) end end describe '#pop_scope' do before do node = s(:def) variable_table.push_scope(node) end it 'returns popped scope object' do last_scope = variable_table.current_scope popped_scope = variable_table.pop_scope expect(popped_scope).to equal(last_scope) end end describe '#current_scope_level' do before do variable_table.push_scope(s(:def)) end it 'increases by pushing scope' do last_scope_level = variable_table.current_scope_level variable_table.push_scope(s(:def)) expect(variable_table.current_scope_level) .to eq(last_scope_level + 1) end it 'decreases by popping scope' do last_scope_level = variable_table.current_scope_level variable_table.pop_scope expect(variable_table.current_scope_level) .to eq(last_scope_level - 1) end end describe '#declare_variable' do before do 2.times do node = s(:def) variable_table.push_scope(node) end end it 'adds variable to current scope with its name as key' do node = s(:lvasgn, :foo) variable_table.declare_variable(:foo, node) expect(variable_table.current_scope.variables.key?(:foo)) .to be(true) expect(variable_table.scope_stack[-2].variables.empty?) .to be(true) variable = variable_table.current_scope.variables[:foo] expect(variable.declaration_node).to equal(node) end it 'returns the added variable' do node = s(:lvasgn, :foo) variable = variable_table.declare_variable(:foo, node) expect(variable.declaration_node).to equal(node) end end describe '#find_variable' do before do variable_table.push_scope(s(:class)) variable_table.declare_variable(:baz, s(:lvasgn, :baz)) variable_table.push_scope(s(:def)) variable_table.declare_variable(:bar, s(:lvasgn, :bar)) end context 'when current scope is block' do before do variable_table.push_scope(s(:block)) end context 'when a variable with the target name exists ' \ 'in current scope' do before do variable_table.declare_variable(:foo, s(:lvasgn, :foo)) end context 'and does not exist in outer scope' do it 'returns the current scope variable' do found_variable = variable_table.find_variable(:foo) expect(found_variable.name).to eq(:foo) end end context 'and also exists in outer scope' do before do variable_table.declare_variable(:bar, s(:lvasgn, :bar)) end it 'returns the current scope variable' do found_variable = variable_table.find_variable(:bar) expect(found_variable.name).to equal(:bar) expect( variable_table.current_scope.variables.value?(found_variable) ).to be(true) expect( variable_table.scope_stack[-2].variables.value?(found_variable) ).to be(false) end end end context 'when a variable with the target name does not exist ' \ 'in current scope' do context 'but exists in the direct outer scope' do it 'returns the direct outer scope variable' do found_variable = variable_table.find_variable(:bar) expect(found_variable.name).to equal(:bar) end end context 'but exists in a indirect outer scope' do context 'when the direct outer scope is block' do before do variable_table.pop_scope variable_table.pop_scope variable_table.push_scope(s(:block)) variable_table.push_scope(s(:block)) end it 'returns the indirect outer scope variable' do found_variable = variable_table.find_variable(:baz) expect(found_variable.name).to equal(:baz) end end context 'when the direct outer scope is not block' do it 'returns nil' do found_variable = variable_table.find_variable(:baz) expect(found_variable.nil?).to be(true) end end end context 'and does not exist in all outer scopes' do it 'returns nil' do found_variable = variable_table.find_variable(:non) expect(found_variable.nil?).to be(true) end end end end context 'when current scope is not block' do before do variable_table.push_scope(s(:def)) end context 'when a variable with the target name exists ' \ 'in current scope' do before do variable_table.declare_variable(:foo, s(:lvasgn, :foo)) end context 'and does not exist in outer scope' do it 'returns the current scope variable' do found_variable = variable_table.find_variable(:foo) expect(found_variable.name).to eq(:foo) end end context 'and also exists in outer scope' do it 'returns the current scope variable' do found_variable = variable_table.find_variable(:foo) expect(found_variable.name).to equal(:foo) expect( variable_table.current_scope.variables.value?(found_variable) ).to be(true) expect( variable_table.scope_stack[-2].variables.value?(found_variable) ).to be(false) end end end context 'when a variable with the target name does not exist ' \ 'in current scope' do context 'but exists in the direct outer scope' do it 'returns nil' do found_variable = variable_table.find_variable(:bar) expect(found_variable.nil?).to be(true) end end context 'and does not exist in all outer scopes' do it 'returns nil' do found_variable = variable_table.find_variable(:non) expect(found_variable.nil?).to be(true) end end end end end describe '#find_variable with an empty scope stack' do it 'returns nil' do found_variable = variable_table.find_variable(:unknown) expect(found_variable.nil?).to be(true) end end describe '#accessible_variables' do let(:accessible_variable_names) do variable_table.accessible_variables.map(&:name) end before do variable_table.push_scope(s(:class)) end context 'when there are no variables' do it 'returns empty array' do expect(variable_table.accessible_variables.empty?).to be(true) end end context 'when the current scope has some variables' do before do variable_table.declare_variable(:foo, s(:lvasgn, :foo)) variable_table.declare_variable(:bar, s(:lvasgn, :bar)) end it 'returns all the variables' do expect(accessible_variable_names).to contain_exactly(:foo, :bar) end end context 'when the direct outer scope has some variables' do before do variable_table.declare_variable(:foo, s(:lvasgn, :foo)) end context 'and the current scope is block' do before do variable_table.push_scope(s(:block)) variable_table.declare_variable(:bar, s(:lvasgn, :bar)) variable_table.declare_variable(:baz, s(:lvasgn, :baz)) end it 'returns the current and direct outer scope variables' do expect(accessible_variable_names) .to contain_exactly(:foo, :bar, :baz) end end context 'and the current scope is not block' do before do variable_table.push_scope(s(:def)) variable_table.declare_variable(:bar, s(:lvasgn, :bar)) variable_table.declare_variable(:baz, s(:lvasgn, :baz)) end it 'returns only the current scope variables' do expect(accessible_variable_names).to contain_exactly(:bar, :baz) end end end end end rubocop-0.52.1/spec/rubocop/cop/variable_force_spec.rb000066400000000000000000000014461322072016200227360ustar00rootroot00000000000000# frozen_string_literal: true require 'rubocop/ast/sexp' RSpec.describe RuboCop::Cop::VariableForce do include RuboCop::AST::Sexp subject(:force) { described_class.new([]) } describe '#process_node' do before do force.variable_table.push_scope(s(:def)) end context 'when processing lvar node' do let(:node) { s(:lvar, :foo) } context 'when the variable is not yet declared' do it 'does not raise error' do expect { force.process_node(node) }.not_to raise_error end end end context 'when processing an empty regex' do let(:node) { s(:match_with_lvasgn, s(:regexp, s(:regopt)), s(:str)) } it 'does not raise an error' do expect { force.process_node(node) }.not_to raise_error end end end end rubocop-0.52.1/spec/rubocop/formatter/000077500000000000000000000000001322072016200176515ustar00rootroot00000000000000rubocop-0.52.1/spec/rubocop/formatter/base_formatter_spec.rb000066400000000000000000000115231322072016200242070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::BaseFormatter do include FileHelper describe 'how the API methods are invoked', :isolated_environment do subject(:formatter) { double('formatter').as_null_object } let(:runner) { RuboCop::Runner.new({}, RuboCop::ConfigStore.new) } let(:output) { $stdout.string } before do create_file('1_offense.rb', '#' * 90) create_file('4_offenses.rb', ['puts x ', 'test;', 'top;', '#' * 90]) create_file('no_offense.rb', '# frozen_string_literal: true') allow(RuboCop::Formatter::SimpleTextFormatter) .to receive(:new).and_return(formatter) $stdout = StringIO.new # avoid intermittent failure caused when another test set global # options on ConfigLoader RuboCop::ConfigLoader.clear_options end after do $stdout = STDOUT end def run runner.run([]) end describe 'invocation order' do subject(:formatter) do formatter = double('formatter') %i[started file_started file_finished finished output] .each do |message| allow(formatter).to receive(message) do puts message.to_s unless message == :output end end formatter end it 'is called in the proper sequence' do run expect(output).to eq(<<-OUTPUT.strip_indent) started file_started file_finished file_started file_finished file_started file_finished finished OUTPUT end end shared_examples 'receives all file paths' do |method_name| it 'receives all file paths' do expected_paths = [ '1_offense.rb', '4_offenses.rb', 'no_offense.rb' ].map { |path| File.expand_path(path) }.sort expect(formatter).to receive(method_name) do |all_files| expect(all_files.sort).to eq(expected_paths) end run end describe 'the passed files paths' do it 'is frozen' do expect(formatter).to receive(method_name) do |all_files| all_files.each do |path| expect(path.frozen?).to be(true) end end run end end end describe '#started' do include_examples 'receives all file paths', :started end describe '#finished' do context 'when RuboCop finished inspecting all files normally' do include_examples 'receives all file paths', :started end context 'when RuboCop is interrupted by user' do it 'receives only processed file paths' do class << formatter attr_reader :processed_file_count def file_finished(_file, _offenses) @processed_file_count ||= 0 @processed_file_count += 1 end end allow(runner).to receive(:aborting?) do formatter.processed_file_count == 2 end expect(formatter).to receive(:finished) do |processed_files| expect(processed_files.size).to eq(2) end run end end end shared_examples 'receives a file path' do |method_name| it 'receives a file path' do expect(formatter).to receive(method_name) .with(File.expand_path('1_offense.rb'), anything) expect(formatter).to receive(method_name) .with(File.expand_path('4_offenses.rb'), anything) expect(formatter).to receive(method_name) .with(File.expand_path('no_offense.rb'), anything) run end describe 'the passed path' do it 'is frozen' do expect(formatter) .to receive(method_name).exactly(3).times do |path| expect(path.frozen?).to be(true) end run end end end describe '#file_started' do include_examples 'receives a file path', :file_started it 'receives file specific information hash' do expect(formatter).to receive(:file_started) .with(anything, an_instance_of(Hash)).exactly(3).times run end end describe '#file_finished' do include_examples 'receives a file path', :file_finished it 'receives an array of detected offenses for the file' do expect(formatter).to receive(:file_finished) .exactly(3).times do |file, offenses| case File.basename(file) when '1_offense.rb' expect(offenses.size).to eq(1) when '4_offenses.rb' expect(offenses.size).to eq(4) when 'no_offense.rb' expect(offenses.empty?).to be(true) else raise end expect(offenses.all? { |o| o.is_a?(RuboCop::Cop::Offense) }) .to be_truthy end run end end end end rubocop-0.52.1/spec/rubocop/formatter/clang_style_formatter_spec.rb000066400000000000000000000070561322072016200256070ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::ClangStyleFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } describe '#report_file' do let(:file) { '/path/to/file' } let(:offense) do RuboCop::Cop::Offense.new(:convention, location, 'This is a message.', 'CopName', status) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end it 'displays text containing the offending source line' do cop = RuboCop::Cop::Cop.new source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = ('aa'..'az').to_a.join($RS) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 0, 2), message: 'message 1' ) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 30, 32), message: 'message 2' ) formatter.report_file('test', cop.offenses) expect(output.string).to eq <<-OUTPUT.strip_indent test:1:1: C: message 1 aa ^^ test:11:1: C: message 2 ak ^^ OUTPUT end context 'when the source line is blank' do it 'does not display offending source line' do cop = RuboCop::Cop::Cop.new source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = [' ', 'yaba'].join($RS) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 0, 2), message: 'message 1' ) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 6, 10), message: 'message 2' ) formatter.report_file('test', cop.offenses) expect(output.string).to eq <<-OUTPUT.strip_indent test:1:1: C: message 1 test:2:1: C: message 2 yaba ^^^^ OUTPUT end end context 'when the offending source spans multiple lines' do it 'displays the first line with ellipses' do source = <<-RUBY.strip_indent do_something([this, is, target]) RUBY source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = source location = Parser::Source::Range.new(source_buffer, source.index('['), source.index(']') + 1) cop = RuboCop::Cop::Cop.new cop.add_offense(nil, location: location, message: 'message 1') formatter.report_file('test', cop.offenses) expect(output.string) .to eq <<-OUTPUT.strip_indent test:1:14: C: message 1 do_something([this, #{described_class::ELLIPSES} ^^^^^^ OUTPUT end end context 'when the offense is not corrected' do let(:status) { :uncorrected } it 'prints message as-is' do formatter.report_file(file, [offense]) expect(output.string) .to include(': This is a message.') end end context 'when the offense is automatically corrected' do let(:status) { :corrected } it 'prints [Corrected] along with message' do formatter.report_file(file, [offense]) expect(output.string) .to include(': [Corrected] This is a message.') end end end end rubocop-0.52.1/spec/rubocop/formatter/colorizable_spec.rb000066400000000000000000000046131322072016200235210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::Colorizable do let(:formatter_class) do Class.new(RuboCop::Formatter::BaseFormatter) do include RuboCop::Formatter::Colorizable end end let(:options) { {} } let(:formatter) do formatter_class.new(output, options) end let(:output) { double('output') } around do |example| original_state = Rainbow.enabled begin example.run ensure Rainbow.enabled = original_state end end describe '#colorize' do subject { formatter.colorize('foo', :red) } shared_examples 'does nothing' do it 'does nothing' do is_expected.to eq('foo') end end context 'when the global Rainbow.enabled is true' do before do Rainbow.enabled = true end context "and the formatter's output is a tty" do before do allow(output).to receive(:tty?).and_return(true) end it 'colorizes the passed string' do is_expected.to eq("\e[31mfoo\e[0m") end end context "and the formatter's output is not a tty" do before do allow(output).to receive(:tty?).and_return(false) end include_examples 'does nothing' end context 'and output is not a tty, but --color option was provided' do let(:options) { { color: true } } before do allow(output).to receive(:tty?).and_return(false) end it 'colorizes the passed string' do is_expected.to eq("\e[31mfoo\e[0m") end end end context 'when the global Rainbow.enabled is false' do before do Rainbow.enabled = false end context "and the formatter's output is a tty" do before do allow(output).to receive(:tty?).and_return(true) end include_examples 'does nothing' end context "and the formatter's output is not a tty" do before do allow(output).to receive(:tty?).and_return(false) end include_examples 'does nothing' end end end %i[ black red green yellow blue magenta cyan white ].each do |color| describe "##{color}" do it "invokes #colorize(string, #{color}" do expect(formatter).to receive(:colorize).with('foo', color) formatter.send(color, 'foo') end end end end rubocop-0.52.1/spec/rubocop/formatter/disabled_config_formatter_spec.rb000066400000000000000000000132141322072016200263700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::DisabledConfigFormatter, :isolated_environment do # rubocop:disable Metrics/LineLength include FileHelper subject(:formatter) { described_class.new(output) } let(:output) do io = StringIO.new def io.path '.rubocop_todo.yml' end io end let(:offenses) do [RuboCop::Cop::Offense.new(:convention, location, 'message', 'Cop1'), RuboCop::Cop::Offense.new(:convention, location, 'message', 'Cop2')] end let(:location) { OpenStruct.new(line: 1, column: 5) } let(:heading) do format(described_class::HEADING, expected_heading_command) + "\n" end let(:expected_heading_command) do 'rubocop --auto-gen-config' end around do |example| original_stdout = $stdout original_stderr = $stderr $stdout = StringIO.new $stderr = StringIO.new example.run $stdout = original_stdout $stderr = original_stderr end before do # Avoid intermittent failure when another test set ConfigLoader options RuboCop::ConfigLoader.clear_options end context 'when any offenses are detected' do before do formatter.started(['test_a.rb', 'test_b.rb']) formatter.file_started('test_a.rb', {}) formatter.file_finished('test_a.rb', offenses) formatter.file_started('test_b.rb', {}) formatter.file_finished('test_b.rb', [offenses.first]) formatter.finished(['test_a.rb', 'test_b.rb']) end let(:expected_rubocop_todo) do [heading, '# Offense count: 2', 'Cop1:', ' Exclude:', " - 'test_a.rb'", " - 'test_b.rb'", '', '# Offense count: 1', 'Cop2:', ' Exclude:', " - 'test_a.rb'", ''].join("\n") end it 'displays YAML configuration disabling all cops with offenses' do expect(output.string).to eq(expected_rubocop_todo) expect($stdout.string).to eq("Created .rubocop_todo.yml.\n") end end context "when there's .rubocop.yml" do before do create_file('.rubocop.yml', <<-YAML.strip_indent) Cop1: Exclude: - Gemfile Cop2: Exclude: - "**/*.blah" YAML formatter.started(['test_a.rb', 'test_b.rb']) formatter.file_started('test_a.rb', {}) formatter.file_finished('test_a.rb', offenses) formatter.file_started('test_b.rb', {}) formatter.file_finished('test_b.rb', [offenses.first]) formatter.finished(['test_a.rb', 'test_b.rb']) end let(:expected_rubocop_todo) do [heading, '# Offense count: 2', 'Cop1:', ' Exclude:', " - 'Gemfile'", " - 'test_a.rb'", " - 'test_b.rb'", '', '# Offense count: 1', 'Cop2:', ' Exclude:', " - '**/*.blah'", " - 'test_a.rb'", ''].join("\n") end it 'merges in excludes from .rubocop.yml' do expect(output.string).to eq(expected_rubocop_todo) end end context 'when exclude_limit option is omitted' do before do formatter.started(filenames) filenames.each do |filename| formatter.file_started(filename, {}) if filename == filenames.last formatter.file_finished(filename, [offenses.first]) else formatter.file_finished(filename, offenses) end end formatter.finished(filenames) end let(:filenames) do Array.new(16) { |index| format('test_%02d.rb', index + 1) } end let(:expected_rubocop_todo) do [heading, '# Offense count: 16', 'Cop1:', ' Enabled: false', '', '# Offense count: 15', 'Cop2:', ' Exclude:', " - 'test_01.rb'", " - 'test_02.rb'", " - 'test_03.rb'", " - 'test_04.rb'", " - 'test_05.rb'", " - 'test_06.rb'", " - 'test_07.rb'", " - 'test_08.rb'", " - 'test_09.rb'", " - 'test_10.rb'", " - 'test_11.rb'", " - 'test_12.rb'", " - 'test_13.rb'", " - 'test_14.rb'", " - 'test_15.rb'", ''].join("\n") end it 'disables the cop with 15 offending files' do expect(output.string).to eq(expected_rubocop_todo) end end context 'when exclude_limit option is passed' do before do formatter.started(filenames) filenames.each do |filename| formatter.file_started(filename, {}) if filename == filenames.last formatter.file_finished(filename, [offenses.first]) else formatter.file_finished(filename, offenses) end end formatter.finished(filenames) end let(:formatter) { described_class.new(output, exclude_limit: 5) } let(:filenames) do Array.new(6) { |index| format('test_%02d.rb', index + 1) } end let(:expected_heading_command) do 'rubocop --auto-gen-config --exclude-limit 5' end let(:expected_rubocop_todo) do [heading, '# Offense count: 6', 'Cop1:', ' Enabled: false', '', '# Offense count: 5', 'Cop2:', ' Exclude:', " - 'test_01.rb'", " - 'test_02.rb'", " - 'test_03.rb'", " - 'test_04.rb'", " - 'test_05.rb'", ''].join("\n") end it 'respects the file exclusion list limit' do expect(output.string).to eq(expected_rubocop_todo) end end context 'when no files are inspected' do before do formatter.started([]) formatter.finished([]) end it 'creates a .rubocop_todo.yml even in such case' do expect(output.string).to eq(heading) end end end rubocop-0.52.1/spec/rubocop/formatter/disabled_lines_formatter_spec.rb000066400000000000000000000044211322072016200262350ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::DisabledLinesFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb bin/rubocop].map do |path| File.expand_path(path) end end let(:file_started) do formatter.file_started(files.first, cop_disabled_line_ranges) end describe '#file_started' do before { formatter.started(files) } context 'when no disable cop comments are detected' do let(:cop_disabled_line_ranges) { {} } it 'does not add to cop_disabled_line_ranges' do expect { file_started }.not_to( change { formatter.cop_disabled_line_ranges } ) end end context 'when any disable cop comments are detected' do let(:cop_disabled_line_ranges) do { cop_disabled_line_ranges: { 'LineLength' => [1..1] } } end it 'merges the changes into cop_disabled_line_ranges' do expect { file_started }.to( change { formatter.cop_disabled_line_ranges } ) end end end describe '#finished' do context 'when there disabled cops detected' do let(:cop_disabled_line_ranges) do { cop_disabled_line_ranges: { 'LineLength' => [1..1], 'ClassLength' => [1..Float::INFINITY] } } end let(:offenses) do [ RuboCop::Cop::Offense.new(:convention, location, 'Class too long.', 'ClassLength', :disabled), RuboCop::Cop::Offense.new(:convention, location, 'Line too long.', 'LineLength', :uncorrected) ] end let(:location) { OpenStruct.new(line: 3) } before do formatter.started(files) formatter.file_started('lib/rubocop.rb', cop_disabled_line_ranges) formatter.file_finished('lib/rubocop.rb', offenses) end it 'lists disabled cops by file' do formatter.finished(files) expect(output.string) .to eq(<<-OUTPUT.strip_indent) Cops disabled line ranges: lib/rubocop.rb:1..1: LineLength lib/rubocop.rb:1..Infinity: ClassLength OUTPUT end end end end rubocop-0.52.1/spec/rubocop/formatter/emacs_style_formatter_spec.rb000066400000000000000000000050711322072016200256060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::EmacsStyleFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } describe '#file_finished' do it 'displays parsable text' do cop = RuboCop::Cop::Cop.new source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = %w[a b cdefghi].join("\n") cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 0, 1), message: 'message 1' ) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 9, 10), message: 'message 2' ) formatter.file_finished('test', cop.offenses) expect(output.string).to eq <<-OUTPUT.strip_indent test:1:1: C: message 1 test:3:6: C: message 2 OUTPUT end context 'when the offense is automatically corrected' do let(:file) { '/path/to/file' } let(:offense) do RuboCop::Cop::Offense.new(:convention, location, 'This is a message.', 'CopName', status) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end let(:status) { :corrected } it 'prints [Corrected] along with message' do formatter.file_finished(file, [offense]) expect(output.string) .to include(': [Corrected] This is a message.') end end context 'when the offense message contains a newline' do let(:file) { '/path/to/file' } let(:offense) do RuboCop::Cop::Offense.new(:error, location, "unmatched close parenthesis: /\n world " \ "# Some comment containing a )\n/", 'CopName', :uncorrected) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end it 'strips newlines out of the error message' do formatter.file_finished(file, [offense]) expect(output.string).to eq( '/path/to/file:1:1: E: unmatched close parenthesis: / ' \ "world # Some comment containing a ) /\n" ) end end end describe '#finished' do it 'does not report summary' do formatter.finished(['/path/to/file']) expect(output.string.empty?).to be(true) end end end rubocop-0.52.1/spec/rubocop/formatter/file_list_formatter_spec.rb000066400000000000000000000015171322072016200252510ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::FileListFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } describe '#file_finished' do it 'displays parsable text' do cop = RuboCop::Cop::Cop.new source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = %w[a b cdefghi].join("\n") cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 0, 1), message: 'message 1' ) cop.add_offense( nil, location: Parser::Source::Range.new(source_buffer, 9, 10), message: 'message 2' ) formatter.file_finished('test', cop.offenses) formatter.file_finished('test_2', cop.offenses) expect(output.string).to eq "test\ntest_2\n" end end end rubocop-0.52.1/spec/rubocop/formatter/formatter_set_spec.rb000066400000000000000000000105541322072016200240730ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::FormatterSet do subject(:formatter_set) { described_class.new } it 'responds to all formatter API methods' do %i[started file_started file_finished finished].each do |method| expect(formatter_set).to respond_to(method) end end describe 'formatter API method' do before do formatter_set.add_formatter('simple') formatter_set.add_formatter('emacs') end let(:files) { ['/path/to/file1', '/path/to/file2'] } it 'invokes same method of all containing formatters' do expect(formatter_set).to all(receive(:started).with(files)) formatter_set.started(files) end end describe 'add_formatter' do it 'adds a formatter to itself' do formatter_set.add_formatter('simple') expect(formatter_set.size).to eq(1) end it 'adds a formatter with specified formatter type' do formatter_set.add_formatter('simple') expect(formatter_set.first.class) .to eq(RuboCop::Formatter::SimpleTextFormatter) end it 'can add multiple formatters by being invoked multiple times' do formatter_set.add_formatter('simple') formatter_set.add_formatter('emacs') expect(formatter_set[0].class) .to eq(RuboCop::Formatter::SimpleTextFormatter) expect(formatter_set[1].class) .to eq(RuboCop::Formatter::EmacsStyleFormatter) end context 'when output path is omitted' do it 'adds a formatter outputs to $stdout' do formatter_set.add_formatter('simple') expect(formatter_set.first.output).to eq($stdout) end end context 'when output path is specified' do it 'adds a formatter outputs to the specified file' do output_path = Tempfile.new('').path formatter_set.add_formatter('simple', output_path) expect(formatter_set.first.output.class).to eq(File) expect(formatter_set.first.output.path).to eq(output_path) end context "when parent directories don't exist" do let(:tmpdir) { Dir.mktmpdir } after { FileUtils.rm_rf(tmpdir) } it 'creates them' do output_path = File.join(tmpdir, 'path/does/not/exist') formatter_set.add_formatter('simple', output_path) expect(formatter_set.first.output.class).to eq(File) expect(formatter_set.first.output.path).to eq(output_path) end end end end describe '#close_output_files' do before do 2.times do output_path = Tempfile.new('').path formatter_set.add_formatter('simple', output_path) end formatter_set.add_formatter('simple') end around do |example| begin $stdout = StringIO.new example.run ensure $stdout = STDOUT end end it 'closes all output files' do formatter_set.close_output_files formatter_set[0..1].each do |formatter| expect(formatter.output.closed?).to be(true) end end it 'does not close non file output' do expect(formatter_set[2].output.closed?).to be(false) end end describe '#builtin_formatter_class' do def builtin_formatter_class(string) described_class.new.send(:builtin_formatter_class, string) end it 'returns class which matches passed alias name exactly' do expect(builtin_formatter_class('simple')) .to eq(RuboCop::Formatter::SimpleTextFormatter) end it 'returns class whose first letter of alias name ' \ 'matches passed letter' do expect(builtin_formatter_class('s')) .to eq(RuboCop::Formatter::SimpleTextFormatter) end end describe '#custom_formatter_class' do def custom_formatter_class(string) described_class.new.send(:custom_formatter_class, string) end it 'returns constant represented by the passed string' do expect(custom_formatter_class('RuboCop')).to eq(RuboCop) end it 'can handle namespaced constant name' do expect(custom_formatter_class('RuboCop::CLI')).to eq(RuboCop::CLI) end it 'can handle top level namespaced constant name' do expect(custom_formatter_class('::RuboCop::CLI')).to eq(RuboCop::CLI) end context 'when non-existent constant name is passed' do it 'raises error' do expect { custom_formatter_class('RuboCop::NonExistentClass') } .to raise_error(NameError) end end end end rubocop-0.52.1/spec/rubocop/formatter/fuubar_style_formatter_spec.rb000066400000000000000000000061301322072016200257770ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::FuubarStyleFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb].map do |path| File.expand_path(path) end end describe '#with_color' do around do |example| original_state = formatter.rainbow.enabled begin example.run ensure formatter.rainbow.enabled = original_state end end context 'when color is enabled' do before do formatter.rainbow.enabled = true end it 'outputs coloring sequence code at the beginning and the end' do formatter.with_color { formatter.output.write 'foo' } expect(output.string).to eq("\e[32mfoo\e[0m") end end context 'when color is enabled' do before do formatter.rainbow.enabled = false end it 'outputs nothing' do formatter.with_color { formatter.output.write 'foo' } expect(output.string).to eq('foo') end end end describe '#progressbar_color' do before do formatter.started(files) end def offense(severity, status = :uncorrected) source_range = double('source_range').as_null_object RuboCop::Cop::Offense.new( severity, source_range, 'message', 'Cop', status ) end context 'initially' do it 'is green' do expect(formatter.progressbar_color).to eq(:green) end end context 'when no offenses are detected in a file' do before do formatter.file_finished(files[0], []) end it 'is still green' do expect(formatter.progressbar_color).to eq(:green) end end context 'when a convention offense is detected in a file' do before do formatter.file_finished(files[0], [offense(:convention)]) end it 'is yellow' do expect(formatter.progressbar_color).to eq(:yellow) end end context 'when an error offense is detected in a file' do before do formatter.file_finished(files[0], [offense(:error)]) end it 'is red' do expect(formatter.progressbar_color).to eq(:red) end context 'and then a convention offense is detected in the next file' do before do formatter.file_finished(files[1], [offense(:convention)]) end it 'is still red' do expect(formatter.progressbar_color).to eq(:red) end end end context 'when convention and error offenses are detected in a file' do before do offenses = [offense(:convention), offense(:error)] formatter.file_finished(files[0], offenses) end it 'is red' do expect(formatter.progressbar_color).to eq(:red) end end context 'when a offense is detected in a file and auto-corrected' do before do formatter.file_finished(files[0], [offense(:convention, :corrected)]) end it 'is green' do expect(formatter.progressbar_color).to eq(:green) end end end end rubocop-0.52.1/spec/rubocop/formatter/html_formatter_spec.rb000066400000000000000000000033761322072016200242500ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::HTMLFormatter, :isolated_environment do spec_root = File.expand_path('../../..', __FILE__) around do |example| project_path = File.join(spec_root, 'fixtures/html_formatter/project') FileUtils.cp_r(project_path, '.') Dir.chdir(File.basename(project_path)) do example.run end end let(:actual_html_path) do path = File.expand_path('result.html') # Run without Style/EndOfLine as it gives different results on # different platforms. RuboCop::CLI.new.run(['--except', 'Layout/EndOfLine', '--format', 'html', '--out', path]) path end let(:actual_html_path_cached) do path = File.expand_path('result_cached.html') 2.times do RuboCop::CLI.new.run(['--except', 'Layout/EndOfLine', '--format', 'html', '--out', path]) end path end let(:actual_html) do File.read(actual_html_path, encoding: Encoding::UTF_8) end let(:actual_html_cached) do File.read(actual_html_path_cached, encoding: Encoding::UTF_8) end let(:expected_html_path) do File.join(spec_root, 'fixtures/html_formatter/expected.html') end let(:expected_html) do html = File.read(expected_html_path, encoding: Encoding::UTF_8) # Avoid failure on version bump html.sub(/(class="version".{0,20})\d+(?:\.\d+){2}/i) do Regexp.last_match(1) + RuboCop::Version::STRING end end it 'outputs the result in HTML' do # FileUtils.copy(actual_html_path, expected_html_path) expect(actual_html).to eq(expected_html) end it 'outputs the cached result in HTML' do # FileUtils.copy(actual_html_path, expected_html_path) expect(actual_html_cached).to eq(expected_html) end end rubocop-0.52.1/spec/rubocop/formatter/json_formatter_spec.rb000066400000000000000000000104571322072016200242530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::JSONFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) { %w[/path/to/file1 /path/to/file2] } let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = %w[a b cdefghi].join("\n") Parser::Source::Range.new(source_buffer, 2, 10) end let(:offense) do RuboCop::Cop::Offense.new(:convention, location, 'This is message', 'CopName', :corrected) end describe '#started' do let(:summary) { formatter.output_hash[:summary] } it 'sets target file count in summary' do expect(summary[:target_file_count].nil?).to be(true) formatter.started(%w[/path/to/file1 /path/to/file2]) expect(summary[:target_file_count]).to eq(2) end end describe '#file_finished' do before do count = 0 allow(formatter).to receive(:hash_for_file) do count += 1 end end let(:summary) { formatter.output_hash[:summary] } it 'adds detected offense count in summary' do expect(summary[:offense_count]).to eq(0) formatter.file_started(files[0], {}) expect(summary[:offense_count]).to eq(0) formatter.file_finished(files[0], [ double('offense1'), double('offense2') ]) expect(summary[:offense_count]).to eq(2) end it 'adds value of #hash_for_file to #output_hash[:files]' do expect(formatter.output_hash[:files].empty?).to be(true) formatter.file_started(files[0], {}) expect(formatter.output_hash[:files].empty?).to be(true) formatter.file_finished(files[0], []) expect(formatter.output_hash[:files]).to eq([1]) formatter.file_started(files[1], {}) expect(formatter.output_hash[:files]).to eq([1]) formatter.file_finished(files[1], []) expect(formatter.output_hash[:files]).to eq([1, 2]) end end describe '#finished' do let(:summary) { formatter.output_hash[:summary] } it 'sets inspected file count in summary' do expect(summary[:inspected_file_count].nil?).to be(true) formatter.finished(%w[/path/to/file1 /path/to/file2]) expect(summary[:inspected_file_count]).to eq(2) end it 'outputs #output_hash as JSON' do formatter.finished(files) json = output.string restored_hash = JSON.parse(json, symbolize_names: true) expect(restored_hash).to eq(formatter.output_hash) end end describe '#hash_for_file' do subject(:hash) { formatter.hash_for_file(file, offenses) } let(:file) { File.expand_path('spec/spec_helper.rb') } let(:offenses) { [double('offense1'), double('offense2')] } it 'sets relative file path for :path key' do expect(hash[:path]).to eq('spec/spec_helper.rb') end before do count = 0 allow(formatter).to receive(:hash_for_offense) do count += 1 end end it 'sets an array of #hash_for_offense values for :offenses key' do expect(hash[:offenses]).to eq([1, 2]) end end describe '#hash_for_offense' do subject(:hash) { formatter.hash_for_offense(offense) } it 'sets Offense#severity value for :severity key' do expect(hash[:severity]).to eq(:convention) end it 'sets Offense#message value for :message key' do expect(hash[:message]).to eq('This is message') end it 'sets Offense#cop_name value for :cop_name key' do expect(hash[:cop_name]).to eq('CopName') end it 'sets Offense#corrected? value for :corrected key' do expect(hash[:corrected]).to be_truthy end it 'sets value of #hash_for_location for :location key' do location_hash = { start_line: 2, start_column: 1, last_line: 3, last_column: 6, length: 8, line: 2, column: 1 } expect(hash[:location]).to eq(location_hash) end end describe '#hash_for_location' do subject(:hash) { formatter.hash_for_location(offense) } it 'sets line value for :line key' do expect(hash[:line]).to eq(2) end it 'sets column value for :column key' do expect(hash[:column]).to eq(1) end it 'sets length value for :length key' do expect(hash[:length]).to eq(8) end end end rubocop-0.52.1/spec/rubocop/formatter/offense_count_formatter_spec.rb000066400000000000000000000034341322072016200261340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::OffenseCountFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb bin/rubocop].map do |path| File.expand_path(path) end end let(:finish) { formatter.file_finished(files.first, offenses) } describe '#file_finished' do before { formatter.started(files) } context 'when no offenses are detected' do let(:offenses) { [] } it 'does not add to offense_counts' do expect { finish }.not_to change { formatter.offense_counts } end end context 'when any offenses are detected' do let(:offenses) { [double('offense', cop_name: 'OffendedCop')] } it 'increments the count for the cop in offense_counts' do expect { finish }.to change { formatter.offense_counts } end end end describe '#report_summary' do context 'when an offense is detected' do let(:cop_counts) { { 'OffendedCop' => 1 } } it 'shows the cop and the offense count' do formatter.report_summary(cop_counts) expect(output.string).to include( "\n1 OffendedCop\n--\n1 Total" ) end end end describe '#finished' do context 'when there are many offenses' do let(:offenses) do %w[CopB CopA CopC CopC].map { |c| double('offense', cop_name: c) } end before do formatter.started(files) finish end it 'sorts by offense count first and then by cop name' do formatter.finished(files) expect(output.string).to eq(<<-OUTPUT.strip_indent) 2 CopC 1 CopA 1 CopB -- 4 Total OUTPUT end end end end rubocop-0.52.1/spec/rubocop/formatter/progress_formatter_spec.rb000066400000000000000000000114331322072016200251410ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::ProgressFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb bin/rubocop].map do |path| File.expand_path(path) end end describe '#file_finished' do before do formatter.started(files) formatter.file_started(files.first, {}) end shared_examples 'calls #report_file_as_mark' do it 'calls #report_as_with_mark' do expect(formatter).to receive(:report_file_as_mark) formatter.file_finished(files.first, offenses) end end context 'when no offenses are detected' do let(:offenses) { [] } include_examples 'calls #report_file_as_mark' end context 'when any offenses are detected' do let(:offenses) { [double('offense').as_null_object] } include_examples 'calls #report_file_as_mark' end end describe '#report_file_as_mark' do before do formatter.report_file_as_mark(offenses) end def offense_with_severity(severity) source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" RuboCop::Cop::Offense.new(severity, Parser::Source::Range.new(source_buffer, 0, 1), 'message', 'CopName') end context 'when no offenses are detected' do let(:offenses) { [] } it 'prints "."' do expect(output.string).to eq('.') end end context 'when a refactor severity offense is detected' do let(:offenses) { [offense_with_severity(:refactor)] } it 'prints "R"' do expect(output.string).to eq('R') end end context 'when a refactor convention offense is detected' do let(:offenses) { [offense_with_severity(:convention)] } it 'prints "C"' do expect(output.string).to eq('C') end end context 'when different severity offenses are detected' do let(:offenses) do [ offense_with_severity(:refactor), offense_with_severity(:error) ] end it 'prints highest level mark' do expect(output.string).to eq('E') end end end describe '#finished' do before do formatter.started(files) end context 'when any offenses are detected' do before do source_buffer = Parser::Source::Buffer.new('test', 1) source = Array.new(9) do |index| "This is line #{index + 1}." end source_buffer.source = source.join("\n") line_length = source[0].length + 1 formatter.file_started(files[0], {}) formatter.file_finished( files[0], [ RuboCop::Cop::Offense.new( :convention, Parser::Source::Range.new(source_buffer, line_length + 2, line_length + 3), 'foo', 'Cop' ) ] ) formatter.file_started(files[1], {}) formatter.file_finished(files[1], []) formatter.file_started(files[2], {}) formatter.file_finished( files[2], [ RuboCop::Cop::Offense.new( :error, Parser::Source::Range.new(source_buffer, 4 * line_length + 1, 4 * line_length + 2), 'bar', 'Cop' ), RuboCop::Cop::Offense.new( :convention, Parser::Source::Range.new(source_buffer, 5 * line_length, 5 * line_length + 1), 'foo', 'Cop' ) ] ) end it 'reports all detected offenses for all failed files' do formatter.finished(files) expect(output.string).to include(<<-OUTPUT.strip_indent) Offenses: lib/rubocop.rb:2:3: C: foo This is line 2. ^ bin/rubocop:5:2: E: bar This is line 5. ^ bin/rubocop:6:1: C: foo This is line 6. ^ OUTPUT end end context 'when no offenses are detected' do before do files.each do |file| formatter.file_started(file, {}) formatter.file_finished(file, []) end end it 'does not report offenses' do formatter.finished(files) expect(output.string).not_to include('Offenses:') end end it 'calls #report_summary' do expect(formatter).to receive(:report_summary) formatter.finished(files) end end end rubocop-0.52.1/spec/rubocop/formatter/quiet_formatter_spec.rb000066400000000000000000000066501322072016200244310ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::QuietFormatter do before do Rainbow.enabled = true end subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } describe '#report_file' do before do formatter.report_file(file, [offense]) end let(:file) { '/path/to/file' } let(:offense) do RuboCop::Cop::Offense.new(:convention, location, 'This is a message with `colored text`.', 'CopName', status) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end let(:status) { :uncorrected } context 'the file is under the current working directory' do let(:file) { File.expand_path('spec/spec_helper.rb') } it 'prints as relative path' do expect(output.string).to include('== spec/spec_helper.rb ==') end end context 'the file is outside of the current working directory' do let(:file) do tempfile = Tempfile.new('') tempfile.close File.expand_path(tempfile.path) end it 'prints as absolute path' do expect(output.string).to include("== #{file} ==") end end context 'when the offense is not corrected' do let(:status) { :uncorrected } it 'prints message as-is' do expect(output.string) .to include(': This is a message with colored text.') end end context 'when the offense is automatically corrected' do let(:status) { :corrected } it 'prints [Corrected] along with message' do expect(output.string) .to include(': [Corrected] This is a message with colored text.') end end end describe '#report_summary' do context 'when no files inspected' do it 'handles pluralization correctly' do formatter.report_summary(0, 0, 0) expect(output.string.empty?).to eq(true) end end context 'when a file inspected and no offenses detected' do it 'handles pluralization correctly' do formatter.report_summary(1, 0, 0) expect(output.string.empty?).to eq(true) end end context 'when a offense detected' do it 'handles pluralization correctly' do formatter.report_summary(1, 1, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected OUTPUT end end context 'when 2 offenses detected' do it 'handles pluralization correctly' do formatter.report_summary(2, 2, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 2 files inspected, 2 offenses detected OUTPUT end end context 'when an offense is corrected' do it 'prints about correction' do formatter.report_summary(1, 1, 1) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected, 1 offense corrected OUTPUT end end context 'when 2 offenses are corrected' do it 'handles pluralization correctly' do formatter.report_summary(1, 1, 2) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected, 2 offenses corrected OUTPUT end end end after do Rainbow.enabled = false end end rubocop-0.52.1/spec/rubocop/formatter/simple_text_formatter_spec.rb000066400000000000000000000071061322072016200256340ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::SimpleTextFormatter do before do Rainbow.enabled = true end subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } describe '#report_file' do before do formatter.report_file(file, [offense]) end let(:file) { '/path/to/file' } let(:offense) do RuboCop::Cop::Offense.new(:convention, location, 'This is a message with `colored text`.', 'CopName', status) end let(:location) do source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = "a\n" Parser::Source::Range.new(source_buffer, 0, 1) end let(:status) { :uncorrected } context 'the file is under the current working directory' do let(:file) { File.expand_path('spec/spec_helper.rb') } it 'prints as relative path' do expect(output.string).to include('== spec/spec_helper.rb ==') end end context 'the file is outside of the current working directory' do let(:file) do tempfile = Tempfile.new('') tempfile.close File.expand_path(tempfile.path) end it 'prints as absolute path' do expect(output.string).to include("== #{file} ==") end end context 'when the offense is not corrected' do let(:status) { :uncorrected } it 'prints message as-is' do expect(output.string) .to include(': This is a message with colored text.') end end context 'when the offense is automatically corrected' do let(:status) { :corrected } it 'prints [Corrected] along with message' do expect(output.string) .to include(': [Corrected] This is a message with colored text.') end end end describe '#report_summary' do context 'when no files inspected' do it 'handles pluralization correctly' do formatter.report_summary(0, 0, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 0 files inspected, no offenses detected OUTPUT end end context 'when a file inspected and no offenses detected' do it 'handles pluralization correctly' do formatter.report_summary(1, 0, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, no offenses detected OUTPUT end end context 'when a offense detected' do it 'handles pluralization correctly' do formatter.report_summary(1, 1, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected OUTPUT end end context 'when 2 offenses detected' do it 'handles pluralization correctly' do formatter.report_summary(2, 2, 0) expect(output.string).to eq(<<-OUTPUT.strip_indent) 2 files inspected, 2 offenses detected OUTPUT end end context 'when an offense is corrected' do it 'prints about correction' do formatter.report_summary(1, 1, 1) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected, 1 offense corrected OUTPUT end end context 'when 2 offenses are corrected' do it 'handles pluralization correctly' do formatter.report_summary(1, 1, 2) expect(output.string).to eq(<<-OUTPUT.strip_indent) 1 file inspected, 1 offense detected, 2 offenses corrected OUTPUT end end end after do Rainbow.enabled = false end end rubocop-0.52.1/spec/rubocop/formatter/tap_formatter_spec.rb000066400000000000000000000065441322072016200240700ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::TapFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb bin/rubocop].map do |path| File.expand_path(path) end end describe '#file_finished' do before do formatter.started(files) formatter.file_started(files.first, {}) formatter.file_finished(files.first, offenses) end context 'when no offenses are detected' do let(:offenses) { [] } it 'prints "ok"' do expect(output.string).to include('ok 1') end end context 'when any offenses are detected' do let(:offenses) { [double('offense').as_null_object] } it 'prints "not ok"' do expect(output.string).to include('not ok 1') end end end describe '#finished' do before do formatter.started(files) end context 'when any offenses are detected' do before do source_buffer = Parser::Source::Buffer.new('test', 1) source = Array.new(9) do |index| "This is line #{index + 1}." end source_buffer.source = source.join("\n") line_length = source[0].length + 1 formatter.file_started(files[0], {}) formatter.file_finished( files[0], [ RuboCop::Cop::Offense.new( :convention, Parser::Source::Range.new(source_buffer, line_length + 2, line_length + 3), 'foo', 'Cop' ) ] ) formatter.file_started(files[1], {}) formatter.file_finished(files[1], []) formatter.file_started(files[2], {}) formatter.file_finished( files[2], [ RuboCop::Cop::Offense.new( :error, Parser::Source::Range.new(source_buffer, 4 * line_length + 1, 4 * line_length + 2), 'bar', 'Cop' ), RuboCop::Cop::Offense.new( :convention, Parser::Source::Range.new(source_buffer, 5 * line_length, 5 * line_length + 1), 'foo', 'Cop' ) ] ) end it 'reports all detected offenses for all failed files' do formatter.finished(files) expect(output.string).to include(<<-OUTPUT.strip_indent) 1..3 not ok 1 - lib/rubocop.rb # lib/rubocop.rb:2:3: C: foo # This is line 2. # ^ ok 2 - spec/spec_helper.rb not ok 3 - bin/rubocop # bin/rubocop:5:2: E: bar # This is line 5. # ^ # bin/rubocop:6:1: C: foo # This is line 6. # ^ OUTPUT end end context 'when no offenses are detected' do before do files.each do |file| formatter.file_started(file, {}) formatter.file_finished(file, []) end end it 'does not report offenses' do formatter.finished(files) expect(output.string).not_to include('not ok') end end end end rubocop-0.52.1/spec/rubocop/formatter/text_util_spec.rb000066400000000000000000000023571322072016200232400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::TextUtil do describe 'pluralize' do it 'will not change 0 to no' do pluralized_text = described_class.pluralize(0, 'file') expect(pluralized_text).to eq('0 files') end it 'will change 0 to no when configured' do pluralized_text = described_class.pluralize(0, 'file', no_for_zero: true) expect(pluralized_text).to eq('no files') end it 'will not pluralize 1' do pluralized_text = described_class.pluralize(1, 'file') expect(pluralized_text).to eq('1 file') end it 'will pluralize quantities greater than 1' do pluralized_text = described_class.pluralize(3, 'file') expect(pluralized_text).to eq('3 files') end it 'will pluralize fractions' do pluralized_text = described_class.pluralize(0.5, 'file') expect(pluralized_text).to eq('0.5 files') end it 'will pluralize -1' do pluralized_text = described_class.pluralize(-1, 'file') expect(pluralized_text).to eq('-1 files') end it 'will pluralize negative quantities less than -1' do pluralized_text = described_class.pluralize(-2, 'file') expect(pluralized_text).to eq('-2 files') end end end rubocop-0.52.1/spec/rubocop/formatter/worst_offenders_formatter_spec.rb000066400000000000000000000016431322072016200265100ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Formatter::WorstOffendersFormatter do subject(:formatter) { described_class.new(output) } let(:output) { StringIO.new } let(:files) do %w[lib/rubocop.rb spec/spec_helper.rb bin/rubocop].map do |path| File.expand_path(path) end end describe '#finished' do context 'when there are many offenses' do let(:offense) { double('offense') } before do formatter.started(files) files.each_with_index do |file, index| formatter.file_finished(file, [offense] * (index + 2)) end end it 'sorts by offense count first and then by cop name' do formatter.finished(files) expect(output.string).to eq(<<-OUTPUT.strip_indent) 4 bin/rubocop 3 spec/spec_helper.rb 2 lib/rubocop.rb -- 9 Total OUTPUT end end end end rubocop-0.52.1/spec/rubocop/magic_comment_spec.rb000066400000000000000000000102031322072016200220030ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::MagicComment do shared_examples 'magic comment' do |comment, expectations = {}| encoding = expectations[:encoding] frozen_string = expectations[:frozen_string_literal] it "returns #{encoding.inspect} for encoding when comment is #{comment}" do expect(described_class.parse(comment).encoding).to eql(encoding) end it "returns #{frozen_string.inspect} for frozen_string_literal " \ "when comment is #{comment}" do expect(described_class.parse(comment).frozen_string_literal) .to eql(frozen_string) end end include_examples 'magic comment', '#' include_examples 'magic comment', '# encoding: utf-8', encoding: 'utf-8' include_examples 'magic comment', '# ENCODING: utf-8', encoding: 'utf-8' include_examples 'magic comment', '# eNcOdInG: utf-8', encoding: 'utf-8' include_examples 'magic comment', '# coding: utf-8', encoding: 'utf-8' include_examples 'magic comment', '# incoding: utf-8' include_examples 'magic comment', '# encoding: stateless-iso-2022-jp-kddi', encoding: 'stateless-iso-2022-jp-kddi' include_examples 'magic comment', '# frozen_string_literal: true', frozen_string_literal: true include_examples 'magic comment', '# frozen_string_literal:true', frozen_string_literal: true include_examples 'magic comment', '# frozen_string_literal: false', frozen_string_literal: false include_examples 'magic comment', '# frozen-string-literal: true', frozen_string_literal: true include_examples 'magic comment', '# FROZEN-STRING-LITERAL: true', frozen_string_literal: true include_examples 'magic comment', '# fRoZeN-sTrInG_lItErAl: true', frozen_string_literal: true include_examples 'magic comment', '# frozen_string_literal: invalid', frozen_string_literal: 'invalid' include_examples 'magic comment', '# -*- encoding : ascii-8bit -*-', encoding: 'ascii-8bit', frozen_string_literal: nil include_examples 'magic comment', '# encoding: ascii-8bit frozen_string_literal: true', encoding: 'ascii-8bit', frozen_string_literal: nil include_examples 'magic comment', '# frozen_string_literal: true encoding: ascii-8bit', encoding: 'ascii-8bit', frozen_string_literal: nil include_examples( 'magic comment', '# -*- encoding: ASCII-8BIT; frozen_string_literal: true -*-', encoding: 'ascii-8bit', frozen_string_literal: true ) include_examples( 'magic comment', '# coding: utf-8 -*- encoding: ASCII-8BIT; frozen_string_literal: true -*-', encoding: 'ascii-8bit', frozen_string_literal: true ) include_examples 'magic comment', '# vim: filetype=ruby, fileencoding=ascii-8bit', encoding: 'ascii-8bit' include_examples 'magic comment', '# vim: filetype=ruby,fileencoding=ascii-8bit', encoding: nil include_examples 'magic comment', '# vim: filetype=ruby, fileencoding=ascii-8bit', encoding: 'ascii-8bit' include_examples 'magic comment', '#vim: filetype=ruby, fileencoding=ascii-8bit', encoding: 'ascii-8bit' include_examples( 'magic comment', '# coding: utf-8 vim: filetype=ruby, fileencoding=ascii-8bit', encoding: 'utf-8' ) include_examples 'magic comment', '# vim: filetype=python, fileencoding=ascii-8bit', encoding: 'ascii-8bit' include_examples 'magic comment', '# vim:fileencoding=utf-8', encoding: nil end rubocop-0.52.1/spec/rubocop/node_pattern_spec.rb000066400000000000000000000660351322072016200217010ustar00rootroot00000000000000# frozen_string_literal: true require 'parser/current' RSpec.describe RuboCop::NodePattern do let(:root_node) do buffer = Parser::Source::Buffer.new('(string)', 1) buffer.source = ruby builder = RuboCop::AST::Builder.new Parser::CurrentRuby.new(builder).parse(buffer) end let(:node) { root_node } let(:params) { [] } shared_examples :matching do include RuboCop::AST::Sexp it 'matches' do expect(described_class.new(pattern).match(node, *params)).to be true end end shared_examples :nonmatching do it "doesn't match" do expect(described_class.new(pattern).match(node, *params).nil?).to be(true) end end shared_examples :invalid do it 'is invalid' do expect { described_class.new(pattern) } .to raise_error(RuboCop::NodePattern::Invalid) end end shared_examples :single_capture do include RuboCop::AST::Sexp it 'yields captured value(s) and returns true if there is a block' do expect do |probe| compiled = described_class.new(pattern) retval = compiled.match(node, *params) do |capture| probe.to_proc.call(capture) :retval_from_block end expect(retval).to be :retval_from_block end.to yield_with_args(captured_val) end it 'returns captured values if there is no block' do retval = described_class.new(pattern).match(node, *params) expect(retval).to eq captured_val end end shared_examples :multiple_capture do include RuboCop::AST::Sexp it 'yields captured value(s) and returns true if there is a block' do expect do |probe| compiled = described_class.new(pattern) retval = compiled.match(node, *params) do |*captures| probe.to_proc.call(captures) :retval_from_block end expect(retval).to be :retval_from_block end.to yield_with_args(captured_vals) end it 'returns captured values if there is no block' do retval = described_class.new(pattern).match(node, *params) expect(retval).to eq captured_vals end end describe 'bare node type' do let(:pattern) { 'send' } context 'on a node with the same type' do let(:ruby) { 'obj.method' } it_behaves_like :matching end context 'on a node with a different type' do let(:ruby) { '@ivar' } it_behaves_like :nonmatching end context 'on a node with a matching, hyphenated type' do let(:pattern) { 'op-asgn' } let(:ruby) { 'a += 1' } # this is an (op-asgn ...) node it_behaves_like :matching end end describe 'literals' do context 'negative integer literals' do let(:pattern) { '(int -100)' } let(:ruby) { '-100' } it_behaves_like :matching end context 'positive float literals' do let(:pattern) { '(float 1.0)' } let(:ruby) { '1.0' } it_behaves_like :matching end context 'negative float literals' do let(:pattern) { '(float -2.5)' } let(:ruby) { '-2.5' } it_behaves_like :matching end context 'single quoted string literals' do let(:pattern) { '(str "foo")' } let(:ruby) { '"foo"' } it_behaves_like :matching end context 'double quoted string literals' do let(:pattern) { '(str "foo")' } let(:ruby) { "'foo'" } it_behaves_like :matching end context 'symbol literals' do let(:pattern) { '(sym :foo)' } let(:ruby) { ':foo' } it_behaves_like :matching end end describe 'nil' do context 'nil literals' do let(:pattern) { '(nil)' } let(:ruby) { 'nil' } it_behaves_like :matching end context 'nil value in AST' do let(:pattern) { '(send nil :foo)' } let(:ruby) { 'foo' } it_behaves_like :nonmatching end context 'nil value in AST, use nil? method' do let(:pattern) { '(send nil? :foo)' } let(:ruby) { 'foo' } it_behaves_like :matching end end describe 'simple sequence' do let(:pattern) { '(send int :+ int)' } context 'on a node with the same type and matching children' do let(:ruby) { '1 + 1' } it_behaves_like :matching end context 'on a node with a different type' do let(:ruby) { 'a = 1' } it_behaves_like :nonmatching end context 'on a node with the same type and non-matching children' do context 'with non-matching selector' do let(:ruby) { '1 - 1' } it_behaves_like :nonmatching end context 'with non-matching receiver type' do let(:ruby) { '1.0 + 1' } it_behaves_like :nonmatching end end context 'on a node with too many children' do let(:pattern) { '(send int :blah int)' } let(:ruby) { '1.blah(1, 2)' } it_behaves_like :nonmatching end context 'with a nested sequence in head position' do let(:pattern) { '((send) int :blah)' } it_behaves_like :invalid end context 'with a nested sequence in non-head position' do let(:pattern) { '(send (send _ :a) :b)' } let(:ruby) { 'obj.a.b' } it_behaves_like :matching end end describe 'sequence with trailing ...' do let(:pattern) { '(send int :blah ...)' } context 'on a node with the same type and exact number of children' do let(:ruby) { '1.blah' } it_behaves_like :matching end context 'on a node with the same type and more children' do context 'with 1 child more' do let(:ruby) { '1.blah(1)' } it_behaves_like :matching end context 'with 2 children more' do let(:ruby) { '1.blah(1, :something)' } it_behaves_like :matching end end context 'on a node with the same type and fewer children' do let(:pattern) { '(send int :blah int int ...)' } let(:ruby) { '1.blah(2)' } it_behaves_like :nonmatching end context 'on a node with fewer children, with a wildcard preceding' do let(:pattern) { '(hash _ ...)' } let(:ruby) { '{}' } it_behaves_like :nonmatching end context 'on a node with a different type' do let(:ruby) { 'A = 1' } it_behaves_like :nonmatching end context 'on a node with non-matching children' do let(:ruby) { '1.foo' } it_behaves_like :nonmatching end end describe 'wildcards' do describe 'unnamed wildcards' do context 'at the root level' do let(:pattern) { '_' } let(:ruby) { 'class << self; def something; 1; end end.freeze' } it_behaves_like :matching end context 'within a sequence' do let(:pattern) { '(const _ _)' } let(:ruby) { 'Const' } it_behaves_like :matching end context 'within a sequence with other patterns intervening' do let(:pattern) { '(ivasgn _ (int _))' } let(:ruby) { '@abc = 22' } it_behaves_like :matching end context 'in head position of a sequence' do let(:pattern) { '(_ int ...)' } let(:ruby) { '1 + a' } it_behaves_like :matching end context 'negated' do let(:pattern) { '!_' } let(:ruby) { '123' } it_behaves_like :nonmatching end end describe 'named wildcards' do # unification is done on named wildcards! context 'at the root level' do let(:pattern) { '_node' } let(:ruby) { 'class << self; def something; 1; end end.freeze' } it_behaves_like :matching end context 'within a sequence' do context 'with values which can be unified' do let(:pattern) { '(send _num :+ _num)' } let(:ruby) { '5 + 5' } it_behaves_like :matching end context 'with values which cannot be unified' do let(:pattern) { '(send _num :+ _num)' } let(:ruby) { '5 + 4' } it_behaves_like :nonmatching end context 'unifying the node type with an argument' do let(:pattern) { '(_type _ _type)' } let(:ruby) { 'obj.send' } it_behaves_like :matching end end context 'within a sequence with other patterns intervening' do let(:pattern) { '(ivasgn _ivar (int _val))' } let(:ruby) { '@abc = 22' } it_behaves_like :matching end context 'in head position of a sequence' do let(:pattern) { '(_type int ...)' } let(:ruby) { '1 + a' } it_behaves_like :matching end end end describe 'sets' do context 'at the top level' do context 'containing symbol literals' do context 'when the AST has a matching symbol' do let(:pattern) { '(send _ {:a :b})' } let(:ruby) { 'obj.b' } it_behaves_like :matching end context 'when the AST does not have a matching symbol' do let(:pattern) { '(send _ {:a :b})' } let(:ruby) { 'obj.c' } it_behaves_like :nonmatching end end context 'containing string literals' do let(:pattern) { '(send (str {"a" "b"}) :upcase)' } let(:ruby) { '"a".upcase' } it_behaves_like :matching end context 'containing integer literals' do let(:pattern) { '(send (int {1 10}) :abs)' } let(:ruby) { '10.abs' } it_behaves_like :matching end context 'containing multiple []' do let(:pattern) { '{[(int odd?) int] [!nil float]}' } context 'on a node which meets all requirements of the first []' do let(:ruby) { '3' } it_behaves_like :matching end context 'on a node which meets all requirements of the second []' do let(:ruby) { '2.2' } it_behaves_like :matching end context 'on a node which meets some requirements but not all' do let(:ruby) { '2' } it_behaves_like :nonmatching end end end context 'nested inside a sequence' do let(:pattern) { '(send {const int} ...)' } let(:ruby) { 'Const.method' } it_behaves_like :matching end context 'with a nested sequence' do let(:pattern) { '{(send int ...) (send const ...)}' } let(:ruby) { 'Const.method' } it_behaves_like :matching end end describe 'captures on a wildcard' do context 'at the root level' do let(:pattern) { '$_' } let(:ruby) { 'begin; raise StandardError; rescue Exception => e; end' } let(:captured_val) { node } it_behaves_like :single_capture end context 'in head position in a sequence' do let(:pattern) { '($_ ...)' } let(:ruby) { 'A.method' } let(:captured_val) { :send } it_behaves_like :single_capture end context 'in non-head position in a sequence' do let(:pattern) { '(send $_ ...)' } let(:ruby) { 'A.method' } let(:captured_val) { s(:const, nil, :A) } it_behaves_like :single_capture end context 'in a nested sequence' do let(:pattern) { '(send (const nil? $_) ...)' } let(:ruby) { 'A.method' } let(:captured_val) { :A } it_behaves_like :single_capture end end describe 'captures which also perform a match' do context 'on a sequence' do let(:pattern) { '(send $(send _ :keys) :each)' } let(:ruby) { '{}.keys.each' } let(:captured_val) { s(:send, s(:hash), :keys) } it_behaves_like :single_capture end context 'on a set' do let(:pattern) { '(send _ ${:inc :dec})' } let(:ruby) { '1.dec' } let(:captured_val) { :dec } it_behaves_like :single_capture end context 'on []' do let(:pattern) { '(send (int $[!odd? !zero?]) :inc)' } let(:ruby) { '2.inc' } let(:captured_val) { 2 } it_behaves_like :single_capture end context 'on a node type' do let(:pattern) { '(send $int :inc)' } let(:ruby) { '5.inc' } let(:captured_val) { s(:int, 5) } it_behaves_like :single_capture end context 'on a literal' do let(:pattern) { '(send int $:inc)' } let(:ruby) { '5.inc' } let(:captured_val) { :inc } it_behaves_like :single_capture end context 'when nested' do let(:pattern) { '(send $(int $_) :inc)' } let(:ruby) { '5.inc' } let(:captured_vals) { [s(:int, 5), 5] } it_behaves_like :multiple_capture end end describe 'captures on ...' do context 'with no remaining pattern at the end' do let(:pattern) { '(send $...)' } let(:ruby) { '5.inc' } let(:captured_val) { [s(:int, 5), :inc] } it_behaves_like :single_capture end context 'with a remaining node type at the end' do let(:pattern) { '(send $... int)' } let(:ruby) { '5 + 4' } let(:captured_val) { [s(:int, 5), :+] } it_behaves_like :single_capture end context 'with a remaining sequence at the end' do let(:pattern) { '(send $... (int 4))' } let(:ruby) { '5 + 4' } let(:captured_val) { [s(:int, 5), :+] } it_behaves_like :single_capture end context 'with a remaining set at the end' do let(:pattern) { '(send $... {int float})' } let(:ruby) { '5 + 4' } let(:captured_val) { [s(:int, 5), :+] } it_behaves_like :single_capture end context 'with a remaining [] at the end' do let(:pattern) { '(send $... [(int even?) (int zero?)])' } let(:ruby) { '5 + 0' } let(:captured_val) { [s(:int, 5), :+] } it_behaves_like :single_capture end context 'with a remaining literal at the end' do let(:pattern) { '(send $... :inc)' } let(:ruby) { '5.inc' } let(:captured_val) { [s(:int, 5)] } it_behaves_like :single_capture end context 'with a remaining wildcard at the end' do let(:pattern) { '(send $... _)' } let(:ruby) { '5.inc' } let(:captured_val) { [s(:int, 5)] } it_behaves_like :single_capture end context 'with a remaining capture at the end' do let(:pattern) { '(send $... $_)' } let(:ruby) { '5 + 4' } let(:captured_vals) { [[s(:int, 5), :+], s(:int, 4)] } it_behaves_like :multiple_capture end context 'at the very beginning of a sequence' do let(:pattern) { '($... (int 1))' } let(:ruby) { '10 * 1' } let(:captured_val) { [s(:int, 10), :*] } it_behaves_like :single_capture end end describe 'captures within sets' do context 'on simple subpatterns' do let(:pattern) { '{$send $int $float}' } let(:ruby) { '2.0' } let(:captured_val) { s(:float, 2.0) } it_behaves_like :single_capture end context 'within nested sequences' do let(:pattern) { '{(send $_ $_) (const $_ $_)}' } let(:ruby) { 'Namespace::CONST' } let(:captured_vals) { [s(:const, nil, :Namespace), :CONST] } it_behaves_like :multiple_capture end context 'with complex nesting' do let(:pattern) do '{(send {$int $float} {$:inc $:dec}) ' \ '[!nil {($_ sym $_) (send ($_ $_) :object_id)}]}' end let(:ruby) { '10.object_id' } let(:captured_vals) { [:int, 10] } it_behaves_like :multiple_capture end context 'with a different number of captures in each branch' do let(:pattern) { '{(send $...) (int $...) (send $_ $_)}' } it_behaves_like :invalid end end describe 'negation' do context 'on a symbol' do let(:pattern) { '(send _ !:abc)' } context 'with a matching symbol' do let(:ruby) { 'obj.abc' } it_behaves_like :nonmatching end context 'with a non-matching symbol' do let(:ruby) { 'obj.xyz' } it_behaves_like :matching end context 'with a non-matching symbol, but too many children' do let(:ruby) { 'obj.xyz(1)' } it_behaves_like :nonmatching end end context 'on a string' do let(:pattern) { '(send (str !"foo") :upcase)' } context 'with a matching string' do let(:ruby) { '"foo".upcase' } it_behaves_like :nonmatching end context 'with a non-matching symbol' do let(:ruby) { '"bar".upcase' } it_behaves_like :matching end end context 'on a set' do let(:pattern) { '(ivasgn _ !(int {1 2}))' } context 'with a matching value' do let(:ruby) { '@a = 1' } it_behaves_like :nonmatching end context 'with a non-matching value' do let(:ruby) { '@a = 3' } it_behaves_like :matching end end context 'on a sequence' do let(:pattern) { '!(ivasgn :@a ...)' } context 'with a matching node' do let(:ruby) { '@a = 1' } it_behaves_like :nonmatching end context 'with a node of different type' do let(:ruby) { '@@a = 1' } it_behaves_like :matching end context 'with a node with non-matching children' do let(:ruby) { '@b = 1' } it_behaves_like :matching end end context 'on square brackets' do let(:pattern) { '![!int !float]' } context 'with a node which meets all requirements of []' do let(:ruby) { '"abc"' } it_behaves_like :nonmatching end context 'with a node which meets only 1 requirement of []' do let(:ruby) { '1' } it_behaves_like :matching end end context 'when nested in complex ways' do let(:pattern) { '!(send !{int float} !:+ !(send _ :to_i))' } context 'with (send str :+ (send str :to_i))' do let(:ruby) { '"abc" + "1".to_i' } it_behaves_like :matching end context 'with (send int :- int)' do let(:ruby) { '1 - 1' } it_behaves_like :matching end context 'with (send str :<< str)' do let(:ruby) { '"abc" << "xyz"' } it_behaves_like :nonmatching end end end describe 'ellipsis' do context 'preceding a capture' do let(:pattern) { '(send array :push ... $_)' } let(:ruby) { '[1].push(2, 3, 4)' } let(:captured_val) { s(:int, 4) } it_behaves_like :single_capture end context 'with a wildcard at the end, but no remaining child to match it' do let(:pattern) { '(send array :zip array ... _)' } let(:ruby) { '[1,2].zip([3,4])' } it_behaves_like :nonmatching end context 'with a nodetype at the end, but no remaining child to match it' do let(:pattern) { '(send array :zip array ... array)' } let(:ruby) { '[1,2].zip([3,4])' } it_behaves_like :nonmatching end context 'with a nested sequence at the end, but no remaining child' do let(:pattern) { '(send array :zip array ... (array ...))' } let(:ruby) { '[1,2].zip([3,4])' } it_behaves_like :nonmatching end context 'with a set at the end, but no remaining child to match it' do let(:pattern) { '(send array :zip array ... {array})' } let(:ruby) { '[1,2].zip([3,4])' } it_behaves_like :nonmatching end context 'with [] at the end, but no remaining child to match it' do let(:pattern) { '(send array :zip array ... [array !nil])' } let(:ruby) { '[1,2].zip([3,4])' } it_behaves_like :nonmatching end context 'at the very beginning of a sequence' do let(:pattern) { '(... (int 1))' } let(:ruby) { '10 * 1' } it_behaves_like :matching end end describe 'predicates' do context 'in root position' do let(:pattern) { 'send_type?' } let(:ruby) { '1.inc' } it_behaves_like :matching end context 'at head position of a sequence' do # called on the type symbol let(:pattern) { '(!nil? int ...)' } let(:ruby) { '1.inc' } it_behaves_like :matching end context 'applied to an integer for which the predicate is true' do let(:pattern) { '(send (int odd?) :inc)' } let(:ruby) { '1.inc' } it_behaves_like :matching end context 'applied to an integer for which the predicate is false' do let(:pattern) { '(send (int odd?) :inc)' } let(:ruby) { '2.inc' } it_behaves_like :nonmatching end context 'when captured' do let(:pattern) { '(send (int $odd?) :inc)' } let(:ruby) { '1.inc' } let(:captured_val) { 1 } it_behaves_like :single_capture end context 'when negated' do let(:pattern) { '(send int !nil?)' } let(:ruby) { '1.inc' } it_behaves_like :matching end context 'when in last-child position, but all children have already ' \ 'been matched' do let(:pattern) { '(send int :inc ... !nil?)' } let(:ruby) { '1.inc' } it_behaves_like :nonmatching end context 'with one extra argument' do let(:pattern) { '(send (int equal?(%1)) ...)' } let(:ruby) { '1 + 2' } context 'for which the predicate is true' do let(:params) { [1] } it_behaves_like :matching end context 'for which the predicate is false' do let(:params) { [2] } it_behaves_like :nonmatching end end end describe 'params' do context 'in root position' do let(:pattern) { '%1' } let(:params) { [s(:int, 10)] } let(:ruby) { '10' } it_behaves_like :matching end context 'in a nested sequence' do let(:pattern) { '(send (send _ %2) %1)' } let(:params) { %i[inc dec] } let(:ruby) { '5.dec.inc' } it_behaves_like :matching end context 'when preceded by ...' do let(:pattern) { '(send ... %1)' } let(:params) { [s(:int, 10)] } let(:ruby) { '1 + 10' } it_behaves_like :matching end context 'when preceded by $...' do let(:pattern) { '(send $... %1)' } let(:params) { [s(:int, 10)] } let(:ruby) { '1 + 10' } let(:captured_val) { [s(:int, 1), :+] } it_behaves_like :single_capture end context 'when captured' do let(:pattern) { '(const _ $%1)' } let(:params) { [:A] } let(:ruby) { 'Namespace::A' } let(:captured_val) { :A } it_behaves_like :single_capture end context 'when negated, with a matching value' do let(:pattern) { '(const _ !%1)' } let(:params) { [:A] } let(:ruby) { 'Namespace::A' } it_behaves_like :nonmatching end context 'when negated, with a nonmatching value' do let(:pattern) { '(const _ !%1)' } let(:params) { [:A] } let(:ruby) { 'Namespace::B' } it_behaves_like :matching end context 'without explicit number' do let(:pattern) { '(const %2 %)' } let(:params) { [:A, s(:const, nil, :Namespace)] } let(:ruby) { 'Namespace::A' } it_behaves_like :matching end context 'when inside a union, with a matching value' do let(:pattern) { '{str (int %)}' } let(:params) { [10] } let(:ruby) { '10' } it_behaves_like :matching end context 'when inside a union, with a nonmatching value' do let(:pattern) { '{str (int %)}' } let(:params) { [10] } let(:ruby) { '1.0' } it_behaves_like :nonmatching end context 'when inside an intersection' do let(:pattern) { '(int [!%1 %2 !zero?])' } let(:params) { [10, 20] } let(:ruby) { '20' } it_behaves_like :matching end context 'param number zero' do # refers to original target node passed to #match let(:pattern) { '^(send %0 :+ (int 2))' } let(:ruby) { '1 + 2' } context 'in a position which matches original target node' do let(:node) { root_node.children[0] } it_behaves_like :matching end context 'in a position which does not match original target node' do let(:node) { root_node.children[2] } it_behaves_like :nonmatching end end end describe 'caret (ascend)' do context 'used with a node type' do let(:ruby) { '1.inc' } let(:node) { root_node.children[0] } context 'which matches' do let(:pattern) { '^send' } it_behaves_like :matching end context "which doesn't match" do let(:pattern) { '^const' } it_behaves_like :nonmatching end end context 'repeated twice' do # ascends to grandparent node let(:pattern) { '^^block' } let(:ruby) { '1.inc { something }' } let(:node) { root_node.children[0].children[0] } it_behaves_like :matching end context 'inside an intersection' do let(:pattern) { '^[!nil send ^(block ...)]' } let(:ruby) { '1.inc { something }' } let(:node) { root_node.children[0].children[0] } it_behaves_like :matching end context 'inside a union' do let(:pattern) { '{^send ^^send}' } let(:ruby) { '"str".concat(local += "abc")' } let(:node) { root_node.children[2].children[2] } it_behaves_like :matching end # NOTE!! a pitfall of doing this is that unification is done using #== # This means that 'identical' AST nodes, which are not really identical # because they have different metadata, will still unify context 'using unification to match self within parent' do let(:pattern) { '[_self ^(send _ _ _self)]' } let(:ruby) { '1 + 2' } context 'with self in the right position' do let(:node) { root_node.children[2] } it_behaves_like :matching end context 'with self in the wrong position' do let(:node) { root_node.children[0] } it_behaves_like :nonmatching end end end describe 'funcalls' do module RuboCop class NodePattern def goodmatch(_arg1) true end def badmatch(_arg1) false end def witharg(_arg1, arg2) arg2 end def withargs(_arg1, _arg2, arg3) arg3 end end end context 'without extra arguments' do let(:pattern) { '(lvasgn #goodmatch ...)' } let(:ruby) { 'a = 1' } it_behaves_like :matching end end describe 'commas' do context 'with commas randomly strewn around' do let(:pattern) { ',,(,send,, ,int,:+, int ), ' } let(:ruby) { '1 + 2' } it_behaves_like :invalid end end describe 'bad syntax' do context 'with empty parentheses' do let(:pattern) { '()' } it_behaves_like :invalid end context 'with unmatched opening paren' do let(:pattern) { '(send (const)' } it_behaves_like :invalid end context 'with unmatched closing paren' do let(:pattern) { '(send (const)))' } it_behaves_like :invalid end context 'with unmatched opening curly' do let(:pattern) { '{send const' } it_behaves_like :invalid end context 'with unmatched closing curly' do let(:pattern) { '{send const}}' } it_behaves_like :invalid end context 'with negated closing paren' do let(:pattern) { '(send (const) !)' } it_behaves_like :invalid end context 'with negated closing curly' do let(:pattern) { '{send const !}' } it_behaves_like :invalid end context 'with negated ellipsis' do let(:pattern) { '(send !...)' } it_behaves_like :invalid end context 'with doubled ellipsis' do let(:pattern) { '(send ... ...)' } it_behaves_like :invalid end end end rubocop-0.52.1/spec/rubocop/options_spec.rb000066400000000000000000000332741322072016200207110ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Options, :isolated_environment do include FileHelper subject(:options) { described_class.new } before do $stdout = StringIO.new $stderr = StringIO.new end after do $stdout = STDOUT $stderr = STDERR end def abs(path) File.expand_path(path) end describe 'option' do describe '-h/--help' do it 'exits cleanly' do expect { options.parse ['-h'] }.to exit_with_code(0) expect { options.parse ['--help'] }.to exit_with_code(0) end it 'shows help text' do begin options.parse(['--help']) rescue SystemExit # rubocop:disable Lint/HandleExceptions end expected_help = <<-OUTPUT.strip_indent Usage: rubocop [options] [file1, file2, ...] -L, --list-target-files List all files RuboCop will inspect. --except [COP1,COP2,...] Disable the given cop(s). --only [COP1,COP2,...] Run only the given cop(s). --only-guide-cops Run only cops for rules that link to a style guide. -c, --config FILE Specify configuration file. --auto-gen-config Generate a configuration file acting as a TODO list. --exclude-limit COUNT Used together with --auto-gen-config to set the limit for how many Exclude properties to generate. Default is 15. --force-exclusion Force excluding files specified in the configuration `Exclude` even if they are explicitly passed as arguments. --ignore-parent-exclusion Prevent from inheriting AllCops/Exclude from parent folders. --force-default-config Use default configuration even if configuration files are present in the directory tree. --no-offense-counts Do not include offense counts in configuration file generated by --auto-gen-config. -f, --format FORMATTER Choose an output formatter. This option can be specified multiple times to enable multiple formatters at the same time. [p]rogress (default) [s]imple [c]lang [d]isabled cops via inline comments [fu]ubar [e]macs [j]son [h]tml [fi]les [o]ffenses [w]orst [t]ap [q]uiet custom formatter class name -o, --out FILE Write output to a file instead of STDOUT. This option applies to the previously specified --format, or the default format if no format is specified. -r, --require FILE Require Ruby file. --fail-level SEVERITY Minimum severity (A/R/C/W/E/F) for exit with error code. --show-cops [COP1,COP2,...] Shows the given cops, or all cops by default, and their configurations for the current directory. -F, --fail-fast Inspect files in order of modification time and stop after the first file containing offenses. -C, --cache FLAG Use result caching (FLAG=true) or don't (FLAG=false), default determined by configuration parameter AllCops: UseCache. -d, --debug Display debug info. -D, --[no-]display-cop-names Display cop names in offense messages. Default is true. -E, --extra-details Display extra details in offense messages. -S, --display-style-guide Display style guide URLs in offense messages. -R, --rails Run extra Rails cops. -l, --lint Run only lint cops. -a, --auto-correct Auto-correct offenses. --[no-]color Force color output on or off. -v, --version Display version. -V, --verbose-version Display verbose version. -P, --parallel Use available CPUs to execute inspection in parallel. -s, --stdin FILE Pipe source from STDIN, using FILE in offense reports. This is useful for editor integration. OUTPUT expect($stdout.string).to eq(expected_help) end it 'lists all builtin formatters' do begin options.parse(['--help']) rescue SystemExit # rubocop:disable Lint/HandleExceptions end option_sections = $stdout.string.lines.slice_before(/^\s*-/) format_section = option_sections.find do |lines| lines.first =~ /^\s*-f/ end formatter_keys = format_section.reduce([]) do |keys, line| match = line.match(/^[ ]{39}(\[[a-z\]]+)/) next keys unless match keys << match.captures.first.gsub(/\[|\]/, '') end.sort expected_formatter_keys = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS .keys.sort expect(formatter_keys).to eq(expected_formatter_keys) end end describe 'incompatible cli options' do it 'rejects using -v with -V' do msg = 'Incompatible cli options: [:version, :verbose_version]' expect { options.parse %w[-vV] } .to raise_error(ArgumentError, msg) end it 'rejects using -v with --show-cops' do msg = 'Incompatible cli options: [:version, :show_cops]' expect { options.parse %w[-v --show-cops] } .to raise_error(ArgumentError, msg) end it 'rejects using -V with --show-cops' do msg = 'Incompatible cli options: [:verbose_version, :show_cops]' expect { options.parse %w[-V --show-cops] } .to raise_error(ArgumentError, msg) end it 'mentions all incompatible options when more than two are used' do msg = 'Incompatible cli options: [:version, :verbose_version,' \ ' :show_cops]' expect { options.parse %w[-vV --show-cops] } .to raise_error(ArgumentError, msg) end end describe '--parallel' do context 'combined with --cache false' do it 'fails with an error message' do msg = ['-P/--parallel uses caching to speed up execution, so ', 'combining with --cache false is not allowed.'].join expect { options.parse %w[--parallel --cache false] } .to raise_error(ArgumentError, msg) end end context 'combined with --auto-correct' do it 'fails with an error message' do msg = '-P/--parallel can not be combined with --auto-correct.' expect { options.parse %w[--parallel --auto-correct] } .to raise_error(ArgumentError, msg) end end context 'combined with --auto-gen-config' do it 'fails with an error message' do msg = '-P/--parallel uses caching to speed up execution, while ' \ '--auto-gen-config needs a non-cached run, so they cannot be ' \ 'combined.' expect { options.parse %w[--parallel --auto-gen-config] } .to raise_error(ArgumentError, msg) end end context 'combined with --fail-fast' do it 'fails with an error message' do msg = '-P/--parallel can not be combined with -F/--fail-fast.' expect { options.parse %w[--parallel --fail-fast] } .to raise_error(ArgumentError, msg) end end end describe '--fail-level' do it 'accepts full severity names' do %w[refactor convention warning error fatal].each do |severity| expect { options.parse(['--fail-level', severity]) } .not_to raise_error end end it 'accepts severity initial letters' do %w[R C W E F].each do |severity| expect { options.parse(['--fail-level', severity]) } .not_to raise_error end end it 'accepts the "fake" severities A/autocorrect' do %w[autocorrect A].each do |severity| expect { options.parse(['--fail-level', severity]) } .not_to raise_error end end end describe '--require' do let(:required_file_path) { './path/to/required_file.rb' } before do create_file('example.rb', '# encoding: utf-8') create_file(required_file_path, "puts 'Hello from required file!'") end it 'requires the passed path' do options.parse(['--require', required_file_path, 'example.rb']) expect($stdout.string).to start_with('Hello from required file!') end end describe '--cache' do it 'fails if no argument is given' do expect { options.parse %w[--cache] } .to raise_error(OptionParser::MissingArgument) end it 'fails if unrecognized argument is given' do expect { options.parse %w[--cache maybe] }.to raise_error(ArgumentError) end it 'accepts true as argument' do expect { options.parse %w[--cache true] }.not_to raise_error end it 'accepts false as argument' do expect { options.parse %w[--cache false] }.not_to raise_error end end describe '--exclude-limit' do it 'fails if given last without argument' do expect { options.parse %w[--auto-gen-config --exclude-limit] } .to raise_error(OptionParser::MissingArgument) end it 'fails if given alone without argument' do expect { options.parse %w[--exclude-limit] } .to raise_error(OptionParser::MissingArgument) end it 'fails if given first without argument' do expect { options.parse %w[--exclude-limit --auto-gen-config] } .to raise_error(OptionParser::MissingArgument) end it 'fails if given without --auto-gen-config' do expect { options.parse %w[--exclude-limit 10] } .to raise_error(ArgumentError) end end describe '--auto-gen-config' do it 'accepts other options' do expect { options.parse %w[--auto-gen-config --rails] } .not_to raise_error end end describe '-s/--stdin' do before do $stdin = StringIO.new $stdin.puts("{ foo: 'bar' }") $stdin.rewind end it 'fails if no paths are given' do expect { options.parse %w[-s] } .to raise_error(OptionParser::MissingArgument) end it 'succeeds with exactly one path' do expect { options.parse %w[--stdin foo] }.not_to raise_error end it 'fails if more than one path is given' do expect { options.parse %w[--stdin foo bar] } .to raise_error(ArgumentError) end end end describe 'options precedence' do def with_env_options(options) ENV['RUBOCOP_OPTS'] = options yield ensure ENV.delete('RUBOCOP_OPTS') end subject { options.parse(command_line_options).first } let(:command_line_options) { %w[--no-color] } context '.rubocop file' do before do create_file('.rubocop', %w[--color --fail-level C]) end it 'has lower precedence then command line options' do is_expected.to eq(color: false, fail_level: :convention) end it 'has lower precedence then options from RUBOCOP_OPTS env variable' do with_env_options '--fail-level W' do is_expected.to eq(color: false, fail_level: :warning) end end end context '.rubocop directory' do before do FileUtils.mkdir '.rubocop' end it 'is ignored and command line options are used' do is_expected.to eq(color: false) end end context 'RUBOCOP_OPTS environment variable' do it 'has lower precedence then command line options' do with_env_options '--color' do is_expected.to eq(color: false) end end it 'has higher precedence then options from .rubocop file' do create_file('.rubocop', %w[--color --fail-level C]) with_env_options '--fail-level W' do is_expected.to eq(color: false, fail_level: :warning) end end end end end rubocop-0.52.1/spec/rubocop/path_util_spec.rb000066400000000000000000000075671322072016200212150ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::PathUtil do describe '#relative_path' do it 'builds paths relative to PWD by default as a stop-gap' do relative = File.join(Dir.pwd, 'relative') expect(described_class.relative_path(relative)).to eq('relative') end it 'supports custom base paths' do expect(described_class.relative_path('/foo/bar', '/foo')).to eq('bar') end end describe '#match_path?', :isolated_environment do include FileHelper before do create_file('file', '') create_file('dir/file', '') create_file('dir/files', '') create_file('dir/dir/file', '') create_file('dir/sub/file', '') create_file('dir/.hidden/file', '') create_file('dir/.hidden_file', '') $stderr = StringIO.new end after { $stderr = STDERR } it 'does not match dir/** for file in hidden dir' do expect(described_class.match_path?('dir/**', 'dir/.hidden/file')) .to be(false) expect($stderr.string).to eq('') end it 'does not match dir/** for hidden file' do expect(described_class.match_path?('dir/**', 'dir/.hidden_file')) .to be(false) expect($stderr.string).to eq('') end it 'does not match file in a subdirectory' do expect(described_class.match_path?('file', 'dir/files')).to be(false) expect(described_class.match_path?('dir', 'dir/file')).to be(false) end it 'matches strings to the full path' do expect(described_class.match_path?("#{Dir.pwd}/dir/file", "#{Dir.pwd}/dir/file")).to be(true) expect(described_class.match_path?( "#{Dir.pwd}/dir/file", "#{Dir.pwd}/dir/dir/file" )).to be(false) end it 'matches glob expressions' do expect(described_class.match_path?('dir/*', 'dir/file')).to be(true) expect(described_class.match_path?('dir/*/*', 'dir/sub/file')).to be(true) expect(described_class.match_path?('dir/**/*', 'dir/sub/file')).to be(true) expect(described_class.match_path?('dir/**/*', 'dir/file')).to be(true) expect(described_class.match_path?('**/*', 'dir/sub/file')).to be(true) expect(described_class.match_path?('**/file', 'file')).to be(true) expect(described_class.match_path?('sub/*', 'dir/sub/file')).to be(false) expect(described_class.match_path?('**/*', 'dir/.hidden/file')).to be(false) expect(described_class.match_path?('**/*', 'dir/.hidden_file')).to be(false) expect(described_class.match_path?('**/.*/*', 'dir/.hidden/file')) .to be(true) expect(described_class.match_path?('**/.*', 'dir/.hidden_file')).to be(true) end it 'matches regexps' do expect(described_class.match_path?(/^d.*e$/, 'dir/file')).to be(0) expect(described_class.match_path?(/^d.*e$/, 'dir/filez')).to be(nil) end it 'does not match invalid UTF-8 paths' do expect(described_class.match_path?(/^d.*$/, "dir/file\xBF")).to be(false) end end describe '#find_file_upwards', :isolated_environment do include FileHelper before do create_file('file', '') create_file('dir/file', '') end it 'returns a file to be found upwards' do expect(described_class.find_file_upwards('file')) .to eq(File.join(Dir.pwd, 'file')) end it 'returns a file when start directory is given' do expect(described_class.find_file_upwards('file', 'dir')) .to eq(File.join(Dir.pwd, 'dir', 'file')) end it 'returns nil when file is not found' do expect(described_class.find_file_upwards('xyz')).to be(nil) expect(described_class.find_file_upwards('xyz', 'dir')).to be(nil) end end end rubocop-0.52.1/spec/rubocop/processed_source_spec.rb000066400000000000000000000140131322072016200225530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::ProcessedSource do include FileHelper subject(:processed_source) { described_class.new(source, ruby_version, path) } let(:ruby_version) { RuboCop::Config::KNOWN_RUBIES.last } let(:source) { <<-RUBY.strip_indent } # encoding: utf-8 def some_method puts 'foo' end some_method RUBY let(:path) { 'path/to/file.rb' } describe '.from_file', :isolated_environment do describe 'when the file exists' do before do create_file(path, 'foo') end let(:processed_source) { described_class.from_file(path, ruby_version) } it 'returns an instance of ProcessedSource' do expect(processed_source.is_a?(described_class)).to be(true) end it "sets the file path to the instance's #path" do expect(processed_source.path).to eq(path) end end it 'raises RuboCop::Error when the file does not exist' do expect do described_class.from_file('foo', ruby_version) end.to raise_error(RuboCop::Error) .with_message(/No such file or directory/) end end describe '#path' do it 'is the path passed to .new' do expect(processed_source.path).to eq(path) end end describe '#buffer' do it 'is a source buffer' do expect(processed_source.buffer.is_a?(Parser::Source::Buffer)).to be(true) end end describe '#ast' do it 'is the root node of AST' do expect(processed_source.ast.is_a?(RuboCop::AST::Node)).to be(true) end end describe '#comments' do it 'is an array of comments' do expect(processed_source.comments.is_a?(Array)).to be(true) expect( processed_source.comments.first.is_a?(Parser::Source::Comment) ).to be(true) end end describe '#tokens' do it 'has an array of tokens' do expect(processed_source.tokens.is_a?(Array)).to be(true) expect(processed_source.tokens.first.is_a?(RuboCop::Token)).to be(true) end end shared_context 'invalid encoding source' do let(:source) do [ '# encoding: utf-8', "# \xf9" ].join("\n") end end describe '#parser_error' do context 'when the source was properly parsed' do it 'is nil' do expect(processed_source.parser_error.nil?).to be(true) end end context 'when the source lacks encoding comment and is really utf-8 ' \ 'encoded but has been read as US-ASCII' do let(:source) do # When files are read into RuboCop, the encoding of source code # lacking an encoding comment will default to the external encoding, # which could for example be US-ASCII if the LC_ALL environment # variable is set to "C". '号码 = 3'.dup.force_encoding('US-ASCII') end it 'is nil' do # ProcessedSource#parse sets UTF-8 as default encoding, so no error. expect(processed_source.parser_error.nil?).to be(true) end end context 'when the source could not be parsed due to encoding error' do include_context 'invalid encoding source' it 'returns the error' do expect(processed_source.parser_error.is_a?(Exception)).to be(true) expect(processed_source.parser_error.message) .to include('invalid byte sequence') end end end describe '#lines' do it 'is an array' do expect(processed_source.lines.is_a?(Array)).to be(true) end it 'has same number of elements as line count' do # Since the source has a trailing newline, there is a final empty line expect(processed_source.lines.size).to eq(6) end it 'contains lines as string without linefeed' do first_line = processed_source.lines.first expect(first_line).to eq('# encoding: utf-8') end end describe '#[]' do context 'when an index is passed' do it 'returns the line' do expect(processed_source[3]).to eq('end') end end context 'when a range is passed' do it 'returns the array of lines' do expect(processed_source[3..4]).to eq(%w[end some_method]) end end context 'when start index and length are passed' do it 'returns the array of lines' do expect(processed_source[3, 2]).to eq(%w[end some_method]) end end end describe 'valid_syntax?' do subject { processed_source.valid_syntax? } context 'when the source is completely valid' do let(:source) { 'def valid_code; end' } it 'returns true' do expect(processed_source.diagnostics.empty?).to be(true) expect(processed_source.valid_syntax?).to be(true) end end context 'when the source is invalid' do let(:source) { 'def invalid_code; en' } it 'returns false' do expect(processed_source.valid_syntax?).to be(false) end end context 'when the source is valid but has some warning diagnostics' do let(:source) { 'do_something *array' } it 'returns true' do expect(processed_source.diagnostics.empty?).to be(false) expect(processed_source.diagnostics.first.level).to eq(:warning) expect(processed_source.valid_syntax?).to be(true) end end context 'when the source could not be parsed due to encoding error' do include_context 'invalid encoding source' it 'returns false' do expect(processed_source.valid_syntax?).to be(false) end end # https://github.com/whitequark/parser/issues/283 context 'when the source itself is valid encoding but includes strange ' \ 'encoding literals that are accepted by MRI' do let(:source) do 'p "\xff"' end it 'returns true' do expect(processed_source.diagnostics.empty?).to be(true) expect(processed_source.valid_syntax?).to be(true) end end context 'when a line starts with an integer literal' do let(:source) { '1 + 1' } # regression test it 'tokenizes the source correctly' do expect(processed_source.tokens[0].text).to eq '1' end end end end rubocop-0.52.1/spec/rubocop/rake_task_spec.rb000066400000000000000000000105261322072016200211550ustar00rootroot00000000000000# frozen_string_literal: true require 'support/file_helper' require 'rubocop/rake_task' RSpec.describe RuboCop::RakeTask do include FileHelper before do Rake::Task.clear end after do Rake::Task.clear end describe 'defining tasks' do it 'creates a rubocop task and a rubocop auto_correct task' do described_class.new expect(Rake::Task.task_defined?(:rubocop)).to be true expect(Rake::Task.task_defined?('rubocop:auto_correct')).to be true end it 'creates a named task and a named auto_correct task' do described_class.new(:lint_lib) expect(Rake::Task.task_defined?(:lint_lib)).to be true expect(Rake::Task.task_defined?('lint_lib:auto_correct')).to be true end end describe 'running tasks' do before do $stdout = StringIO.new $stderr = StringIO.new end after do $stdout = STDOUT $stderr = STDERR end it 'runs with default options' do described_class.new cli = double('cli', run: 0) allow(RuboCop::CLI).to receive(:new) { cli } expect(cli).to receive(:run).with([]) Rake::Task['rubocop'].execute end it 'runs with specified options if a block is given' do described_class.new do |task| task.patterns = ['lib/**/*.rb'] task.formatters = ['files'] task.fail_on_error = false task.options = ['--display-cop-names'] task.verbose = false end cli = double('cli', run: 0) allow(RuboCop::CLI).to receive(:new) { cli } options = ['--format', 'files', '--display-cop-names', 'lib/**/*.rb'] expect(cli).to receive(:run).with(options) Rake::Task['rubocop'].execute end it 'allows nested arrays inside formatters, options, and requires' do described_class.new do |task| task.formatters = [['files']] task.requires = [['library']] task.options = [['--display-cop-names']] end cli = double('cli', run: 0) allow(RuboCop::CLI).to receive(:new) { cli } options = ['--format', 'files', '--require', 'library', '--display-cop-names'] expect(cli).to receive(:run).with(options) Rake::Task['rubocop'].execute end it 'will not error when result is not 0 and fail_on_error is false' do described_class.new do |task| task.fail_on_error = false end cli = double('cli', run: 1) allow(RuboCop::CLI).to receive(:new) { cli } expect { Rake::Task['rubocop'].execute }.not_to raise_error end it 'exits when result is not 0 and fail_on_error is true' do described_class.new cli = double('cli', run: 1) allow(RuboCop::CLI).to receive(:new) { cli } expect { Rake::Task['rubocop'].execute }.to raise_error(SystemExit) end it 'uses the default formatter from .rubocop.yml if no formatter ' \ 'option is given', :isolated_environment do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: DefaultFormatter: offenses YAML create_file('test.rb', '$:') described_class.new do |task| task.options = ['test.rb'] end expect { Rake::Task['rubocop'].execute }.to raise_error(SystemExit) expect($stdout.string).to eq(<<-RESULT.strip_indent) Running RuboCop... 1 Style/SpecialGlobalVars -- 1 Total RESULT expect($stderr.string.strip).to eq 'RuboCop failed!' end context 'auto_correct' do it 'runs with --auto-correct' do described_class.new cli = double('cli', run: 0) allow(RuboCop::CLI).to receive(:new) { cli } options = ['--auto-correct'] expect(cli).to receive(:run).with(options) Rake::Task['rubocop:auto_correct'].execute end it 'runs with with the options that were passed to its parent task' do described_class.new do |task| task.patterns = ['lib/**/*.rb'] task.formatters = ['files'] task.fail_on_error = false task.options = ['-D'] task.verbose = false end cli = double('cli', run: 0) allow(RuboCop::CLI).to receive(:new) { cli } options = ['--auto-correct', '--format', 'files', '-D', 'lib/**/*.rb'] expect(cli).to receive(:run).with(options) Rake::Task['rubocop:auto_correct'].execute end end end end rubocop-0.52.1/spec/rubocop/remote_config_spec.rb000066400000000000000000000056371322072016200220400ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::RemoteConfig do include FileHelper subject(:remote_config) do described_class.new(remote_config_url, base_dir).file end let(:remote_config_url) { 'http://example.com/rubocop.yml' } let(:base_dir) { '.' } let(:cached_file_name) { '.rubocop-http---example-com-rubocop-yml' } let(:cached_file_path) { File.expand_path(cached_file_name, base_dir) } before do stub_request(:get, remote_config_url) .to_return(status: 200, body: "Style/Encoding:\n Enabled: true") end after do File.unlink cached_file_path if File.exist? cached_file_path end describe '.file' do it 'downloads the file if the file does not exist' do expect(remote_config).to eq(cached_file_path) expect(File.exist?(cached_file_path)).to be_truthy end it 'does not download the file if cache lifetime has not been reached' do FileUtils.touch cached_file_path, mtime: Time.now - ((60 * 60) * 20) expect(remote_config).to eq(cached_file_path) assert_not_requested :get, remote_config_url end it 'downloads the file if cache lifetime has been reached' do FileUtils.touch cached_file_path, mtime: Time.now - ((60 * 60) * 30) expect(remote_config).to eq(cached_file_path) assert_requested :get, remote_config_url end context 'when the remote URL responds with redirect' do let(:new_location) { 'http://cdn.example.com/rubocop.yml' } before do stub_request(:get, remote_config_url) .to_return(headers: { 'Location' => new_location }) stub_request(:get, new_location) .to_return(status: 200, body: "Style/Encoding:\n Enabled: true") end it 'follows the redirect and downloads the file' do expect(remote_config).to eq(cached_file_path) expect(File.exist?(cached_file_path)).to be_truthy end end context 'when the remote URL responds with not modified' do before do stub_request(:get, remote_config_url) .to_return(status: 304) end it 'reuses the existing cached file' do FileUtils.touch cached_file_path, mtime: Time.now - ((60 * 60) * 30) expect do remote_config end.not_to change(File.stat(cached_file_path), :mtime) assert_requested :get, remote_config_url end end context 'when the network is inaccessible' do before do stub_request(:get, remote_config_url) .to_raise(SocketError) end it 'reuses the existing cached file' do expect(remote_config).to eq(cached_file_path) end end context 'when the remote URL responds with 500' do before do stub_request(:get, remote_config_url) .to_return(status: 500) end it 'raises error' do expect do remote_config end.to raise_error(Net::HTTPFatalError) end end end end rubocop-0.52.1/spec/rubocop/result_cache_spec.rb000066400000000000000000000200761322072016200216530ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::ResultCache, :isolated_environment do include FileHelper subject(:cache) do described_class.new(file, options, config_store, cache_root) end let(:file) { 'example.rb' } let(:options) { {} } let(:config_store) { double('config_store', for: RuboCop::Config.new) } let(:cache_root) { "#{Dir.pwd}/rubocop_cache" } let(:offenses) do [RuboCop::Cop::Offense.new(:warning, location, 'unused var', 'Lint/UselessAssignment')] end let(:location) do source_buffer = Parser::Source::Buffer.new(file) source_buffer.read Parser::Source::Range.new(source_buffer, 0, 2) end def abs(path) File.expand_path(path) end before do create_file('example.rb', <<-RUBY.strip_indent) # Hello x = 1 RUBY allow(config_store).to receive(:for).with('example.rb') .and_return(RuboCop::Config.new) end describe 'cached result that was saved with no command line option' do shared_examples 'valid' do it 'is valid and can be loaded' do cache.save(offenses) cache2 = described_class.new(file, options2, config_store, cache_root) expect(cache2.valid?).to eq(true) saved_offenses = cache2.load expect(saved_offenses).to eq(offenses) end end context 'when no option is given' do let(:options2) { {} } include_examples 'valid' context 'when file contents have changed' do it 'is invalid' do cache.save(offenses) create_file('example.rb', ['x = 2']) cache2 = described_class.new(file, options, config_store, cache_root) expect(cache2.valid?).to eq(false) end end context 'when file permission have changed' do unless RuboCop::Platform.windows? it 'is invalid' do cache.save(offenses) FileUtils.chmod('+x', file) cache2 = described_class.new(file, options, config_store, cache_root) expect(cache2.valid?).to eq(false) end end end context 'when a symlink is present in the cache location' do let(:cache2) do described_class.new(file, options, config_store, cache_root) end let(:attack_target_dir) { Dir.mktmpdir } before do # Avoid getting "symlink() function is unimplemented on this # machine" on Windows. if RuboCop::Platform.windows? skip 'Symlinks not implemented on Windows' end cache.save(offenses) Find.find(cache_root) do |path| next unless File.basename(path) == '_' FileUtils.rm_rf(path) FileUtils.ln_s(attack_target_dir, path) end $stderr = StringIO.new end after do FileUtils.rm_rf(attack_target_dir) $stderr = STDERR end context 'and symlink attack protection is enabled' do it 'prevents caching and prints a warning' do cache2.save(offenses) # The cache file has not been created because there was a symlink in # its path. expect(cache2.valid?).to eq(false) expect($stderr.string) .to match(/Warning: .* is a symlink, which is not allowed.\n/) end end context 'and symlink attack protection is disabled' do before do allow(config_store).to receive(:for).with('.').and_return( RuboCop::Config.new( 'AllCops' => { 'AllowSymlinksInCacheRootDirectory' => true } ) ) end it 'permits caching and prints no warning' do cache2.save(offenses) expect(cache2.valid?).to eq(true) expect($stderr.string) .not_to match(/Warning: .* is a symlink, which is not allowed.\n/) end end end end context 'when --format is given' do let(:options2) { { format: 'simple' } } include_examples 'valid' end context 'when --only is given' do it 'is invalid' do cache.save(offenses) cache2 = described_class.new(file, { only: ['Metrics/LineLength'] }, config_store, cache_root) expect(cache2.valid?).to eq(false) end end context 'when --display-cop-names is given' do it 'is invalid' do cache.save(offenses) cache2 = described_class.new(file, { display_cop_names: true }, config_store, cache_root) expect(cache2.valid?).to eq(false) end end context 'when a cache source is read' do it 'has utf8 encoding' do cache.save(offenses) result = cache.load loaded_encoding = result[0].location.source.encoding expect(loaded_encoding).to eql(Encoding::UTF_8) end end end describe '#save' do context 'when the default internal encoding is UTF-8' do let(:offenses) do [RuboCop::Cop::Offense.new(:warning, location, "unused var \xF0", 'Lint/UselessAssignment')] end before { Encoding.default_internal = Encoding::UTF_8 } after { Encoding.default_internal = nil } it 'writes non UTF-8 encodable data to file with no exception' do cache.save(offenses) end end end describe '.cleanup' do before do cfg = RuboCop::Config.new('AllCops' => { 'MaxFilesInCache' => 1 }) allow(config_store).to receive(:for).with('.').and_return(cfg) allow(config_store).to receive(:for).with('other.rb').and_return(cfg) create_file('other.rb', ['x = 1']) $stdout = StringIO.new end after do $stdout = STDOUT end it 'removes the oldest files in the cache if needed' do cache.save(offenses) cache2 = described_class.new('other.rb', options, config_store, cache_root) expect(Dir["#{cache_root}/*/_/*"].size).to eq(1) cache.class.cleanup(config_store, :verbose, cache_root) expect($stdout.string).to eq('') cache2.save(offenses) underscore_dir = Dir["#{cache_root}/*/_"].first expect(Dir["#{underscore_dir}/*"].size).to eq(2) cache.class.cleanup(config_store, :verbose, cache_root) expect(File.exist?(underscore_dir)).to be_falsey expect($stdout.string) .to eq("Removing the 2 oldest files from #{cache_root}\n") end end describe 'the cache path' do let(:config_store) { double('config_store') } let(:puid) { Process.uid.to_s } before do all_cops = { 'AllCops' => { 'CacheRootDirectory' => cache_root_directory } } config = RuboCop::Config.new(all_cops) allow(config_store).to receive(:for).with('.').and_return(config) end context 'when CacheRootDirectory not set' do let(:cache_root_directory) { nil } context 'and XDG_CACHE_HOME is not set' do before { ENV['XDG_CACHE_HOME'] = nil } it 'contains $HOME/.cache' do cacheroot = RuboCop::ResultCache.cache_root(config_store) expect(cacheroot) .to eq(File.join(Dir.home, '.cache', 'rubocop_cache')) end end context 'and XDG_CACHE_HOME is set' do around do |example| ENV['XDG_CACHE_HOME'] = '/etc/rccache' begin example.run ensure ENV.delete('XDG_CACHE_HOME') end end it 'contains the given path and UID' do cacheroot = RuboCop::ResultCache.cache_root(config_store) expect(cacheroot) .to eq(File.join(ENV['XDG_CACHE_HOME'], puid, 'rubocop_cache')) end end end context 'when CacheRootDirectory is set' do let(:cache_root_directory) { '/opt' } it 'contains the given root' do cacheroot = RuboCop::ResultCache.cache_root(config_store) expect(cacheroot).to eq(File.join('/opt', 'rubocop_cache')) end end end end rubocop-0.52.1/spec/rubocop/runner_spec.rb000066400000000000000000000100621322072016200205150ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop class Runner attr_writer :errors # Needed only for testing. end end RSpec.describe RuboCop::Runner, :isolated_environment do include FileHelper let(:formatter_output_path) { 'formatter_output.txt' } let(:formatter_output) { File.read(formatter_output_path) } before do create_file('example.rb', source) end describe '#run' do subject(:runner) { described_class.new(options, RuboCop::ConfigStore.new) } let(:options) { { formatters: [['progress', formatter_output_path]] } } context 'if there are no offenses in inspected files' do let(:source) { <<-RUBY.strip_indent } # frozen_string_literal: true def valid_code; end RUBY it 'returns true' do expect(runner.run([])).to be true end end context 'if there is an offense in an inspected file' do let(:source) { <<-RUBY.strip_indent } # frozen_string_literal: true def INVALID_CODE; end RUBY it 'returns false' do expect(runner.run([])).to be false end it 'sends the offense to a formatter' do runner.run([]) expect(formatter_output).to eq <<-RESULT.strip_indent Inspecting 1 file C Offenses: example.rb:3:5: C: Naming/MethodName: Use snake_case for method names. def INVALID_CODE; end ^^^^^^^^^^^^ 1 file inspected, 1 offense detected RESULT end end context 'if a cop crashes' do before do # The cache responds that it's not valid, which means that new results # should normally be collected and saved... cache = double('cache', 'valid?' => false) # ... but there's a crash in one cop. runner.errors = ['An error occurred in ...'] allow(RuboCop::ResultCache).to receive(:new) { cache } end let(:source) { '' } it 'does not call ResultCache#save' do # The double doesn't define #save, so we'd get an error if it were # called. runner.run([]) end end context 'if -s/--stdin is used with an offense' do before do # Make Style/EndOfLine give same output regardless of platform. create_file('.rubocop.yml', <<-YAML.strip_indent) Layout/EndOfLine: EnforcedStyle: lf YAML end let(:options) do { formatters: [['progress', formatter_output_path]], stdin: <<-RUBY.strip_indent # frozen_string_literal: true def INVALID_CODE; end RUBY } end let(:source) { '' } it 'returns false' do expect(runner.run([])).to be false end it 'sends the offense to a formatter' do runner.run([]) expect(formatter_output).to eq <<-RESULT.strip_indent Inspecting 1 file C Offenses: example.rb:3:5: C: Naming/MethodName: Use snake_case for method names. def INVALID_CODE; end ^^^^^^^^^^^^ 1 file inspected, 1 offense detected RESULT end end end describe '#run with cops autocorrecting each-other' do subject(:runner) do runner_class = Class.new(RuboCop::Runner) do def mobilized_cop_classes(_config) RuboCop::Cop::Registry.new( [ RuboCop::Cop::Test::ClassMustBeAModuleCop, RuboCop::Cop::Test::ModuleMustBeAClassCop ] ) end end runner_class.new(options, RuboCop::ConfigStore.new) end let(:options) do { auto_correct: true, formatters: [['progress', formatter_output_path]] } end context 'if there is an offense in an inspected file' do let(:source) { <<-RUBY.strip_indent } # frozen_string_literal: true class Klass end RUBY it 'aborts because of an infinite loop' do expect do runner.run([]) end.to raise_error RuboCop::Runner::InfiniteCorrectionLoop end end end end rubocop-0.52.1/spec/rubocop/string_interpreter_spec.rb000066400000000000000000000022331322072016200231360ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::StringInterpreter do describe '.interpret' do shared_examples 'simple escape' do |escaped| it "handles #{escaped}" do expect(described_class.interpret(escaped)).to eq escaped[1..-1] end end it 'handles hex' do expect(described_class.interpret('\\\\x68')).to eq('\x68') end it 'handles octal' do expect(described_class.interpret('\\\\150')).to eq('\150') end it 'handles unicode' do expect(described_class.interpret('\\\\u0068')).to eq('\u0068') end it 'handles extended unicode' do expect(described_class.interpret('\\\\u{0068 0068}')) .to eq('\\u{0068 0068}') end it_behaves_like 'simple escape', '\\\\a' it_behaves_like 'simple escape', '\\\\b' it_behaves_like 'simple escape', '\\\\e' it_behaves_like 'simple escape', '\\\\f' it_behaves_like 'simple escape', '\\\\n' it_behaves_like 'simple escape', '\\\\r' it_behaves_like 'simple escape', '\\\\s' it_behaves_like 'simple escape', '\\\\t' it_behaves_like 'simple escape', '\\\\v' it_behaves_like 'simple escape', '\\\\n' end end rubocop-0.52.1/spec/rubocop/string_util_spec.rb000066400000000000000000000024301322072016200215470ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::StringUtil::Jaro do { %w[foo foo] => 1.000, %w[foo bar] => 0.000, %w[martha marhta] => 0.944, %w[dwayne duane] => 0.822 }.each do |strings, expected| context "with #{strings.first.inspect} and #{strings.last.inspect}" do subject(:distance) { described_class.distance(*strings) } it "returns #{expected}" do expect(distance).to be_within(0.001).of(expected) end end end end RSpec.describe RuboCop::StringUtil::JaroWinkler do # These samples are derived from Apache Lucene project. # https://github.com/apache/lucene-solr/blob/lucene_solr_4_9_0/lucene/suggest/src/test/org/apache/lucene/search/spell/TestJaroWinklerDistance.java { %w[al al] => 1.000, %w[martha marhta] => 0.961, %w[jones johnson] => 0.832, %w[abcvwxyz cabvwxyz] => 0.958, %w[dwayne duane] => 0.840, %w[dixon dicksonx] => 0.813, %w[fvie ten] => 0.000 }.each do |strings, expected| context "with #{strings.first.inspect} and #{strings.last.inspect}" do subject(:distance) { described_class.distance(*strings) } it "returns #{expected}" do expect(distance).to be_within(0.001).of(expected) end end end end rubocop-0.52.1/spec/rubocop/target_finder_spec.rb000066400000000000000000000201001322072016200220130ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::TargetFinder, :isolated_environment do include FileHelper subject(:target_finder) do described_class.new(config_store, options) end let(:config_store) { RuboCop::ConfigStore.new } let(:options) { { force_exclusion: force_exclusion, debug: debug } } let(:force_exclusion) { false } let(:debug) { false } before do create_file('dir1/ruby1.rb', '# encoding: utf-8') create_file('dir1/ruby2.rb', '# encoding: utf-8') create_file('dir1/file.txt', '# encoding: utf-8') create_file('dir1/file', '# encoding: utf-8') create_file('dir1/executable', '#!/usr/bin/env ruby') create_file('dir2/ruby3.rb', '# encoding: utf-8') end describe '#find' do let(:found_files) { target_finder.find(args) } let(:found_basenames) { found_files.map { |f| File.basename(f) } } let(:args) { [] } it 'returns absolute paths' do expect(found_files.empty?).to be(false) found_files.each do |file| expect(file.sub(/^[A-Z]:/, '')).to start_with('/') end end context 'when no argument is passed' do let(:args) { [] } it 'finds files under the current directory' do Dir.chdir('dir1') do expect(found_files.empty?).to be(false) found_files.each do |file| expect(file).to include('/dir1/') expect(file).not_to include('/dir2/') end end end end context 'when a directory path is passed' do let(:args) { ['../dir2'] } it 'finds files under the specified directory' do Dir.chdir('dir1') do expect(found_files.empty?).to be(false) found_files.each do |file| expect(file).to include('/dir2/') expect(file).not_to include('/dir1/') end end end end context 'when a non-ruby file is passed' do let(:args) { ['dir2/file'] } it "doesn't pick the file" do expect(found_basenames.empty?).to be(true) end end context 'when files with a ruby extension are passed' do let(:args) { RuboCop::RUBY_EXTENSIONS.map { |ext| "dir2/file#{ext}" } } it 'picks all the ruby files' do expect(found_basenames).to eq( RuboCop::RUBY_EXTENSIONS.map { |ext| "file#{ext}" } ) end end context 'when a file with a ruby filename is passed' do let(:args) { RuboCop::RUBY_FILENAMES.map { |name| "dir2/#{name}" } } it 'picks all the ruby files' do expect(found_basenames).to eq(RuboCop::RUBY_FILENAMES) end end context 'when files with ruby interpreters are passed' do let(:args) { RuboCop::RUBY_INTERPRETERS.map { |name| "dir2/#{name}" } } before do RuboCop::RUBY_INTERPRETERS.each do |interpreter| create_file("dir2/#{interpreter}", "#!/usr/bin/#{interpreter}") end end it 'picks all the ruby files' do expect(found_basenames).to eq(RuboCop::RUBY_INTERPRETERS) end end context 'when a pattern is passed' do let(:args) { ['dir1/*2.rb'] } it 'finds files which match the pattern' do expect(found_basenames).to eq(['ruby2.rb']) end end context 'when same paths are passed' do let(:args) { %w[dir1 dir1] } it 'does not return duplicated file paths' do count = found_basenames.count { |f| f == 'ruby1.rb' } expect(count).to eq(1) end end context 'when some paths are specified in the configuration Exclude ' \ 'and they are explicitly passed as arguments' do before do create_file('.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - dir1/ruby1.rb - 'dir2/*' YAML create_file('dir1/.rubocop.yml', <<-YAML.strip_indent) AllCops: Exclude: - executable YAML end let(:args) do ['dir1/ruby1.rb', 'dir1/ruby2.rb', 'dir1/exe*', 'dir2/ruby3.rb'] end context 'normally' do it 'does not exclude them' do expect(found_basenames) .to eq(['ruby1.rb', 'ruby2.rb', 'executable', 'ruby3.rb']) end end context "when it's forced to adhere file exclusion configuration" do let(:force_exclusion) { true } it 'excludes them' do expect(found_basenames).to eq(['ruby2.rb']) end end end end describe '#find_files' do let(:found_files) { target_finder.find_files(base_dir, flags) } let(:found_basenames) { found_files.map { |f| File.basename(f) } } let(:base_dir) { Dir.pwd } let(:flags) { 0 } it 'does not search excluded top level directories' do config = double('config') exclude_property = { 'Exclude' => [File.expand_path('dir1/**/*')] } allow(config).to receive(:for_all_cops).and_return(exclude_property) allow(config_store).to receive(:for).and_return(config) expect(found_basenames).not_to include('ruby1.rb') expect(found_basenames).to include('ruby3.rb') end it 'works also if a folder is named ","' do create_file(',/ruby4.rb', '# encoding: utf-8') config = double('config') exclude_property = { 'Exclude' => [File.expand_path('dir1/**/*')] } allow(config).to receive(:for_all_cops).and_return(exclude_property) allow(config_store).to receive(:for).and_return(config) expect(found_basenames).not_to include('ruby1.rb') expect(found_basenames).to include('ruby3.rb') expect(found_basenames).to include('ruby4.rb') end end describe '#target_files_in_dir' do let(:found_files) { target_finder.target_files_in_dir(base_dir) } let(:found_basenames) { found_files.map { |f| File.basename(f) } } let(:base_dir) { '.' } it 'picks files with extension .rb' do rb_file_count = found_files.count { |f| f.end_with?('.rb') } expect(rb_file_count).to eq(3) end it 'picks ruby executable files with no extension' do expect(found_basenames).to include('executable') end it 'does not pick files with no extension and no ruby shebang' do expect(found_basenames).not_to include('file') end it 'does not pick directories' do found_basenames = found_files.map { |f| File.basename(f) } expect(found_basenames).not_to include('dir1') end it 'picks files specified to be included in config' do config = double('config') allow(config).to receive(:file_to_include?) do |file| File.basename(file) == 'file' end allow(config) .to receive(:for_all_cops).and_return('Exclude' => []) allow(config).to receive(:file_to_exclude?).and_return(false) allow(config_store).to receive(:for).and_return(config) expect(found_basenames).to include('file') end it 'does not pick files specified to be excluded in config' do config = double('config').as_null_object allow(config) .to receive(:for_all_cops).and_return('Exclude' => []) allow(config).to receive(:file_to_include?).and_return(false) allow(config).to receive(:file_to_exclude?) do |file| File.basename(file) == 'ruby2.rb' end allow(config_store).to receive(:for).and_return(config) expect(found_basenames).not_to include('ruby2.rb') end context 'when an exception is raised while reading file' do around do |example| original_stderr = $stderr $stderr = StringIO.new begin example.run ensure $stderr = original_stderr end end before do allow_any_instance_of(File).to receive(:readline).and_raise(EOFError) end context 'and debug mode is enabled' do let(:debug) { true } it 'outputs error message' do found_files expect($stderr.string).to include('Unprocessable file') end end context 'and debug mode is disabled' do let(:debug) { false } it 'outputs nothing' do found_files expect($stderr.string.empty?).to be(true) end end end end end rubocop-0.52.1/spec/rubocop/token_spec.rb000066400000000000000000000014101322072016200203210ustar00rootroot00000000000000# frozen_string_literal: true RSpec.describe RuboCop::Token do describe '.from_parser_token' do subject(:token) { described_class.from_parser_token(parser_token) } let(:parser_token) { [type, [text, range]] } let(:type) { :kDEF } let(:text) { 'def' } let(:range) { double('range', line: 42, column: 30) } it "sets parser token's type to rubocop token's type" do expect(token.type).to eq(type) end it "sets parser token's text to rubocop token's text" do expect(token.text).to eq(text) end it "sets parser token's range to rubocop token's pos" do expect(token.pos).to eq(range) end it 'returns a #to_s useful for debugging' do expect(token.to_s).to eq('[[42, 30], kDEF, "def"]') end end end rubocop-0.52.1/spec/spec_helper.rb000066400000000000000000000031701322072016200170140ustar00rootroot00000000000000# frozen_string_literal: true # Disable colors in specs require 'rainbow' Rainbow.enabled = false # Coverage support needs to be required *before* the RuboCop code is required! require 'support/coverage' require 'rubocop' require 'rubocop/cop/internal_affairs' require 'webmock/rspec' require 'powerpack/string/strip_margin' require 'pry' # Require supporting files exposed for testing. require 'rubocop/rspec/support' # Requires supporting files with custom matchers and macros, etc, # in ./support/ and its subdirectories. Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f } RSpec.configure do |config| # These two settings work together to allow you to limit a spec run # to individual examples or groups you care about by tagging them with # `:focus` metadata. When nothing is tagged with `:focus`, all examples # get run. unless defined?(::TestQueue) # See. https://github.com/tmm1/test-queue/issues/60#issuecomment-281948929 config.filter_run :focus config.run_all_when_everything_filtered = true end config.example_status_persistence_file_path = 'spec/examples.txt' config.disable_monkey_patching! config.include RuboCop::RSpec::ExpectOffense config.order = :random Kernel.srand config.seed config.expect_with :rspec do |expectations| expectations.include_chain_clauses_in_custom_matcher_descriptions = true expectations.syntax = :expect # Disable `should` end config.mock_with :rspec do |mocks| mocks.syntax = :expect # Disable `should_receive` and `stub` mocks.verify_partial_doubles = true end config.after do RuboCop::PathUtil.reset_pwd end end rubocop-0.52.1/spec/support/000077500000000000000000000000001322072016200157115ustar00rootroot00000000000000rubocop-0.52.1/spec/support/cli_spec_behavior.rb000066400000000000000000000016561322072016200217060ustar00rootroot00000000000000# frozen_string_literal: true RSpec.shared_context 'cli spec behavior' do include FileHelper def abs(path) File.expand_path(path) end before do $stdout = StringIO.new $stderr = StringIO.new RuboCop::ConfigLoader.debug = false # OPTIMIZE: Makes these specs faster. Work directory (the parent of # .rubocop_cache) is removed afterwards anyway. RuboCop::ResultCache.inhibit_cleanup = true end # Wrap all cli specs in `aggregate_failures` so that the expected and # actual results of every expectation per example are shown. This is # helpful because it shows information like expected and actual # $stdout messages while not using `aggregate_failures` will only # show information about expected and actual exit code around do |example| aggregate_failures(&example) end after do $stdout = STDOUT $stderr = STDERR RuboCop::ResultCache.inhibit_cleanup = false end end rubocop-0.52.1/spec/support/cops/000077500000000000000000000000001322072016200166555ustar00rootroot00000000000000rubocop-0.52.1/spec/support/cops/class_must_be_a_module_cop.rb000066400000000000000000000005701322072016200245350ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Test class ClassMustBeAModuleCop < RuboCop::Cop::Cop def on_class(node) add_offense(node, message: 'Class must be a Module') end def autocorrect(node) ->(corrector) { corrector.replace(node.loc.keyword, 'module') } end end end end end rubocop-0.52.1/spec/support/cops/module_must_be_a_class_cop.rb000066400000000000000000000005701322072016200245350ustar00rootroot00000000000000# frozen_string_literal: true module RuboCop module Cop module Test class ModuleMustBeAClassCop < RuboCop::Cop::Cop def on_module(node) add_offense(node, message: 'Module must be a Class') end def autocorrect(node) ->(corrector) { corrector.replace(node.loc.keyword, 'class') } end end end end end rubocop-0.52.1/spec/support/coverage.rb000066400000000000000000000004671322072016200200400ustar00rootroot00000000000000# frozen_string_literal: true on_master = ENV['TRAVIS_BRANCH'] == 'master' && ENV['TRAVIS_PULL_REQUEST'] == 'false' if on_master || ENV['COVERAGE'] require 'simplecov' SimpleCov.add_filter '/spec/' SimpleCov.add_filter '/vendor/bundle/' SimpleCov.command_name 'rspec' SimpleCov.start end rubocop-0.52.1/spec/support/custom_matchers.rb000066400000000000000000000010711322072016200214350ustar00rootroot00000000000000# frozen_string_literal: true RSpec::Matchers.define :exit_with_code do |code| supports_block_expectations actual = nil match do |block| begin block.call rescue SystemExit => e actual = e.status end actual && actual == code end failure_message do "expected block to call exit(#{code}) but exit" + (actual.nil? ? ' not called' : "(#{actual}) was called") end failure_message_when_negated do "expected block not to call exit(#{code})" end description do "expect block to call exit(#{code})" end end rubocop-0.52.1/spec/support/empty_lines_around_body_shared_examples.rb000066400000000000000000000256441322072016200264120ustar00rootroot00000000000000# frozen_string_literal: true shared_examples_for 'empty_lines_around_class_or_module_body' do |type| context 'when EnforcedStyle is empty_lines_special' do let(:cop_config) { { 'EnforcedStyle' => 'empty_lines_special' } } context 'when first child is method' do it "requires blank line at the beginning and ending of #{type} body" do inspect_source(<<-RUBY.strip_indent) #{type} SomeObject def do_something; end end RUBY expect(cop.messages).to eq([]) end context 'source without blank lines' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject def do_something; end end RUBY end it "registers an offense for #{type} not beginning "\ 'and ending with a blank line' do inspect_source(source) expect(cop.messages).to eq([missing_begin, missing_end]) end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} SomeObject def do_something; end end RUBY end end context "when #{type} has a namespace" do it 'requires no empty lines for namespace but '\ "requires blank line at the beginning and ending of #{type} body" do inspect_source(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject def do_something end end end RUBY expect(cop.messages).to eq([]) end context 'source without blank lines' do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject def do_something end end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject def do_something end end end RUBY end end context 'source with blank lines' do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject def do_something end end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject def do_something end end end RUBY end end end end context 'when first child is NOT a method' do it "does not require blank line at the beginning of #{type} body "\ 'but requires blank line before first def definition '\ "and requires blank line at the end of #{type} body" do inspect_source(<<-RUBY.strip_indent) #{type} SomeObject include Something def do_something; end end RUBY expect(cop.messages).to eq([]) end context 'source without blank lines' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject include Something def do_something; end end RUBY end it "registers an offense for #{type} not ending with a blank line" do inspect_source(source) expect(cop.messages).to eq([missing_def, missing_end]) end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} SomeObject include Something def do_something; end end RUBY end end context 'source with blank lines' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject include Something def do_something; end end RUBY end it "registers an offense for #{type} beginning with a blank line" do inspect_source(source) expect(cop.messages).to eq([extra_begin, missing_def]) end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} SomeObject include Something def do_something; end end RUBY end end context 'source with comment before method definition' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject include Something # Comment def do_something; end end RUBY end it "registers an offense for #{type} beginning with a blank line" do inspect_source(source) expect(cop.messages).to eq([extra_begin, missing_def]) end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} SomeObject include Something # Comment def do_something; end end RUBY end end context "when #{type} has a namespace" do it 'requires no empty lines for namespace '\ "and does not require blank line at the beginning of #{type} body "\ "but requires blank line at the end of #{type} body" do inspect_source(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject include Something def do_something end end end RUBY expect(cop.messages).to eq([]) end context 'source without blank lines' do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject include Something def do_something end end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject include Something def do_something end end end RUBY end end context 'source with blank lines' do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject include Something def do_something end end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject include Something def do_something end end end RUBY end end context 'source with constants' do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject URL = %q(http://example.com) def do_something end end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject URL = %q(http://example.com) def do_something end end end RUBY end end end end context 'when namespace has multiple children' do it 'requires empty lines for namespace' do inspect_source(<<-RUBY.strip_indent) #{type} Parent #{type} Mom def do_something end end #{type} Dad end end RUBY expect(cop.messages).to eq([]) end end context "#{type} with only constants" do let(:source) do <<-RUBY.strip_indent #{type} Parent #{type} SomeObject URL = %q(http://example.com) WSDL = %q(http://example.com/wsdl) end end RUBY end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent #{type} SomeObject URL = %q(http://example.com) WSDL = %q(http://example.com/wsdl) end end RUBY end end context "#{type} with constant and child #{type}" do let(:source) do <<-RUBY.strip_indent #{type} Parent URL = %q(http://example.com) #{type} SomeObject def do_something; end end end RUBY end it 'registers offenses' do inspect_source(source) expect(cop.messages).to eq([missing_type, missing_begin, missing_end, missing_end]) end it 'autocorrects the offenses' do new_source = autocorrect_source(source) expect(new_source).to eq(<<-RUBY.strip_indent) #{type} Parent URL = %q(http://example.com) #{type} SomeObject def do_something; end end end RUBY end end context "#{type} with empty body" do context 'with empty line' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject end RUBY end it 'does NOT register offenses' do inspect_source(source) expect(cop.messages).to eq([]) end end context 'without empty line' do let(:source) do <<-RUBY.strip_indent #{type} SomeObject end RUBY end it 'does NOT register offenses' do inspect_source(source) expect(cop.messages).to eq([]) end end end end end rubocop-0.52.1/spec/support/file_helper.rb000066400000000000000000000006671322072016200205250ustar00rootroot00000000000000# frozen_string_literal: true require 'fileutils' module FileHelper def create_file(file_path, content) file_path = File.expand_path(file_path) dir_path = File.dirname(file_path) FileUtils.makedirs dir_path unless File.exist?(dir_path) File.open(file_path, 'w') do |file| case content when String file.puts content when Array file.puts content.join("\n") end end end end rubocop-0.52.1/spec/support/mri_syntax_checker.rb000066400000000000000000000041551322072016200221240ustar00rootroot00000000000000# frozen_string_literal: true require 'open3' # The reincarnation of syntax cop :) module MRISyntaxChecker module_function def offenses_for_source(source, fake_cop_name = 'Syntax', grep_message = nil) if source.is_a?(Array) source_lines = source source = source_lines.join("\n") else source_lines = source.each_line.to_a end source_buffer = Parser::Source::Buffer.new('test', 1) source_buffer.source = source offenses = check_syntax(source).each_line.map do |line| check_line(line, source_lines, source_buffer, fake_cop_name, grep_message) end offenses.compact end def check_line(line, source_lines, source_buffer, fake_cop_name, grep_message) line_number, severity, message = process_line(line) return unless line_number return if grep_message && !message.include?(grep_message) begin_pos = source_lines[0...(line_number - 1)].reduce(0) do |a, e| a + e.length + 1 end RuboCop::Cop::Offense.new(severity, Parser::Source::Range.new(source_buffer, begin_pos, begin_pos + 1), message.capitalize, fake_cop_name) end def check_syntax(source) raise 'Must be running with MRI' unless RUBY_ENGINE == 'ruby' stdin, stderr, thread = nil # It's extremely important to run the syntax check in a # clean environment - otherwise it will be extremely slow. if defined? Bundler Bundler.with_clean_env do stdin, _, stderr, thread = Open3.popen3('ruby', '-cw') end else stdin, _, stderr, thread = Open3.popen3('ruby', '-cw') end stdin.write(source) stdin.close thread.join stderr.read end def process_line(line) match_data = line.match(/.+:(\d+): (warning: )?(.+)/) return nil unless match_data line_number, warning, message = match_data.captures severity = warning ? :warning : :error [line_number.to_i, severity, message] end end rubocop-0.52.1/spec/support/multiline_literal_brace_layout_examples.rb000066400000000000000000000324351322072016200264120ustar00rootroot00000000000000# frozen_string_literal: true shared_examples_for 'multiline literal brace layout' do let(:prefix) { '' } # A prefix before the opening brace. let(:suffix) { '' } # A suffix for the line after the closing brace. let(:open) { nil } # The opening brace. let(:close) { nil } # The closing brace. let(:a) { 'a' } # The first element. let(:b) { 'b' } # The second element. let(:b_comment) { '' } # Comment after the second element. let(:multi_prefix) { '' } # Prefix multi and heredoc with this. let(:multi) { ['{', 'foo: bar', '}'] } # A viable multi-line element. # This heredoc is unsafe to edit around because it ends on the same line as # the node itself. let(:heredoc) { ['<<-EOM', 'baz', 'EOM'] } # This heredoc is safe to edit around because it ends on a line before the # last line of the node. let(:safe_heredoc) { ['{', 'a: <<-EOM', 'baz', 'EOM', '}'] } def make_multi(multi) multi = multi.dup multi[0] = multi_prefix + multi[0] multi end # Construct the source code for the braces. For instance, for an array # the `open` brace would be `[` and the `close` brace would be `]`, so # you could construct the following: # # braces(true, 'a', 'b', 'c', false) # # [ # line break indicated by `true` as the first argument. # a, # b, # c] # no line break indicated by `false` as the last argument. # # This method also supports multi-line arguments. For example: # # braces(true, 'a', ['{', 'foo: bar', '}'], true) # # [ # line break indicated by `true` as the first argument. # a, # { # foo: bar # } # line break indicated by `true` as the last argument. # ] def braces(open_line_break, *args, close_line_break) args = [a, b + b_comment] if args.empty? open + (open_line_break ? "\n" : '') + args.map { |a| a.respond_to?(:join) ? a.join("\n") : a }.join(",\n") + (close_line_break ? "\n" : '') + close end # Construct a piece of source code for brace layout testing. This farms # out most of the work to `#braces` but it also includes a prefix and suffix. def construct(*args) (prefix + braces(*args) + "\n" + suffix).split("\n") end context 'heredoc' do let(:cop_config) { { 'EnforcedStyle' => 'same_line' } } it 'ignores heredocs that could share a last line' do inspect_source(construct(false, a, make_multi(heredoc), true)) expect(cop.offenses.empty?).to be(true) end it 'detects heredoc structures that are safe to add to' do inspect_source(construct(false, a, make_multi(safe_heredoc), true)) expect(cop.offenses.size).to eq(1) end it 'auto-corrects safe heredoc offenses' do new_source = autocorrect_source( construct(false, a, make_multi(safe_heredoc), true) ) expect(new_source) .to eq(construct(false, a, make_multi(safe_heredoc), false).join("\n")) end end context 'symmetrical style' do let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } context 'opening brace on same line as first element' do it 'allows closing brace on same line as last element' do inspect_source(construct(false, false)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on same line as last multiline element' do inspect_source(construct(false, a, make_multi(multi), false)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on different line from last element' do src = construct(false, true) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::SAME_LINE_MESSAGE]) end it 'autocorrects closing brace on different line from last element' do new_source = autocorrect_source(["#{prefix}#{open}#{a}, # a", "#{b} # b", close, suffix]) expect(new_source) .to eq("#{prefix}#{open}#{a}, # a\n#{b}#{close} # b\n#{suffix}") end unless described_class == RuboCop::Cop::Layout::MultilineMethodDefinitionBraceLayout context 'with a chained call on the closing brace' do let(:suffix) { '.any?' } let(:source) { construct(false, true) } context 'and a comment after the last element' do let(:b_comment) { ' # comment b' } it 'detects closing brace on separate line from last element' do inspect_source(source) expect(cop.highlights).to eq([close]) expect(cop.messages) .to eq([described_class::SAME_LINE_MESSAGE]) end it 'does not autocorrect the closing brace' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join($RS)) end end context 'but no comment after the last element' do it 'autocorrects the closing brace' do new_source = autocorrect_source(source) expect(new_source).to eq(["#{prefix}#{open}#{a},", "#{b}#{close}", suffix].join($RS)) end end end end end context 'opening brace on separate line from first element' do it 'allows closing brace on separate line from last element' do inspect_source(construct(true, true)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on separate line from last multiline element' do inspect_source(construct(true, a, make_multi(multi), true)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on same line as last element' do src = construct(true, false) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::NEW_LINE_MESSAGE]) end it 'autocorrects closing brace on same line from last element' do new_source = autocorrect_source(construct(true, false)) expect(new_source).to eq(construct(true, true).join("\n")) end end end context 'new_line style' do let(:cop_config) { { 'EnforcedStyle' => 'new_line' } } context 'opening brace on same line as first element' do it 'allows closing brace on different line from last element' do inspect_source(construct(false, true)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on different line from multi-line element' do inspect_source(construct(false, a, make_multi(multi), true)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on same line as last element' do src = construct(false, false) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_NEW_LINE_MESSAGE]) end it 'detects closing brace on same line as last multiline element' do src = construct(false, a, make_multi(multi), false) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_NEW_LINE_MESSAGE]) end it 'autocorrects closing brace on same line as last element' do new_source = autocorrect_source(["#{prefix}#{open}#{a}, # a", "#{b}#{close} # b", suffix]) expect(new_source) .to eq("#{prefix}#{open}#{a}, # a\n#{b}\n#{close} # b\n#{suffix}") end end context 'opening brace on separate line from first element' do it 'allows closing brace on separate line from last element' do inspect_source(construct(true, true)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on separate line from last multiline element' do inspect_source(construct(true, a, make_multi(multi), true)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on same line as last element' do src = construct(true, false) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_NEW_LINE_MESSAGE]) end it 'autocorrects closing brace on same line from last element' do new_source = autocorrect_source(construct(true, false)) expect(new_source).to eq(construct(true, true).join("\n")) end end end context 'same_line style' do let(:cop_config) { { 'EnforcedStyle' => 'same_line' } } context 'opening brace on same line as first element' do it 'allows closing brace on same line from last element' do inspect_source(construct(false, false)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on same line as multi-line element' do inspect_source(construct(false, a, make_multi(multi), false)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on different line from last element' do src = construct(false, true) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_SAME_LINE_MESSAGE]) end it 'detects closing brace on different line from multiline element' do src = construct(false, a, make_multi(multi), true) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_SAME_LINE_MESSAGE]) end it 'autocorrects closing brace on different line as last element' do new_source = autocorrect_source(["#{prefix}#{open}#{a}, # a", "#{b} # b", close, suffix]) expect(new_source) .to eq("#{prefix}#{open}#{a}, # a\n#{b}#{close} # b\n#{suffix}") end unless described_class == RuboCop::Cop::Layout::MultilineMethodDefinitionBraceLayout context 'with a chained call on the closing brace' do let(:suffix) { '.any?' } let(:source) { construct(false, true) } context 'and a comment after the last element' do let(:b_comment) { ' # comment b' } it 'detects closing brace on separate line from last element' do inspect_source(source) expect(cop.highlights).to eq([close]) expect(cop.messages) .to eq([described_class::ALWAYS_SAME_LINE_MESSAGE]) end it 'does not autocorrect the closing brace' do new_source = autocorrect_source(source) expect(new_source).to eq(source.join($RS)) end end context 'but no comment after the last element' do it 'autocorrects the closing brace' do new_source = autocorrect_source(source) expect(new_source).to eq(["#{prefix}#{open}#{a},", "#{b}#{close}", suffix].join($RS)) end end end end end context 'opening brace on separate line from first element' do it 'allows closing brace on same line as last element' do inspect_source(construct(true, false)) expect(cop.offenses.empty?).to be(true) end it 'allows closing brace on same line as last multiline element' do inspect_source(construct(true, a, make_multi(multi), false)) expect(cop.offenses.empty?).to be(true) end it 'detects closing brace on different line from last element' do src = construct(true, true) inspect_source(src) expect(cop.offenses.size).to eq(1) expect(cop.offenses.first.line) .to eq(src.length - (suffix.empty? ? 0 : 1)) expect(cop.highlights).to eq([close]) expect(cop.messages).to eq([described_class::ALWAYS_SAME_LINE_MESSAGE]) end it 'autocorrects closing brace on different line from last element' do new_source = autocorrect_source(construct(true, true)) expect(new_source).to eq(construct(true, false).join("\n")) end end end end rubocop-0.52.1/spec/support/multiline_literal_brace_layout_trailing_comma_examples.rb000066400000000000000000000032721322072016200314540ustar00rootroot00000000000000# frozen_string_literal: true shared_examples_for 'multiline literal brace layout trailing comma' do let(:prefix) { '' } # A prefix before the opening brace. let(:suffix) { '' } # A suffix for the line after the closing brace. let(:open) { nil } # The opening brace. let(:close) { nil } # The closing brace. let(:a) { 'a' } # The first element. let(:b) { 'b' } # The second element. context 'symmetrical style' do let(:cop_config) { { 'EnforcedStyle' => 'symmetrical' } } context 'opening brace on same line as first element' do context 'last element has a trailing comma' do it 'autocorrects closing brace on different line from last element' do new_source = autocorrect_source(["#{prefix}#{open}#{a}, # a", "#{b}, # b", close, suffix]) expect(new_source) .to eq("#{prefix}#{open}#{a}, # a\n#{b},#{close} # b\n#{suffix}") end end end end context 'same_line style' do let(:cop_config) { { 'EnforcedStyle' => 'same_line' } } context 'opening brace on same line as first element' do context 'last element has a trailing comma' do it 'autocorrects closing brace on different line as last element' do new_source = autocorrect_source(["#{prefix}#{open}#{a}, # a", "#{b}, # b", close, suffix]) expect(new_source) .to eq("#{prefix}#{open}#{a}, # a\n#{b},#{close} # b\n#{suffix}") end end end end end rubocop-0.52.1/spec/support/statement_modifier_helper.rb000066400000000000000000000025441322072016200234640ustar00rootroot00000000000000# frozen_string_literal: true module StatementModifierHelper def check_empty(cop, keyword) inspect_source(<<-RUBY.strip_indent) #{keyword} cond end RUBY expect(cop.offenses.empty?).to be(true) end def check_really_short(cop, keyword) inspect_source(<<-RUBY.strip_indent) #{keyword} a b end RUBY expect(cop.messages).to eq( ["Favor modifier `#{keyword}` usage when having a single-line body."] ) expect(cop.offenses.map { |o| o.location.source }).to eq([keyword]) end def autocorrect_really_short(keyword) corrected = autocorrect_source(<<-RUBY.strip_indent) #{keyword} a b end RUBY expect(corrected).to eq "b #{keyword} a\n" end def check_too_long(cop, keyword) # This statement is one character too long to fit. condition = 'a' * (40 - keyword.length) body = 'b' * 37 expect(" #{body} #{keyword} #{condition}".length).to eq(81) inspect_source(<<-RUBY.strip_margin('|')) | #{keyword} #{condition} | #{body} | end RUBY expect(cop.offenses.empty?).to be(true) end def check_short_multiline(cop, keyword) inspect_source(<<-RUBY.strip_indent) #{keyword} ENV['COVERAGE'] require 'simplecov' SimpleCov.start end RUBY expect(cop.messages.empty?).to be(true) end end rubocop-0.52.1/tasks/000077500000000000000000000000001322072016200143705ustar00rootroot00000000000000rubocop-0.52.1/tasks/cops_documentation.rake000066400000000000000000000147201322072016200211350ustar00rootroot00000000000000# frozen_string_literal: true require 'yard' require 'rubocop' YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task| task.files = ['lib/rubocop/cop/*/*.rb'] task.options = ['--no-output'] end desc 'Generate docs of all cops departments' task generate_cops_documentation: :yard_for_generate_documentation do def cops_of_department(cops, department) cops.with_department(department).sort! end def cops_body(config, cop, description, examples_objects, pars) content = h2(cop.cop_name) content << properties(config, cop) content << "#{description}\n" content << examples(examples_objects) if examples_objects.count > 0 content << configurations(pars) content << references(config, cop) content end def examples(examples_object) examples_object.each_with_object(h3('Examples').dup) do |example, content| content << h4(example.name) unless example.name == '' content << code_example(example) end end def properties(config, cop) header = ['Enabled by default', 'Supports autocorrection'] enabled_by_default = config.for_cop(cop).fetch('Enabled') content = [[ enabled_by_default ? 'Enabled' : 'Disabled', cop.new.support_autocorrect? ? 'Yes' : 'No' ]] to_table(header, content) + "\n" end def h2(title) content = "\n".dup content << "## #{title}\n" content << "\n" content end def h3(title) content = "\n".dup content << "### #{title}\n" content << "\n" content end def h4(title) content = "#### #{title}\n".dup content << "\n" content end def code_example(ruby_code) content = "```ruby\n".dup content << ruby_code.text.gsub('@good', '# good') .gsub('@bad', '# bad').strip content << "\n```\n" content end def configurations(pars) return '' if pars.empty? header = ['Name', 'Default value', 'Configurable values'] configs = pars.each_key.reject { |key| key.start_with?('Supported') } content = configs.map do |name| configurable = configurable_values(pars, name) default = format_table_value(pars[name]) [name, default, configurable] end h3('Configurable attributes') + to_table(header, content) end # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength def configurable_values(pars, name) case name when /^Enforced/ supported_style_name = RuboCop::Cop::Util.to_supported_styles(name) format_table_value(pars[supported_style_name]) when 'IndentationWidth' 'Integer' else case pars[name] when String 'String' when Integer 'Integer' when Float 'Float' when true, false 'Boolean' when Array 'Array' else '' end end end # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength def to_table(header, content) table = [ header.join(' | '), Array.new(header.size, '---').join(' | ') ] table.concat(content.map { |c| c.join(' | ') }) table.join("\n") + "\n" end def format_table_value(v) value = case v when Array if v.empty? '`[]`' else v.map { |config| format_table_value(config) }.join(', ') end else "`#{v.nil? ? '' : v}`" end value.gsub("#{Dir.pwd}/", '').rstrip end def references(config, cop) cop_config = config.for_cop(cop) urls = RuboCop::Cop::MessageAnnotator.new(config, cop_config, {}).urls return '' if urls.empty? content = h3('References') content << urls.map { |url| "* [#{url}](#{url})" }.join("\n") content << "\n" content end def print_cops_of_department(cops, department, config) selected_cops = cops_of_department(cops, department) content = "# #{department}\n".dup selected_cops.each do |cop| content << print_cop_with_doc(cop, config) end file_name = "#{Dir.pwd}/manual/cops_#{department.downcase}.md" File.open(file_name, 'w') do |file| puts "* generated #{file_name}" file.write(content.strip + "\n") end end def print_cop_with_doc(cop, config) t = config.for_cop(cop) non_display_keys = %w[Description Enabled StyleGuide Reference] pars = t.reject { |k| non_display_keys.include? k } description = 'No documentation' examples_object = [] YARD::Registry.all(:class).detect do |code_object| next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge description = code_object.docstring unless code_object.docstring.blank? examples_object = code_object.tags('example') end cops_body(config, cop, description, examples_object, pars) end def table_of_content_for_department(cops, department) type_title = department[0].upcase + department[1..-1] filename = "cops_#{department.downcase}.md" content = "#### Department [#{type_title}](#{filename})\n\n".dup cops_of_department(cops, department.to_sym).each do |cop| anchor = cop.cop_name.sub('/', '').downcase content << "* [#{cop.cop_name}](#{filename}##{anchor})\n" end content end def print_table_of_contents(cops) path = "#{Dir.pwd}/manual/cops.md" original = File.read(path) content = "\n".dup content << table_contents(cops) content << "\n" content = original.sub( /.+/m, content ) File.write(path, content) end def table_contents(cops) cops .departments .map(&:to_s) .sort .map { |department| table_of_content_for_department(cops, department) } .join("\n") end def assert_manual_synchronized # Do not print diff and yield whether exit code was zero sh('git diff --quiet manual') do |outcome, _| return if outcome # Output diff before raising error sh('git diff manual') warn 'The manual directory is out of sync. ' \ 'Run `rake generate_cops_documentation` and commit the results.' exit! end end def main cops = RuboCop::Cop::Cop.registry config = RuboCop::ConfigLoader.default_configuration config['Rails']['Enabled'] = true YARD::Registry.load! cops.departments.sort!.each do |department| print_cops_of_department(cops, department, config) end print_table_of_contents(cops) assert_manual_synchronized if ENV['CI'] == 'true' ensure RuboCop::ConfigLoader.default_configuration = nil end main end rubocop-0.52.1/tasks/cut_release.rake000066400000000000000000000043431322072016200175330ustar00rootroot00000000000000# frozen_string_literal: true require 'bump' namespace :cut_release do %w[major minor patch pre].each do |release_type| desc "Cut a new #{release_type} release, create release notes " \ 'and update documents.' task release_type do run(release_type) end end def update_readme(old_version, new_version) readme = File.read('README.md') File.open('README.md', 'w') do |f| f << readme.sub( "gem 'rubocop', '~> #{old_version}', require: false", "gem 'rubocop', '~> #{new_version}', require: false" ) end end def update_manual(old_version, new_version) manual = File.read('manual/installation.md') File.open('manual/installation.md', 'w') do |f| f << manual.sub( "gem 'rubocop', '~> #{old_version}', require: false", "gem 'rubocop', '~> #{new_version}', require: false" ) end end def add_header_to_changelog(version) changelog = File.read('CHANGELOG.md') head, tail = changelog.split("## master (unreleased)\n\n", 2) File.open('CHANGELOG.md', 'w') do |f| f << head f << "## master (unreleased)\n\n" f << "## #{version} (#{Time.now.strftime('%F')})\n\n" f << tail end end def create_release_notes(version) release_notes = new_version_changes.strip contributor_links = user_links(release_notes) File.open("relnotes/v#{version}.md", 'w') do |file| file << release_notes file << "\n\n" file << contributor_links end end def new_version_changes changelog = File.read('CHANGELOG.md') _, _, new_changes, _older_changes = changelog.split(/^## .*$/, 4) new_changes end def user_links(text) names = text.scan(/\[@(\S+)\]\[\]/).map(&:first).uniq names.map { |name| "[@#{name}]: https://github.com/#{name}" } .join("\n") end def run(release_type) old_version = Bump::Bump.current Bump::Bump.run(release_type, commit: false, bundle: false, tag: false) new_version = Bump::Bump.current update_readme(old_version, new_version) update_manual(old_version, new_version) add_header_to_changelog(new_version) create_release_notes(new_version) puts "Changed version from #{old_version} to #{new_version}." end end rubocop-0.52.1/tasks/new_cop.rake000066400000000000000000000006371322072016200166740ustar00rootroot00000000000000# frozen_string_literal: true require 'rubocop' desc 'Generate a new cop template' task :new_cop, [:cop] do |_task, args| cop_name = args.fetch(:cop) do warn 'usage: bundle exec rake new_cop[Department/Name]' exit! end generator = RuboCop::Cop::Generator.new(cop_name) generator.write_source generator.write_spec generator.inject_require generator.inject_config puts generator.todo end