rubocop-0.52.1/ 0000775 0000000 0000000 00000000000 13220720162 0013243 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/.editorconfig 0000664 0000000 0000000 00000000274 13220720162 0015723 0 ustar 00root root 0000000 0000000 root = 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/.gitattributes 0000664 0000000 0000000 00000000031 13220720162 0016130 0 ustar 00root root 0000000 0000000 CHANGELOG.md merge=union
rubocop-0.52.1/.github/ 0000775 0000000 0000000 00000000000 13220720162 0014603 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/.github/ISSUE_TEMPLATE.md 0000664 0000000 0000000 00000001675 13220720162 0017321 0 ustar 00root root 0000000 0000000 *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.md 0000664 0000000 0000000 00000001660 13220720162 0020407 0 ustar 00root root 0000000 0000000 **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/.gitignore 0000664 0000000 0000000 00000001612 13220720162 0015233 0 ustar 00root root 0000000 0000000 # 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/.rspec 0000664 0000000 0000000 00000000036 13220720162 0014357 0 ustar 00root root 0000000 0000000 --color
--require spec_helper
rubocop-0.52.1/.rubocop.yml 0000664 0000000 0000000 00000003220 13220720162 0015512 0 ustar 00root root 0000000 0000000 # 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.yml 0000664 0000000 0000000 00000006133 13220720162 0016545 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002022 13220720162 0015152 0 ustar 00root root 0000000 0000000 # 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.yml 0000664 0000000 0000000 00000001244 13220720162 0015355 0 ustar 00root root 0000000 0000000 sudo: 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/.yardopts 0000664 0000000 0000000 00000000045 13220720162 0015110 0 ustar 00root root 0000000 0000000 --markup markdown
--hide-void-return
rubocop-0.52.1/CHANGELOG.md 0000664 0000000 0000000 00001115534 13220720162 0015066 0 ustar 00root root 0000000 0000000 # 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.md 0000664 0000000 0000000 00000006415 13220720162 0015502 0 ustar 00root root 0000000 0000000 # 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/Gemfile 0000664 0000000 0000000 00000001026 13220720162 0014535 0 ustar 00root root 0000000 0000000 # 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.txt 0000664 0000000 0000000 00000002046 13220720162 0015070 0 ustar 00root root 0000000 0000000 Copyright (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.md 0000664 0000000 0000000 00000035425 13220720162 0014533 0 ustar 00root root 0000000 0000000 [](http://badge.fury.io/rb/rubocop)
[](https://gemnasium.com/bbatsov/rubocop)
[](https://travis-ci.org/bbatsov/rubocop)
[](https://ci.appveyor.com/project/bbatsov/rubocop)
[](https://codeclimate.com/github/bbatsov/rubocop)
[](https://codeclimate.com/github/bbatsov/rubocop)
[](http://inch-ci.org/github/bbatsov/rubocop)
[](https://www.patreon.com/bbatsov)
[](https://liberapay.com/bbatsov/donate)
[](#open-collective-backers)
[](#open-collective-sponsors)
> 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.
[](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/Rakefile 0000664 0000000 0000000 00000010126 13220720162 0014710 0 ustar 00root root 0000000 0000000 # 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.yml 0000664 0000000 0000000 00000000600 13220720162 0015627 0 ustar 00root root 0000000 0000000 ---
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/ 0000775 0000000 0000000 00000000000 13220720162 0014545 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/assets/output.html.erb 0000664 0000000 0000000 00000015702 13220720162 0017547 0 ustar 00root root 0000000 0000000
RuboCop Inspection Report
<%# TODO: Clean up the messy markup and style definitions. %>
rubocop-0.52.1/bin/ 0000775 0000000 0000000 00000000000 13220720162 0014013 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/bin/rubocop 0000775 0000000 0000000 00000000441 13220720162 0015411 0 ustar 00root root 0000000 0000000 #!/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/ 0000775 0000000 0000000 00000000000 13220720162 0014510 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/config/default.yml 0000664 0000000 0000000 00000135046 13220720162 0016670 0 ustar 00root root 0000000 0000000 # 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.yml 0000664 0000000 0000000 00000007756 13220720162 0017021 0 ustar 00root root 0000000 0000000 # 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.yml 0000664 0000000 0000000 00000165037 13220720162 0016641 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0014011 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop.rb 0000664 0000000 0000000 00000074775 13220720162 0016033 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0015462 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/ast/ 0000775 0000000 0000000 00000000000 13220720162 0016251 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/ast/builder.rb 0000664 0000000 0000000 00000004405 13220720162 0020227 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000050455 13220720162 0017534 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0017176 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/ast/node/and_node.rb 0000664 0000000 0000000 00000002227 13220720162 0021275 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001276 13220720162 0021472 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003317 13220720162 0021652 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000006653 13220720162 0021634 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003506 13220720162 0021447 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004107 13220720162 0021270 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001321 13220720162 0022026 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003220 13220720162 0021313 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000006270 13220720162 0021460 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000010750 13220720162 0021131 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002261 13220720162 0023420 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020322 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/ast/node/mixin/basic_literal_node.rb 0000664 0000000 0000000 00000000534 13220720162 0024453 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001067 13220720162 0025057 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000522 13220720162 0024006 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002647 13220720162 0024170 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000007150 13220720162 0024313 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000012735 13220720162 0025023 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005576 13220720162 0026551 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000656 13220720162 0023461 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003540 13220720162 0024512 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001614 13220720162 0025531 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002212 13220720162 0021145 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003776 13220720162 0021500 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001652 13220720162 0022026 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001326 13220720162 0022201 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002546 13220720162 0021470 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000612 13220720162 0021337 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001221 13220720162 0021662 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001077 13220720162 0022042 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002353 13220720162 0021666 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003343 13220720162 0021474 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002353 13220720162 0021643 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001164 13220720162 0021640 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000600 13220720162 0017551 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000012070 13220720162 0020601 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003263 13220720162 0020213 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000020412 13220720162 0016555 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000010554 13220720162 0021003 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000044356 13220720162 0017270 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000016400 13220720162 0020603 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000011611 13220720162 0022523 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003114 13220720162 0020467 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0016243 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/autocorrect_logic.rb 0000664 0000000 0000000 00000001204 13220720162 0022274 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003356 13220720162 0017641 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0017676 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/bundler/duplicated_gem.rb 0000664 0000000 0000000 00000003603 13220720162 0023173 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004216 13220720162 0025344 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003544 13220720162 0022670 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000007357 13220720162 0021313 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000014056 13220720162 0017357 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000010627 13220720162 0020600 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020430 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/correctors/alignment_corrector.rb 0000664 0000000 0000000 00000007377 13220720162 0025033 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001317 13220720162 0025027 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001176 13220720162 0025211 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004023 13220720162 0027710 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002503 13220720162 0025313 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001367 13220720162 0025367 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001255 13220720162 0025413 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002022 13220720162 0024126 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001076 13220720162 0026065 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001477 13220720162 0025204 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001371 13220720162 0017670 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0017666 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/gemspec/duplicated_assignment.rb 0000664 0000000 0000000 00000006206 13220720162 0024565 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000006034 13220720162 0024350 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005160 13220720162 0024643 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000012654 13220720162 0020566 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020231 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/generator/require_file_injector.rb 0000664 0000000 0000000 00000004546 13220720162 0025137 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001711 13220720162 0021224 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000610 13220720162 0022074 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0021552 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/internal_affairs/node_destructuring.rb 0000664 0000000 0000000 00000002275 13220720162 0026014 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002313 13220720162 0026104 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003100 13220720162 0027152 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003062 13220720162 0027656 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004005 13220720162 0027470 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002624 13220720162 0027361 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0017560 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/lib/rubocop/cop/layout/access_modifier_indentation.rb 0000664 0000000 0000000 00000005466 13220720162 0025633 0 ustar 00root root 0000000 0000000 # 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 = '%
rubocop-0.52.1/spec/fixtures/html_formatter/project/ 0000775 0000000 0000000 00000000000 13220720162 0022543 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/fixtures/html_formatter/project/app/ 0000775 0000000 0000000 00000000000 13220720162 0023323 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/fixtures/html_formatter/project/app/controllers/ 0000775 0000000 0000000 00000000000 13220720162 0025671 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/fixtures/html_formatter/project/app/controllers/application_controller.rb 0000664 0000000 0000000 00000000402 13220720162 0032760 0 ustar 00root root 0000000 0000000 class 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.rb 0000664 0000000 0000000 00000003354 13220720162 0031603 0 ustar 00root root 0000000 0000000 class 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/ 0000775 0000000 0000000 00000000000 13220720162 0024606 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/fixtures/html_formatter/project/app/models/book.rb 0000664 0000000 0000000 00000000240 13220720162 0026061 0 ustar 00root root 0000000 0000000 class 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.rb 0000664 0000000 0000000 00000001454 13220720162 0021770 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000012667 13220720162 0017216 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0015646 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/ast/ 0000775 0000000 0000000 00000000000 13220720162 0016435 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/ast/and_node_spec.rb 0000664 0000000 0000000 00000005745 13220720162 0021556 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003533 13220720162 0021741 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005002 13220720162 0022114 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000012073 13220720162 0022076 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004456 13220720162 0021725 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000031105 13220720162 0021537 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000710 13220720162 0022300 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002707 13220720162 0021575 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000013320 13220720162 0021723 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000023007 13220720162 0021401 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000021474 13220720162 0023700 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000023332 13220720162 0020724 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005672 13220720162 0021433 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000044031 13220720162 0021736 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004463 13220720162 0022302 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001032 13220720162 0022444 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000054641 13220720162 0021744 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002326 13220720162 0021614 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000023337 13220720162 0022147 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000000653 13220720162 0022312 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002051 13220720162 0022132 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005252 13220720162 0021746 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002051 13220720162 0022107 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000020376 13220720162 0022117 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0016415 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cli/cli_auto_gen_config_spec.rb 0000664 0000000 0000000 00000065044 13220720162 0023742 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000113005 13220720162 0023135 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000130145 13220720162 0022302 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000156477 13220720162 0020000 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000013703 13220720162 0022200 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000065536 13220720162 0022017 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000053313 13220720162 0020457 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000004521 13220720162 0021670 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0016427 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/badge_spec.rb 0000664 0000000 0000000 00000002663 13220720162 0021037 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020062 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/bundler/duplicated_gem_spec.rb 0000664 0000000 0000000 00000004160 13220720162 0024370 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003251 13220720162 0026540 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000014674 13220720162 0024074 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005614 13220720162 0022503 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000016764 13220720162 0020565 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003314 13220720162 0021771 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001327 13220720162 0021067 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020052 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/gemspec/duplicated_assignment_spec.rb 0000664 0000000 0000000 00000004015 13220720162 0025757 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000013617 13220720162 0025553 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005632 13220720162 0026045 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0020415 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/generator/require_file_injector_spec.rb 0000664 0000000 0000000 00000013552 13220720162 0026332 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000015532 13220720162 0021762 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0021736 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/internal_affairs/node_destructuring_spec.rb 0000664 0000000 0000000 00000002133 13220720162 0027203 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000001255 13220720162 0027306 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000003742 13220720162 0030364 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000005077 13220720162 0031064 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000006147 13220720162 0030677 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000002065 13220720162 0030556 0 ustar 00root root 0000000 0000000 # 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/ 0000775 0000000 0000000 00000000000 13220720162 0017744 5 ustar 00root root 0000000 0000000 rubocop-0.52.1/spec/rubocop/cop/layout/access_modifier_indentation_spec.rb 0000664 0000000 0000000 00000024573 13220720162 0027031 0 ustar 00root root 0000000 0000000 # 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.rb 0000664 0000000 0000000 00000006161 13220720162 0023577 0 ustar 00root root 0000000 0000000 # 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 => <