ducalis 0.11.1 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +1 -1
- data/.gitignore +1 -0
- data/.travis.yml +4 -4
- data/Gemfile.lock +11 -9
- data/README.md +5 -5
- data/config/.ducalis.yml +5 -1
- data/ducalis.gemspec +1 -0
- data/lib/ducalis.rb +3 -33
- data/lib/ducalis/cli_arguments.rb +1 -0
- data/lib/ducalis/cops/black_list_suffix.rb +2 -0
- data/lib/ducalis/cops/callbacks_activerecord.rb +1 -0
- data/lib/ducalis/cops/complex_cases/smart_delete_check.rb +38 -0
- data/lib/ducalis/cops/complex_regex.rb +50 -0
- data/lib/ducalis/cops/controllers_except.rb +2 -0
- data/lib/ducalis/cops/data_access_objects.rb +1 -0
- data/lib/ducalis/cops/enforce_namespace.rb +2 -0
- data/lib/ducalis/cops/evlis_overusing.rb +2 -0
- data/lib/ducalis/cops/extensions/type_resolving.rb +1 -0
- data/lib/ducalis/cops/facade_pattern.rb +5 -2
- data/lib/ducalis/cops/fetch_expression.rb +2 -1
- data/lib/ducalis/cops/keyword_defaults.rb +5 -0
- data/lib/ducalis/cops/module_like_class.rb +4 -0
- data/lib/ducalis/cops/multiple_times.rb +4 -4
- data/lib/ducalis/cops/only_defs.rb +1 -0
- data/lib/ducalis/cops/options_argument.rb +1 -0
- data/lib/ducalis/cops/params_passing.rb +2 -0
- data/lib/ducalis/cops/possible_tap.rb +7 -3
- data/lib/ducalis/cops/preferable_methods.rb +4 -8
- data/lib/ducalis/cops/private_instance_assign.rb +2 -0
- data/lib/ducalis/cops/protected_scope_cop.rb +1 -0
- data/lib/ducalis/cops/public_send.rb +1 -0
- data/lib/ducalis/cops/raise_without_error_class.rb +1 -0
- data/lib/ducalis/cops/recursion.rb +1 -0
- data/lib/ducalis/cops/regex_cop.rb +1 -0
- data/lib/ducalis/cops/rest_only_cop.rb +2 -0
- data/lib/ducalis/cops/rubocop_disable.rb +2 -0
- data/lib/ducalis/cops/standard_methods.rb +1 -0
- data/lib/ducalis/cops/strings_in_activerecords.rb +3 -0
- data/lib/ducalis/cops/too_long_workers.rb +2 -0
- data/lib/ducalis/cops/uncommented_gem.rb +3 -0
- data/lib/ducalis/cops/unlocked_gem.rb +1 -0
- data/lib/ducalis/cops/useless_only.rb +2 -0
- data/lib/ducalis/documentation.rb +4 -4
- data/lib/ducalis/git_access.rb +4 -1
- data/lib/ducalis/patch.rb +4 -4
- data/lib/ducalis/patched_rubocop/git_turget_finder.rb +1 -0
- data/lib/ducalis/rubo_cop.rb +1 -0
- data/lib/ducalis/version.rb +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9aadaf2bffe42d747bfec8a03418ca1ba12fff39018e1b32305ad71c4108f5b3
|
4
|
+
data.tar.gz: 42115ba6b4ba38977f7cf65eeb8684b90dea5faaeaf4a7bea17e03b0768c79a2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 384403e2c35a226966cbe8e3102fbed36bff5bcba77cc963f3d2dd5c670a66ac7e766dd3f0231a7005bc97091bcb23f55180a6eda7de2b3553072c55a2a926c9
|
7
|
+
data.tar.gz: f267d508e2b72e8f70acbf842703c8563f8b16893bf534c8abf8b02d16b682e0fde539e976969791b27d3578dee9db9d3746302cf9d4875f643d35ba8fc34ef3
|
data/.codeclimate.yml
CHANGED
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
language: ruby
|
2
2
|
rvm:
|
3
3
|
- 2.2.9
|
4
|
-
- 2.3.
|
5
|
-
- 2.4.
|
4
|
+
- 2.3.8
|
5
|
+
- 2.4.5
|
6
6
|
before_install:
|
7
7
|
- gem update --system
|
8
8
|
- gem --version
|
@@ -12,5 +12,5 @@ script:
|
|
12
12
|
- bash bin/legacy_versions_test.sh
|
13
13
|
matrix:
|
14
14
|
include:
|
15
|
-
- rvm: 2.5.
|
16
|
-
env: IGNORE_LEGACY=true
|
15
|
+
- rvm: 2.5.3
|
16
|
+
env: IGNORE_LEGACY=true WITH_DOCS=true
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ducalis (0.
|
4
|
+
ducalis (0.12.0)
|
5
5
|
git (~> 1.3, >= 1.3.0)
|
6
6
|
octokit (>= 4.7.0)
|
7
7
|
regexp-examples (~> 1.3, >= 1.3.2)
|
8
|
+
regexp_parser (>= 0.5.0)
|
8
9
|
rubocop (>= 0.45.0)
|
9
10
|
|
10
11
|
GEM
|
@@ -15,25 +16,26 @@ GEM
|
|
15
16
|
ast (2.4.0)
|
16
17
|
coderay (1.1.2)
|
17
18
|
diff-lcs (1.3)
|
18
|
-
faraday (0.15.
|
19
|
+
faraday (0.15.3)
|
19
20
|
multipart-post (>= 1.2, < 3)
|
20
|
-
git (1.
|
21
|
-
jaro_winkler (1.5.1)
|
21
|
+
git (1.5.0)
|
22
|
+
jaro_winkler (1.5.1-x86_64-darwin-17)
|
22
23
|
method_source (0.9.0)
|
23
24
|
multipart-post (2.0.0)
|
24
|
-
octokit (4.
|
25
|
+
octokit (4.13.0)
|
25
26
|
sawyer (~> 0.8.0, >= 0.5.3)
|
26
27
|
parallel (1.12.1)
|
27
|
-
parser (2.5.
|
28
|
+
parser (2.5.3.0)
|
28
29
|
ast (~> 2.4.0)
|
29
30
|
powerpack (0.1.2)
|
30
31
|
pry (0.11.3)
|
31
32
|
coderay (~> 1.1.0)
|
32
33
|
method_source (~> 0.9.0)
|
33
|
-
public_suffix (3.0.
|
34
|
+
public_suffix (3.0.3)
|
34
35
|
rainbow (3.0.0)
|
35
36
|
rake (12.3.0)
|
36
37
|
regexp-examples (1.4.3)
|
38
|
+
regexp_parser (1.2.0)
|
37
39
|
rspec (3.7.0)
|
38
40
|
rspec-core (~> 3.7.0)
|
39
41
|
rspec-expectations (~> 3.7.0)
|
@@ -47,14 +49,14 @@ GEM
|
|
47
49
|
diff-lcs (>= 1.2.0, < 2.0)
|
48
50
|
rspec-support (~> 3.7.0)
|
49
51
|
rspec-support (3.7.1)
|
50
|
-
rubocop (0.
|
52
|
+
rubocop (0.60.0)
|
51
53
|
jaro_winkler (~> 1.5.1)
|
52
54
|
parallel (~> 1.10)
|
53
55
|
parser (>= 2.5, != 2.5.1.1)
|
54
56
|
powerpack (~> 0.1)
|
55
57
|
rainbow (>= 2.2.2, < 4.0)
|
56
58
|
ruby-progressbar (~> 1.7)
|
57
|
-
unicode-display_width (~> 1.
|
59
|
+
unicode-display_width (~> 1.4.0)
|
58
60
|
ruby-progressbar (1.10.0)
|
59
61
|
sawyer (0.8.1)
|
60
62
|
addressable (>= 2.3.5, < 2.6)
|
data/README.md
CHANGED
@@ -24,7 +24,7 @@ __Ducalis__ is CLI application. By defaukt it will notify you about any possible
|
|
24
24
|
violations in CLI.
|
25
25
|
|
26
26
|
```
|
27
|
-
ducalis
|
27
|
+
ducalis .
|
28
28
|
ducalis app/controllers/
|
29
29
|
```
|
30
30
|
|
@@ -32,16 +32,16 @@ __Ducalis__ allows to pass build even with violations it's make sense to run
|
|
32
32
|
__Ducalis__ across current branch or index:
|
33
33
|
|
34
34
|
```
|
35
|
-
ducalis --branch
|
36
|
-
ducalis --index
|
35
|
+
ducalis --branch .
|
36
|
+
ducalis --index .
|
37
37
|
```
|
38
38
|
|
39
39
|
Additionally you can pass `--reporter` argument to notify about found violations
|
40
40
|
in boundaries of PR:
|
41
41
|
|
42
42
|
```
|
43
|
-
ducalis --reporter "author/repo#42"
|
44
|
-
ducalis --reporter "circleci"
|
43
|
+
ducalis --reporter "author/repo#42" .
|
44
|
+
ducalis --reporter "circleci" .
|
45
45
|
```
|
46
46
|
|
47
47
|
_N.B._ You should provide `GITHUB_TOKEN` Env to allow __Ducalis__ download your
|
data/config/.ducalis.yml
CHANGED
@@ -31,6 +31,10 @@ Ducalis/PreferableMethods:
|
|
31
31
|
Ducalis/Recursion:
|
32
32
|
Enabled: true
|
33
33
|
|
34
|
+
Ducalis/ComplexRegex:
|
35
|
+
Enabled: true
|
36
|
+
MaxComplexity: 3
|
37
|
+
|
34
38
|
Ducalis/CaseMapping:
|
35
39
|
Enabled: true
|
36
40
|
|
@@ -48,7 +52,7 @@ Ducalis/PossibleTap:
|
|
48
52
|
Enabled: false
|
49
53
|
|
50
54
|
Ducalis/PublicSend:
|
51
|
-
Enabled:
|
55
|
+
Enabled: true
|
52
56
|
|
53
57
|
Ducalis/FetchExpression:
|
54
58
|
Enabled: true
|
data/ducalis.gemspec
CHANGED
@@ -30,5 +30,6 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_dependency 'git', '~> 1.3', '>= 1.3.0'
|
31
31
|
spec.add_dependency 'octokit', '>= 4.7.0'
|
32
32
|
spec.add_dependency 'regexp-examples', '~> 1.3', '>= 1.3.2'
|
33
|
+
spec.add_dependency 'regexp_parser', '>= 0.5.0'
|
33
34
|
spec.add_dependency 'rubocop', '>= 0.45.0'
|
34
35
|
end
|
data/lib/ducalis.rb
CHANGED
@@ -30,36 +30,6 @@ require 'ducalis/cli_arguments'
|
|
30
30
|
require 'ducalis/patch'
|
31
31
|
require 'ducalis/git_access'
|
32
32
|
|
33
|
-
|
34
|
-
require
|
35
|
-
|
36
|
-
require 'ducalis/cops/controllers_except'
|
37
|
-
require 'ducalis/cops/data_access_objects'
|
38
|
-
require 'ducalis/cops/descriptive_block_names'
|
39
|
-
require 'ducalis/cops/enforce_namespace'
|
40
|
-
require 'ducalis/cops/evlis_overusing'
|
41
|
-
require 'ducalis/cops/extensions/type_resolving'
|
42
|
-
require 'ducalis/cops/facade_pattern'
|
43
|
-
require 'ducalis/cops/fetch_expression'
|
44
|
-
require 'ducalis/cops/keyword_defaults'
|
45
|
-
require 'ducalis/cops/module_like_class'
|
46
|
-
require 'ducalis/cops/multiple_times'
|
47
|
-
require 'ducalis/cops/only_defs'
|
48
|
-
require 'ducalis/cops/options_argument'
|
49
|
-
require 'ducalis/cops/params_passing'
|
50
|
-
require 'ducalis/cops/possible_tap'
|
51
|
-
require 'ducalis/cops/preferable_methods'
|
52
|
-
require 'ducalis/cops/private_instance_assign'
|
53
|
-
require 'ducalis/cops/protected_scope_cop'
|
54
|
-
require 'ducalis/cops/public_send'
|
55
|
-
require 'ducalis/cops/raise_without_error_class'
|
56
|
-
require 'ducalis/cops/recursion'
|
57
|
-
require 'ducalis/cops/regex_cop'
|
58
|
-
require 'ducalis/cops/rest_only_cop'
|
59
|
-
require 'ducalis/cops/rubocop_disable'
|
60
|
-
require 'ducalis/cops/standard_methods'
|
61
|
-
require 'ducalis/cops/strings_in_activerecords'
|
62
|
-
require 'ducalis/cops/too_long_workers'
|
63
|
-
require 'ducalis/cops/uncommented_gem'
|
64
|
-
require 'ducalis/cops/unlocked_gem'
|
65
|
-
require 'ducalis/cops/useless_only'
|
33
|
+
Dir[File.join('.', 'lib', 'ducalis', 'cops', '**', '*.rb')].each do |file|
|
34
|
+
require file
|
35
|
+
end
|
@@ -17,6 +17,7 @@ module Ducalis
|
|
17
17
|
def on_class(node)
|
18
18
|
classdef_node, _superclass, _body = *node
|
19
19
|
return unless with_blacklisted_suffix?(classdef_node.source)
|
20
|
+
|
20
21
|
add_offense(node, :expression, OFFENSE)
|
21
22
|
end
|
22
23
|
|
@@ -24,6 +25,7 @@ module Ducalis
|
|
24
25
|
|
25
26
|
def with_blacklisted_suffix?(name)
|
26
27
|
return if cop_config['BlackList'].to_a.empty?
|
28
|
+
|
27
29
|
cop_config['BlackList'].any? { |suffix| name.end_with?(suffix) }
|
28
30
|
end
|
29
31
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ComplexCases
|
4
|
+
class SmartDeleteCheck
|
5
|
+
WHITE_LIST = %w[File cache file params attrs options].freeze
|
6
|
+
|
7
|
+
def self.call(who, what, args)
|
8
|
+
!new(who, what, args).false_positive?
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(who, _what, args)
|
12
|
+
@who = who
|
13
|
+
@args = args
|
14
|
+
end
|
15
|
+
|
16
|
+
def false_positive?
|
17
|
+
[
|
18
|
+
called_with_stringlike?,
|
19
|
+
many_args?,
|
20
|
+
whitelisted?
|
21
|
+
].any?
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def called_with_stringlike?
|
27
|
+
%i[sym str].include?(@args.first && @args.first.type)
|
28
|
+
end
|
29
|
+
|
30
|
+
def many_args?
|
31
|
+
@args.count > 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def whitelisted?
|
35
|
+
WHITE_LIST.any? { |regex| @who.to_s.include?(regex) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubocop'
|
4
|
+
require 'regexp_parser'
|
5
|
+
|
6
|
+
module Ducalis
|
7
|
+
class ComplexRegex < RuboCop::Cop::Cop
|
8
|
+
include RuboCop::Cop::DefNode
|
9
|
+
|
10
|
+
OFFENSE = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
11
|
+
| It seems like this regex is a little bit complex. It's better to increase code readability by using long form with "\\x".
|
12
|
+
MESSAGE
|
13
|
+
DEFAULT_COST = 0
|
14
|
+
COMPLEX_TYPES_COSTS = {
|
15
|
+
quantifier: 1,
|
16
|
+
meta: 1,
|
17
|
+
assertion: 1,
|
18
|
+
group: 0.5
|
19
|
+
}.freeze
|
20
|
+
|
21
|
+
def on_begin(node)
|
22
|
+
regex_using(node).each do |regex_desc|
|
23
|
+
next if formatted?(regex_desc) || simple?(regex_desc.first)
|
24
|
+
|
25
|
+
add_offense(regex_desc.first, :expression, OFFENSE)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def simple?(regex_node)
|
32
|
+
Regexp::Scanner.scan(
|
33
|
+
Regexp.new(regex_node.source)
|
34
|
+
).map do |type, _, _, _, _|
|
35
|
+
COMPLEX_TYPES_COSTS.fetch(type, DEFAULT_COST)
|
36
|
+
end.inject(:+) <= maximal_complexity
|
37
|
+
end
|
38
|
+
|
39
|
+
def maximal_complexity
|
40
|
+
cop_config['MaxComplexity']
|
41
|
+
end
|
42
|
+
|
43
|
+
def formatted?(regex_desc)
|
44
|
+
regex_desc.size > 1
|
45
|
+
end
|
46
|
+
|
47
|
+
def_node_search :regex_long_form?, '(regopt :x)'
|
48
|
+
def_node_search :regex_using, '(regexp $... (regopt ...))'
|
49
|
+
end
|
50
|
+
end
|
@@ -15,8 +15,10 @@ module Ducalis
|
|
15
15
|
_, method_name, *args = *node
|
16
16
|
hash_node = args.find { |subnode| subnode.type == :hash }
|
17
17
|
return unless FILTERS.include?(method_name) && hash_node
|
18
|
+
|
18
19
|
type, _method_names = decomposite_hash(hash_node)
|
19
20
|
return unless type == s(:sym, :except)
|
21
|
+
|
20
22
|
add_offense(node, :selector, OFFENSE)
|
21
23
|
end
|
22
24
|
|
@@ -12,12 +12,14 @@ module Ducalis
|
|
12
12
|
|
13
13
|
def on_class(node)
|
14
14
|
return if !node.parent.nil? || !in_service?
|
15
|
+
|
15
16
|
add_offense(node, :expression, OFFENSE)
|
16
17
|
end
|
17
18
|
|
18
19
|
def on_module(node)
|
19
20
|
return if !node.parent.nil? || !in_service?
|
20
21
|
return if contains_class?(node) || contains_classes?(node)
|
22
|
+
|
21
23
|
add_offense(node, :expression, OFFENSE)
|
22
24
|
end
|
23
25
|
|
@@ -16,11 +16,13 @@ module Ducalis
|
|
16
16
|
|
17
17
|
def on_send(node)
|
18
18
|
return unless nested_try?(node)
|
19
|
+
|
19
20
|
add_offense(node, :expression, OFFENSE)
|
20
21
|
end
|
21
22
|
|
22
23
|
def on_csend(node)
|
23
24
|
return unless node.child_nodes.any?(&:csend_type?)
|
25
|
+
|
24
26
|
add_offense(node, :expression, OFFENSE)
|
25
27
|
end
|
26
28
|
|
@@ -19,8 +19,11 @@ module Ducalis
|
|
19
19
|
def on_def(node)
|
20
20
|
return unless in_controller?
|
21
21
|
return if non_public?(node)
|
22
|
-
|
23
|
-
|
22
|
+
|
23
|
+
assigns = instance_variables_matches(node)
|
24
|
+
return if assigns.count < max_instance_variables
|
25
|
+
|
26
|
+
assigns.each { |assign| add_offense(assign, :expression, OFFENSE) }
|
24
27
|
end
|
25
28
|
|
26
29
|
private
|
@@ -4,7 +4,7 @@ require 'rubocop'
|
|
4
4
|
|
5
5
|
module Ducalis
|
6
6
|
class FetchExpression < RuboCop::Cop::Cop
|
7
|
-
HASH_CALLING_REGEX = /\:\[\]
|
7
|
+
HASH_CALLING_REGEX = /\:\[\]/.freeze # params[:key]
|
8
8
|
|
9
9
|
OFFENSE = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
10
10
|
| You can use `fetch` instead:
|
@@ -19,6 +19,7 @@ module Ducalis
|
|
19
19
|
|
20
20
|
def investigate(processed_source)
|
21
21
|
return unless processed_source.ast
|
22
|
+
|
22
23
|
matching_nodes(processed_source.ast).each do |node|
|
23
24
|
add_offense(node, :expression, format(OFFENSE,
|
24
25
|
source: correct_variant(node)))
|
@@ -6,12 +6,17 @@ module Ducalis
|
|
6
6
|
class KeywordDefaults < RuboCop::Cop::Cop
|
7
7
|
OFFENSE = <<-MESSAGE.gsub(/^ +\|\s/, '').strip
|
8
8
|
| Prefer to use keyword arguments for defaults. It increases readability and reduces ambiguities.
|
9
|
+
| It is ok if an argument is single and the name obvious from the function declaration.
|
9
10
|
MESSAGE
|
10
11
|
|
11
12
|
def on_def(node)
|
12
13
|
args = node.type == :defs ? node.to_a[2] : node.to_a[1]
|
14
|
+
|
15
|
+
return if args.to_a.one?
|
16
|
+
|
13
17
|
args.children.each do |arg_node|
|
14
18
|
next unless arg_node.type == :optarg
|
19
|
+
|
15
20
|
add_offense(node, :expression, OFFENSE)
|
16
21
|
end
|
17
22
|
end
|
@@ -13,8 +13,10 @@ module Ducalis
|
|
13
13
|
def on_class(node)
|
14
14
|
_name, inheritance, body = *node
|
15
15
|
return if !inheritance.nil? || body.nil? || allowed_include?(body)
|
16
|
+
|
16
17
|
matched = matched_args(body)
|
17
18
|
return if matched.empty?
|
19
|
+
|
18
20
|
add_offense(node, :expression,
|
19
21
|
format(OFFENSE, args:
|
20
22
|
matched.map { |arg| "`#{arg}`" }.join(', ')))
|
@@ -24,12 +26,14 @@ module Ducalis
|
|
24
26
|
|
25
27
|
def allowed_include?(body)
|
26
28
|
return if cop_config['AllowedIncludes'].to_a.empty?
|
29
|
+
|
27
30
|
(all_includes(body) & cop_config['AllowedIncludes']).any?
|
28
31
|
end
|
29
32
|
|
30
33
|
def matched_args(body)
|
31
34
|
methods_defintions = children(body).select(&public_method_definition?)
|
32
35
|
return [] if methods_defintions.count == 1 && with_initialize?(body)
|
36
|
+
|
33
37
|
methods_defintions.map(&method_args).inject(&:&).to_a
|
34
38
|
end
|
35
39
|
|
@@ -29,12 +29,11 @@ module Ducalis
|
|
29
29
|
|
30
30
|
def on_def(body)
|
31
31
|
multiple = [
|
32
|
-
date_today(body),
|
33
|
-
|
34
|
-
time_current(body),
|
35
|
-
time_now(body)
|
32
|
+
date_today(body), date_current(body), date_yesterday(body),
|
33
|
+
time_current(body), time_now(body)
|
36
34
|
].map(&:to_a).compact.flatten.to_a
|
37
35
|
return if multiple.count < 2
|
36
|
+
|
38
37
|
multiple.each do |time_node|
|
39
38
|
add_offense(time_node, :expression, OFFENSE)
|
40
39
|
end
|
@@ -44,6 +43,7 @@ module Ducalis
|
|
44
43
|
|
45
44
|
def_node_search :date_today, '(send (const _ :Date) :today)'
|
46
45
|
def_node_search :date_current, '(send (const _ :Date) :current)'
|
46
|
+
def_node_search :date_yesterday, '(send (const _ :Date) :yesterday)'
|
47
47
|
def_node_search :time_current, '(send (const _ :Time) :current)'
|
48
48
|
def_node_search :time_now, '(send (const _ :Time) :now)'
|
49
49
|
end
|
@@ -20,6 +20,7 @@ module Ducalis
|
|
20
20
|
|
21
21
|
def inspect_args(args)
|
22
22
|
return if Array(args).empty?
|
23
|
+
|
23
24
|
args.find { |arg| arg == PARAMS_CALL }.tap do |node|
|
24
25
|
return node if node
|
25
26
|
end
|
@@ -28,6 +29,7 @@ module Ducalis
|
|
28
29
|
|
29
30
|
def inspect_hash(args)
|
30
31
|
return if args.nil?
|
32
|
+
|
31
33
|
args.children.find { |arg| arg.to_a[1] == PARAMS_CALL }
|
32
34
|
end
|
33
35
|
end
|
@@ -26,31 +26,34 @@ module Ducalis
|
|
26
26
|
return if body.nil?
|
27
27
|
return unless (possibe_var = return_var?(body) || return_var_call?(body))
|
28
28
|
return unless (assign_node = find_assign(body, possibe_var))
|
29
|
+
|
29
30
|
add_offense(assign_node, :expression, OFFENSE)
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
33
34
|
|
34
|
-
def
|
35
|
+
def unwrap_assign(node)
|
35
36
|
node.type == :or_asgn ? node.children.first : node
|
36
37
|
end
|
37
38
|
|
38
39
|
def find_assign(body, var_node)
|
39
40
|
subnodes(body).find do |subnode|
|
40
|
-
|
41
|
-
|
41
|
+
unwrap_assign(subnode).type == PAIRS[var_node.type] &&
|
42
|
+
unwrap_assign(subnode).to_a.first == var_node.to_a.first
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
46
|
def return_var?(body)
|
46
47
|
return unless body.children.last.respond_to?(:type)
|
47
48
|
return unless ASSIGNS.include?(body.children.last.type)
|
49
|
+
|
48
50
|
body.children.last
|
49
51
|
end
|
50
52
|
|
51
53
|
def return_var_call?(body)
|
52
54
|
return unless last_child(body).respond_to?(:children)
|
53
55
|
return if last_child(body).type == :if
|
56
|
+
|
54
57
|
subnodes(last_child(body).to_a.first).find do |node|
|
55
58
|
ASSIGNS.include?(node.type)
|
56
59
|
end
|
@@ -58,6 +61,7 @@ module Ducalis
|
|
58
61
|
|
59
62
|
def subnodes(node)
|
60
63
|
return [] unless node.respond_to?(:children)
|
64
|
+
|
61
65
|
([node] + node.children).select { |child| child.respond_to?(:type) }
|
62
66
|
end
|
63
67
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'rubocop'
|
4
|
+
require 'ducalis/cops/complex_cases/smart_delete_check'
|
4
5
|
|
5
6
|
module Ducalis
|
6
7
|
class PreferableMethods < RuboCop::Cop::Cop
|
@@ -8,15 +9,8 @@ module Ducalis
|
|
8
9
|
| Prefer to use %<alternative>s method instead of %<original>s because of %<reason>s.
|
9
10
|
MESSAGE
|
10
11
|
|
11
|
-
WHITE_LIST = %w[cache file params attrs options].freeze
|
12
|
-
|
13
12
|
ALWAYS_TRUE = ->(_who, _what, _args) { true }
|
14
13
|
|
15
|
-
DELETE_CHECK = lambda do |who, _what, args|
|
16
|
-
!%i[sym str].include?(args.first && args.first.type) &&
|
17
|
-
args.count <= 1 && WHITE_LIST.none? { |regex| who.to_s.include?(regex) }
|
18
|
-
end
|
19
|
-
|
20
14
|
VALIDATE_CHECK = lambda do |_who, _what, args|
|
21
15
|
(args.first && args.first.source) =~ /validate/
|
22
16
|
end
|
@@ -40,7 +34,7 @@ module Ducalis
|
|
40
34
|
delete: [
|
41
35
|
'`destroy`',
|
42
36
|
'it is not invoking callbacks',
|
43
|
-
|
37
|
+
ComplexCases::SmartDeleteCheck
|
44
38
|
],
|
45
39
|
delete_all: [
|
46
40
|
'`destroy_all`',
|
@@ -70,8 +64,10 @@ module Ducalis
|
|
70
64
|
def on_send(node)
|
71
65
|
who, what, *args = *node
|
72
66
|
return unless DESCRIPTION.key?(what)
|
67
|
+
|
73
68
|
alternative, reason, condition = DESCRIPTION.fetch(what)
|
74
69
|
return unless condition.call(who, what, args)
|
70
|
+
|
75
71
|
add_offense(node, :expression, format(OFFENSE, original: what,
|
76
72
|
alternative: alternative,
|
77
73
|
reason: reason))
|
@@ -22,6 +22,7 @@ module Ducalis
|
|
22
22
|
return unless in_controller?
|
23
23
|
return unless non_public?(node)
|
24
24
|
return check_memo(node) if node.parent.type == :or_asgn
|
25
|
+
|
25
26
|
add_offense(node, :expression, OFFENSE)
|
26
27
|
end
|
27
28
|
|
@@ -29,6 +30,7 @@ module Ducalis
|
|
29
30
|
|
30
31
|
def check_memo(node)
|
31
32
|
return if node.to_a.first.to_s.start_with?('@_')
|
33
|
+
|
32
34
|
add_offense(node, :expression, [OFFENSE, ADD_OFFENSE].join(' '))
|
33
35
|
end
|
34
36
|
end
|
@@ -10,8 +10,10 @@ module Ducalis
|
|
10
10
|
|
11
11
|
def investigate(processed_source)
|
12
12
|
return unless processed_source.ast
|
13
|
+
|
13
14
|
processed_source.comments.each do |comment_node|
|
14
15
|
next unless comment_node.loc.expression.source =~ /rubocop:disable/
|
16
|
+
|
15
17
|
add_offense(comment_node, :expression, OFFENSE)
|
16
18
|
end
|
17
19
|
end
|
@@ -19,8 +19,10 @@ module Ducalis
|
|
19
19
|
_, method_name, *args = *node
|
20
20
|
return unless VALIDATEBLE_METHODS.include?(method_name)
|
21
21
|
return if args.empty?
|
22
|
+
|
22
23
|
node.to_a.last.each_child_node do |current_node|
|
23
24
|
next if skip_node?(current_node)
|
25
|
+
|
24
26
|
add_offense(node, :selector, format(OFFENSE, method_name: method_name))
|
25
27
|
end
|
26
28
|
end
|
@@ -32,6 +34,7 @@ module Ducalis
|
|
32
34
|
return true unless current_node.type == :pair
|
33
35
|
return true unless %w[if unless].include?(key.source)
|
34
36
|
return true unless value.type == :str
|
37
|
+
|
35
38
|
false
|
36
39
|
end
|
37
40
|
end
|
@@ -16,9 +16,11 @@ module Ducalis
|
|
16
16
|
|
17
17
|
def investigate(processed_source)
|
18
18
|
return unless processed_source.ast
|
19
|
+
|
19
20
|
gem_declarations(processed_source.ast).select do |node|
|
20
21
|
_, _, gemname, _args = *node
|
21
22
|
next if commented?(processed_source, node)
|
23
|
+
|
22
24
|
add_offense(node, :selector,
|
23
25
|
format(OFFENSE, gem: gemname.loc.expression.source))
|
24
26
|
end
|
@@ -36,6 +38,7 @@ module Ducalis
|
|
36
38
|
|
37
39
|
def allowed_args?(args)
|
38
40
|
return false if args.nil? || args.type != :hash
|
41
|
+
|
39
42
|
args.children.any? do |arg_node|
|
40
43
|
!ALLOWED_KEYS.include?(arg_node.children.first.source)
|
41
44
|
end
|
@@ -32,9 +32,11 @@ module Ducalis
|
|
32
32
|
_, method_name, *args = *node
|
33
33
|
hash_node = args.find { |subnode| subnode.type == :hash }
|
34
34
|
return unless FILTERS.include?(method_name) && hash_node
|
35
|
+
|
35
36
|
type, method_names = decomposite_hash(hash_node)
|
36
37
|
return unless type == s(:sym, :only)
|
37
38
|
return unless method_names.children.count == 1
|
39
|
+
|
38
40
|
add_offense(node, :selector, OFFENSE)
|
39
41
|
end
|
40
42
|
|
@@ -8,10 +8,10 @@ require 'parser/current'
|
|
8
8
|
class SpecsProcessor < Parser::AST::Processor
|
9
9
|
attr_reader :cases
|
10
10
|
|
11
|
-
LINE_BEGIN_OPEN_SQUARE_BRACKET = /\A\[
|
12
|
-
CLOSE_SQUARE_BRACKET_END_LINE = /\]\z
|
13
|
-
LINE_BEGIN_QUOTE = /\A[\'|\"]
|
14
|
-
QUOTE_COMMA_END_LINE = /[\'|\"]\,?\z
|
11
|
+
LINE_BEGIN_OPEN_SQUARE_BRACKET = /\A\[/.freeze # "/[/1, 2, 3]\n"
|
12
|
+
CLOSE_SQUARE_BRACKET_END_LINE = /\]\z/.freeze # "[1, 2, 3/]\n/"
|
13
|
+
LINE_BEGIN_QUOTE = /\A[\'|\"]/.freeze # "/'/idddqd',"
|
14
|
+
QUOTE_COMMA_END_LINE = /[\'|\"]\,?\z/.freeze # "'iddqd/',/"
|
15
15
|
|
16
16
|
def initialize(*)
|
17
17
|
super
|
data/lib/ducalis/git_access.rb
CHANGED
@@ -9,7 +9,7 @@ class GitAccess
|
|
9
9
|
|
10
10
|
MODES = {
|
11
11
|
branch: ->(git) { git.diff('origin/master') },
|
12
|
-
index:
|
12
|
+
index: ->(git) { git.diff('HEAD') }
|
13
13
|
}.freeze
|
14
14
|
|
15
15
|
include Diffs
|
@@ -29,6 +29,7 @@ class GitAccess
|
|
29
29
|
|
30
30
|
def for(path)
|
31
31
|
return find(path) unless path.include?(Dir.pwd)
|
32
|
+
|
32
33
|
find(Pathname.new(path).relative_path_from(Pathname.new(Dir.pwd)).to_s)
|
33
34
|
end
|
34
35
|
|
@@ -40,6 +41,7 @@ class GitAccess
|
|
40
41
|
|
41
42
|
def changes
|
42
43
|
return default_value if flag.nil? || !under_git?
|
44
|
+
|
43
45
|
@changes ||= patch_diffs
|
44
46
|
end
|
45
47
|
|
@@ -53,6 +55,7 @@ class GitAccess
|
|
53
55
|
|
54
56
|
def default_value
|
55
57
|
raise Ducalis::MissingGit unless flag.nil?
|
58
|
+
|
56
59
|
[]
|
57
60
|
end
|
58
61
|
|
data/lib/ducalis/patch.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Ducalis
|
4
4
|
class Patch
|
5
|
-
RANGE_LINE = /^@@ .+\+(?<line_number>\d+)
|
6
|
-
MODIFIED_LINE = /^\+(?!\+|\+)
|
7
|
-
NOT_REMOVED_LINE = /^[^-]
|
8
|
-
ANY_LINE =
|
5
|
+
RANGE_LINE = /^@@ .+\+(?<line_number>\d+),/.freeze
|
6
|
+
MODIFIED_LINE = /^\+(?!\+|\+)/.freeze
|
7
|
+
NOT_REMOVED_LINE = /^[^-]/.freeze
|
8
|
+
ANY_LINE = /.*/.freeze
|
9
9
|
|
10
10
|
DIFF_LINES = {
|
11
11
|
RANGE_LINE => lambda do |lines, _line_number, line, _position|
|
data/lib/ducalis/rubo_cop.rb
CHANGED
data/lib/ducalis/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ducalis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ignat Zakrevsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
@@ -64,6 +64,20 @@ dependencies:
|
|
64
64
|
- - ">="
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: 1.3.2
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: regexp_parser
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.5.0
|
74
|
+
type: :runtime
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: 0.5.0
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
name: rubocop
|
69
83
|
requirement: !ruby/object:Gem::Requirement
|
@@ -111,6 +125,8 @@ files:
|
|
111
125
|
- lib/ducalis/cops/black_list_suffix.rb
|
112
126
|
- lib/ducalis/cops/callbacks_activerecord.rb
|
113
127
|
- lib/ducalis/cops/case_mapping.rb
|
128
|
+
- lib/ducalis/cops/complex_cases/smart_delete_check.rb
|
129
|
+
- lib/ducalis/cops/complex_regex.rb
|
114
130
|
- lib/ducalis/cops/controllers_except.rb
|
115
131
|
- lib/ducalis/cops/data_access_objects.rb
|
116
132
|
- lib/ducalis/cops/descriptive_block_names.rb
|