Skip to content

Commit

Permalink
[Fix rubocop#7299] Implement Lint/RaiseException cop
Browse files Browse the repository at this point in the history
  • Loading branch information
denys281 committed Oct 28, 2019
1 parent bb227db commit de5e746
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -48,6 +48,7 @@
* [#7317](https://github.com/rubocop-hq/rubocop/pull/7317): Add new formatter `pacman`. ([@crojasaragonez][])
* [#6075](https://github.com/rubocop-hq/rubocop/issues/6075): Support `IgnoredPatterns` option for `Naming/MethodName` cop. ([@koic][])
* [#7335](https://github.com/rubocop-hq/rubocop/pull/7335): Add todo as an alias to disable. `--disable-uncorrectable` will now disable cops using `rubocop:todo` instead of `rubocop:disable`. ([@desheikh][])
* [#7299](https://github.com/rubocop-hq/rubocop/issues/7299): Add new `Lint/RaiseException` cop. ([@denys281][])

### Bug fixes

Expand Down Expand Up @@ -4248,3 +4249,4 @@
[@jdkaplan]: https://github.com/jdkaplan
[@cstyles]: https://github.com/cstyles
[@avmnu-sng]: https://github.com/avmnu-sng
[@denys281]: https://github.com/denys281
6 changes: 6 additions & 0 deletions config/default.yml
Expand Up @@ -1505,6 +1505,12 @@ Lint/PercentSymbolArray:
Enabled: true
VersionAdded: '0.41'

Lint/RaiseException:
Description: Checks for `raise` or `fail` statements which are raising `Exception` class.
StyleGuide: '#raise-exception'
Enabled: true
VersionAdded: '0.75'

Lint/RandOne:
Description: >-
Checks for `rand(1)` calls. Such calls always return `0`
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Expand Up @@ -321,6 +321,7 @@
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/raise_exception'
require_relative 'rubocop/cop/lint/rand_one'
require_relative 'rubocop/cop/lint/redundant_cop_disable_directive'
require_relative 'rubocop/cop/lint/redundant_cop_enable_directive'
Expand Down
39 changes: 39 additions & 0 deletions lib/rubocop/cop/lint/raise_exception.rb
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Lint
# This cop checks for `raise` or `fail` statements which are
# raising `Exception` class.
#
# @example
# # bad
# raise Exception, 'Error message here'
#
# # good
# raise StandardError, 'Error message here'
class RaiseException < Cop
MSG = 'Use `StandardError` over `Exception`.'

def_node_matcher :exception?, <<~PATTERN
(send nil? ${:raise :fail} (const _ :Exception) ... )
PATTERN

def_node_matcher :exception_new_with_message?, <<~PATTERN
(send nil? ${:raise :fail}
(send (const _ :Exception) :new ... ))
PATTERN

def on_send(node)
add_offense(node) if raise_exception?(node)
end

private

def raise_exception?(node)
exception?(node) || exception_new_with_message?(node)
end
end
end
end
end
1 change: 1 addition & 0 deletions manual/cops.md
Expand Up @@ -220,6 +220,7 @@ In the following section you find all available cops:
* [Lint/ParenthesesAsGroupedExpression](cops_lint.md#lintparenthesesasgroupedexpression)
* [Lint/PercentStringArray](cops_lint.md#lintpercentstringarray)
* [Lint/PercentSymbolArray](cops_lint.md#lintpercentsymbolarray)
* [Lint/RaiseException](cops_lint.md#lintraiseexception)
* [Lint/RandOne](cops_lint.md#lintrandone)
* [Lint/RedundantCopDisableDirective](cops_lint.md#lintredundantcopdisabledirective)
* [Lint/RedundantCopEnableDirective](cops_lint.md#lintredundantcopenabledirective)
Expand Down
23 changes: 23 additions & 0 deletions manual/cops_lint.md
Expand Up @@ -1570,6 +1570,29 @@ rather than meant to be part of the resulting symbols.
%i(foo bar)
```

## Lint/RaiseException

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Enabled | Yes | No | 0.75 | -

This cop checks for `raise` or `fail` statements which are
raising `Exception` class.

### Examples

```ruby
# bad
raise Exception, 'Error message here'

# good
raise StandardError, 'Error message here'
```

### References

* [https://rubystyle.guide#raise-exception](https://rubystyle.guide#raise-exception)

## Lint/RandOne

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
83 changes: 83 additions & 0 deletions spec/rubocop/cop/lint/raise_exception_spec.rb
@@ -0,0 +1,83 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Lint::RaiseException do
subject(:cop) { described_class.new }

it 'registers an offense for `raise` with `::Exception`' do
expect_offense(<<~RUBY)
raise ::Exception
^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `::Exception.new`' do
expect_offense(<<~RUBY)
raise ::Exception.new 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `::Exception` and message' do
expect_offense(<<~RUBY)
raise ::Exception, 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `Exception`' do
expect_offense(<<~RUBY)
raise Exception
^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `Exception` and message' do
expect_offense(<<~RUBY)
raise Exception, 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `Exception.new` and message' do
expect_offense(<<~RUBY)
raise Exception.new 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `raise` with `Exception.new(args*)` ' do
expect_offense(<<~RUBY)
raise Exception.new('arg1', 'arg2')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `fail` with `Exception`' do
expect_offense(<<~RUBY)
fail Exception
^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `fail` with `Exception` and message' do
expect_offense(<<~RUBY)
fail Exception, 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'registers an offense for `fail` with `Exception.new` and message' do
expect_offense(<<~RUBY)
fail Exception.new 'Error with exception'
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use `StandardError` over `Exception`.
RUBY
end

it 'does not register an offense for `raise` without arguments' do
expect_no_offenses('raise')
end

it 'does not register an offense for `fail` without arguments' do
expect_no_offenses('fail')
end
end

0 comments on commit de5e746

Please sign in to comment.