ducalis 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ducalis (0.5.5)
4
+ ducalis (0.5.6)
5
5
  git (~> 1.3, >= 1.3.0)
6
6
  policial (= 0.0.4)
7
7
  regexp-examples (~> 1.3, >= 1.3.2)
@@ -38,8 +38,8 @@ GEM
38
38
  multipart-post (2.0.0)
39
39
  octokit (4.7.0)
40
40
  sawyer (~> 0.8.0, >= 0.5.3)
41
- parser (2.4.0.0)
42
- ast (~> 2.2)
41
+ parser (2.4.0.2)
42
+ ast (~> 2.3)
43
43
  policial (0.0.4)
44
44
  coffeelint (~> 1.14)
45
45
  eslintrb (~> 2.0)
@@ -49,11 +49,11 @@ GEM
49
49
  pry (0.11.2)
50
50
  coderay (~> 1.1.0)
51
51
  method_source (~> 0.9.0)
52
- public_suffix (3.0.0)
52
+ public_suffix (3.0.1)
53
53
  rainbow (2.2.2)
54
54
  rake
55
55
  rake (12.1.0)
56
- regexp-examples (1.4.0)
56
+ regexp-examples (1.4.1)
57
57
  rspec (3.7.0)
58
58
  rspec-core (~> 3.7.0)
59
59
  rspec-expectations (~> 3.7.0)
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/ducalis.svg)](https://badge.fury.io/rb/ducalis)
4
4
  [![Build Status](https://travis-ci.org/ignat-z/ducalis.svg?branch=master)](https://travis-ci.org/ignat-z/ducalis)
5
- [![Code Climate](https://codeclimate.com/github/ignat-z/ducalis/badges/gpa.svg)](https://codeclimate.com/github/ignat-z/ducalis)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/d03d4e567e8728d2c58b/maintainability)](https://codeclimate.com/github/ignat-z/ducalis/maintainability)
6
6
 
7
7
  __Ducalis__ is RuboCop-based static code analyzer for enterprise Rails applications.
8
8
  As __Ducalis__ isn't style checker and could sometimes be false-positive it's not
@@ -58,3 +58,15 @@ rack application. All related files are located in the `client/` directory.
58
58
  In CLI modes you can provide yours `.ducalis.yml` file based on
59
59
  [default](https://github.com/ignat-z/ducalis/blob/master/config/.ducalis.yml) by
60
60
  `-c` flag or simply putting it in your project directory.
61
+
62
+ ## Contribution
63
+
64
+ To pass your code through the all checks you simply need to run:
65
+
66
+ ```
67
+ bundle exec rake
68
+ ```
69
+
70
+ Please, do not edit
71
+ [DOCUMENTATION.md](<https://github.com/ignat-z/ducalis/blob/master/DOCUMENTATION.md>),
72
+ this file is generating by `bundle exec rake documentation` command.
@@ -4,11 +4,18 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class CallbacksActiverecord < RuboCop::Cop::Cop
7
- OFFENSE = "Please, avoid using of callbacks for models. It's better to "\
8
- 'keep models small ("dumb") and instead use "builder" classes'\
9
- '/services: to construct new objects. You can read more [here]'\
10
- '(https://medium.com/planet-arkency/a61fd75ab2d3).'
11
- MODELS_CLASS_NAMES = ['ApplicationRecord', 'ActiveRecord::Base'].freeze
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Please, avoid using of callbacks for models. It's better to
9
+ | keep models small ("dumb") and instead use "builder" classes
10
+ | / services: to construct new objects. You can read more
11
+ | [here](https://medium.com/planet-arkency/a61fd75ab2d3).
12
+ MESSAGE
13
+
14
+ MODELS_CLASS_NAMES = [
15
+ 'ApplicationRecord',
16
+ 'ActiveRecord::Base'
17
+ ].freeze
18
+
12
19
  METHODS_BLACK_LIST = %i(
13
20
  after_commit
14
21
  after_create
@@ -4,14 +4,15 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class CaseMapping < RuboCop::Cop::Cop
7
- OFFENSE = %(
8
- Try to avoid `case when` statements. You can replace it with a sequence of
9
- `if... elsif... elsif... else`. For cases where you need to choose from a
10
- large number of possibilities, you can create a dictionary mapping case values
11
- to functions to call by `call`. It's nice to have prefix for the method
12
- names, i.e.: `visit_`.
13
-
14
- <details>
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Try to avoid `case when` statements. You can replace it with a sequence
9
+ | of `if... elsif... elsif... else`. For cases where you need to choose
10
+ | from a large number of possibilities, you can create a dictionary
11
+ | mapping case values to functions to call by `call`. It's nice to have
12
+ | prefix for the method names, i.e.: `visit_`.
13
+ MESSAGE
14
+
15
+ DETAILS = %(
15
16
  Usually `case when` statements are using for the next reasons:
16
17
 
17
18
  I. Mapping between different values.
@@ -3,14 +3,14 @@
3
3
  require 'rubocop'
4
4
 
5
5
  module Ducalis
6
- class ControllersExcept < ::RuboCop::Cop::Cop
7
- include RuboCop::Cop::DefNode
6
+ class ControllersExcept < RuboCop::Cop::Cop
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Prefer to use `:only` over `:except` in controllers because it's more
9
+ | explicit and will be easier to maintain for new developers.
10
+ MESSAGE
11
+
8
12
  FILTERS = %i(before_filter after_filter around_filter
9
13
  before_action after_action around_action).freeze
10
- OFFENSE = %(
11
- Prefer to use `:only` over `:except` in controllers because it's more explicit \
12
- and will be easier to maintain for new developers.
13
- ).strip
14
14
 
15
15
  def on_class(node)
16
16
  _classdef_node, superclass, _body = *node
@@ -4,11 +4,10 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class KeywordDefaults < RuboCop::Cop::Cop
7
- include RuboCop::Cop::DefNode
8
- OFFENSE = %(
9
- Prefer to use keyword arguments for defaults. \
10
- It increases readability and reduces ambiguities.
11
- ).strip
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Prefer to use keyword arguments for defaults. It increases readability
9
+ | and reduces ambiguities.
10
+ MESSAGE
12
11
 
13
12
  def on_def(node)
14
13
  args = node.type == :defs ? node.to_a[2] : node.to_a[1]
@@ -5,11 +5,10 @@ require 'rubocop'
5
5
  module Ducalis
6
6
  class ModuleLikeClass < RuboCop::Cop::Cop
7
7
  include RuboCop::Cop::DefNode
8
-
9
- OFFENSE = %(
10
- Seems like it will be better to define initialize and pass %<args>s there \
11
- instead of each method.
12
- ).strip
8
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
9
+ | Seems like it will be better to define initialize and pass %<args>s
10
+ | there instead of each method.
11
+ MESSAGE
13
12
 
14
13
  def on_class(node)
15
14
  _name, inheritance, body = *node
@@ -4,12 +4,12 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class ParamsPassing < RuboCop::Cop::Cop
7
- include RuboCop::Cop::DefNode
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | It's better to pass already preprocessed params hash to services. Or
9
+ | you can use `arcane` gem.
10
+ MESSAGE
11
+
8
12
  PARAMS_CALL = s(:send, nil, :params)
9
- OFFENSE = %(
10
- It's better to pass already preprocessed params hash to services. Or you can use
11
- `arcane` gem
12
- ).strip
13
13
 
14
14
  def on_send(node)
15
15
  _who, _what, *args = *node
@@ -4,20 +4,19 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class PossibleTap < RuboCop::Cop::Cop
7
- include RuboCop::Cop::DefNode
8
-
9
- OFFENSE = %(
10
- Consider of using `.tap`, default ruby \
11
- [method](<https://apidock.com/ruby/Object/tap>) which allows to replace \
12
- intermediate variables with block, by this you are limiting scope pollution \
13
- and make scope more clear. \
14
- [Related article](<http://seejohncode.com/2012/01/02/ruby-tap-that/>).
15
- ).strip
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Consider of using `.tap`, default ruby
9
+ | [method](<https://apidock.com/ruby/Object/tap>)
10
+ | which allows to replace intermediate variables with block, by this you
11
+ | are limiting scope pollution and make scope more clear.
12
+ | [Related article](<http://seejohncode.com/2012/01/02/ruby-tap-that/>).
13
+ MESSAGE
16
14
 
17
15
  PAIRS = {
18
16
  lvar: :lvasgn,
19
17
  ivar: :ivasgn
20
18
  }.freeze
19
+
21
20
  ASSIGNS = PAIRS.keys
22
21
 
23
22
  def on_def(node)
@@ -49,11 +48,13 @@ and make scope more clear. \
49
48
 
50
49
  def return_var_call?(body)
51
50
  return unless body.children.last.respond_to?(:children)
52
- subnodes(body.children.last).find { |node| ASSIGNS.include?(node.type) }
51
+ subnodes(body.children.last.to_a.first).find do |node|
52
+ ASSIGNS.include?(node.type)
53
+ end
53
54
  end
54
55
 
55
56
  def subnodes(node)
56
- node.children.select { |child| child.respond_to?(:type) }
57
+ ([node] + node.children).select { |child| child.respond_to?(:type) }
57
58
  end
58
59
  end
59
60
  end
@@ -3,21 +3,27 @@ require 'rubocop'
3
3
 
4
4
  module Ducalis
5
5
  class PreferableMethods < RuboCop::Cop::Cop
6
- OFFENSE = %(
7
- Prefer to use %<alternative>s method instead of %<original>s because of
8
- %<reason>s.
9
- ).strip
6
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
7
+ | Prefer to use %<alternative>s method instead of %<original>s because of
8
+ | %<reason>s.
9
+ MESSAGE
10
+
10
11
  ALWAYS_TRUE = ->(_who, _what, _args) { true }
12
+
11
13
  DELETE_CHECK = lambda do |who, _what, args|
12
- !%i(sym str).include?(args.first&.type) &&
14
+ !%i(sym str).include?(args.first && args.first.type) &&
13
15
  args.count <= 1 && who.to_s !~ /file/
14
16
  end
17
+
15
18
  DESCRIPTION = {
16
19
  # Method => [Alternative, Reason, Callable condition]
17
20
  delete_all: [:destroy_all, 'it is not invoking callbacks', ALWAYS_TRUE],
18
21
  delete: [:destroy, 'it is not invoking callbacks', DELETE_CHECK]
19
22
  }.freeze
20
23
 
24
+ DETAILS = "Dangerous methods are:
25
+ #{DESCRIPTION.keys.map { |name| "`#{name}`" }.join(', ')}."
26
+
21
27
  def on_send(node)
22
28
  who, what, *args = *node
23
29
  return unless DESCRIPTION.keys.include?(what)
@@ -5,15 +5,22 @@ require 'rubocop'
5
5
  module Ducalis
6
6
  class PrivateInstanceAssign < RuboCop::Cop::Cop
7
7
  include RuboCop::Cop::DefNode
8
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
9
+ | Don't use filters for setting instance variables, use them only for
10
+ | changing application flow, such as redirecting if a user is not
11
+ | authenticated. Controller instance variables are forming contract
12
+ | between controller and view. Keeping instance variables defined in one
13
+ | place makes it easier to: reason, refactor and remove old views, test
14
+ | controllers and views, extract actions to new controllers, etc.
15
+ MESSAGE
8
16
 
9
- OFFENSE = %(
10
- Please, don't assign instance variables in controller's private methods. It's \
11
- make hard to understand what variables are available in views.
12
- ).strip
13
17
  ADD_OFFENSE = %(
14
18
  If you want to memoize variable, please, add underscore to the variable name \
15
19
  start: `@_name`.
16
20
  ).strip
21
+
22
+ DETAILS = ADD_OFFENSE
23
+
17
24
  def on_class(node)
18
25
  _classdef_node, superclass, _body = *node
19
26
  return if superclass.nil?
@@ -4,17 +4,17 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class ProtectedScopeCop < RuboCop::Cop::Cop
7
- OFFENSE = %{
8
- Seems like you are using `find` on non-protected scope. Potentially it could
9
- lead to unauthorized access. It's better to call `find` on authorized resources
10
- scopes. Example:
11
-
12
- ```ruby
13
- current_group.employees.find(params[:id])
14
- # better then
15
- Employee.find(params[:id])
16
- ```
17
- }.strip
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Seems like you are using `find` on non-protected scope. Potentially it
9
+ | could lead to unauthorized access. It's better to call `find` on
10
+ | authorized resources scopes. Example:
11
+ |
12
+ | ```ruby
13
+ | current_group.employees.find(params[:id])
14
+ | # better then
15
+ | Employee.find(params[:id])
16
+ | ```
17
+ MESSAGE
18
18
 
19
19
  def on_send(node)
20
20
  _, method_name, *args = *node
@@ -4,11 +4,10 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class RaiseWithourErrorClass < RuboCop::Cop::Cop
7
- include RuboCop::Cop::DefNode
8
- OFFENSE = %(
9
- It's better to add exception class as raise argument. It will make easier to \
10
- catch and process it later.
11
- ).strip
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | It's better to add exception class as raise argument. It will make
9
+ | easier to catch and process it later.
10
+ MESSAGE
12
11
 
13
12
  def on_send(node)
14
13
  _who, what, *args = *node
@@ -5,15 +5,17 @@ require 'regexp-examples'
5
5
 
6
6
  module Ducalis
7
7
  class RegexCop < RuboCop::Cop::Cop
8
- OFFENSE = %(
9
- It's better to move regex to constants with example instead of direct using it.
10
- It will allow you to reuse this regex and provide instructions for others.
8
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
9
+ | It's better to move regex to constants with example instead of direct
10
+ | using it. It will allow you to reuse this regex and provide instructions
11
+ | for others.
12
+ |
13
+ |```ruby
14
+ |CONST_NAME = %<constant>s # "%<example>s"
15
+ |%<fixed_string>s
16
+ |```
17
+ MESSAGE
11
18
 
12
- ```ruby
13
- CONST_NAME = %<constant>s # "%<example>s"
14
- %<fixed_string>s
15
- ```
16
- ).strip
17
19
  SELF_DESCRIPTIVE = %w(
18
20
  /[[:alnum:]]/
19
21
  /[[:alpha:]]/
@@ -31,6 +33,9 @@ CONST_NAME = %<constant>s # "%<example>s"
31
33
  /[[:ascii:]]/
32
34
  ).freeze
33
35
 
36
+ DETAILS = "Available regexes are:
37
+ #{SELF_DESCRIPTIVE.map { |name| "`#{name}`" }.join(', ')}"
38
+
34
39
  def on_regexp(node)
35
40
  return if node.parent.type == :casgn
36
41
  return if SELF_DESCRIPTIVE.include?(node.source)
@@ -5,11 +5,12 @@ require 'rubocop'
5
5
  module Ducalis
6
6
  class RestOnlyCop < RuboCop::Cop::Cop
7
7
  include RuboCop::Cop::DefNode
8
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
9
+ | It's better for controllers to stay adherent to REST:
10
+ | http://jeromedalbert.com/how-dhh-organizes-his-rails-controllers/
11
+ MESSAGE
12
+
8
13
  WHITELIST = %i(index show new edit create update destroy).freeze
9
- OFFENSE = %(
10
- It's better for controllers to stay adherent to REST:
11
- http://jeromedalbert.com/how-dhh-organizes-his-rails-controllers/
12
- ).strip
13
14
 
14
15
  def on_class(node)
15
16
  _classdef_node, superclass, _body = *node
@@ -4,10 +4,11 @@ require 'rubocop'
4
4
 
5
5
  module Ducalis
6
6
  class RubocopDisable < RuboCop::Cop::Cop
7
- OFFENSE = %(
8
- Please, do not suppress RuboCop metrics, may be you can introduce some \
9
- refactoring or another concept.
10
- )
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Please, do not suppress RuboCop metrics, may be you can introduce some
9
+ | refactoring or another concept.
10
+ MESSAGE
11
+
11
12
  def investigate(processed_source)
12
13
  return unless processed_source.ast
13
14
  processed_source.comments.each do |comment_node|
@@ -4,12 +4,13 @@ require 'rubocop'
4
4
  require_relative './callbacks_activerecord'
5
5
 
6
6
  module Ducalis
7
- class StringsInActiverecords < ::RuboCop::Cop::Cop
8
- OFFENSE = %(
9
- Please, do not use strings as arguments for %<method_name>s argument.
10
- It's hard to test, grep sources, code highlighting and so on.
11
- Consider using of symbols or lambdas for complex expressions.
12
- ).strip
7
+ class StringsInActiverecords < RuboCop::Cop::Cop
8
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
9
+ | Please, do not use strings as arguments for %<method_name>s argument.
10
+ | It's hard to test, grep sources, code highlighting and so on.
11
+ | Consider using of symbols or lambdas for complex expressions.
12
+ MESSAGE
13
+
13
14
  VALIDATEBLE_METHODS =
14
15
  ::Ducalis::CallbacksActiverecord::METHODS_BLACK_LIST + %i(
15
16
  validates
@@ -3,11 +3,12 @@
3
3
  require 'rubocop'
4
4
 
5
5
  module Ducalis
6
- class UncommentedGem < ::RuboCop::Cop::Cop
7
- OFFENSE = %(
8
- Please, add comment why are you including non-realized gem version for %<gem>s.
9
- It will increase [bus-factor](<https://en.wikipedia.org/wiki/Bus_factor>).
10
- ).strip
6
+ class UncommentedGem < RuboCop::Cop::Cop
7
+ OFFENSE = <<-MESSAGE.gsub(/^ +\|/, '').strip
8
+ | Please, add comment why are you including non-realized gem version for
9
+ | %<gem>s. It will increase
10
+ | [bus-factor](<https://en.wikipedia.org/wiki/Bus_factor>).
11
+ MESSAGE
11
12
 
12
13
  def investigate(processed_source)
13
14
  return unless processed_source.ast