rubocop-nueca 1.1.5 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/rubocop/cop/rails/model_association_missing_through.rb +1 -0
- data/lib/rubocop/cop/rails/route_consistent_spacing.rb +9 -21
- data/lib/rubocop/cop/rails/route_grouping.rb +9 -21
- data/lib/rubocop/cop/rails/route_root_position.rb +13 -19
- data/lib/rubocop/cop/rails/route_separation.rb +9 -21
- data/lib/rubocop/cop/rails/route_sorting.rb +9 -21
- data/lib/rubocop/cop/shared/collection_context.rb +60 -3
- data/lib/rubocop/cop/shared/route_helper.rb +68 -0
- data/lib/rubocop/nueca/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a49b9e5e060e7ec154ef9feaf553325fb156d58c59aba67ea3cc2ac1e1e13b67
|
4
|
+
data.tar.gz: 3e110fe0c9a710158865e3f67a443dacde11a7aba68f92df3ff305016cc2fdbc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 376a36b1a4e897c49af1fc553504471e2c9014e8bfb1b147dc9f0d1af5f5202acb3e91feaf382310f17468e7515b1c59d2cb8d0198285418d5733cf2a643742d
|
7
|
+
data.tar.gz: 910aef0f0fd56d15ef56c1fe7b2e3bb2ebc18d65dfb35aa7c88ab698e6e6ed8fe8bd21635ff3ca94f85c10f9c730d81b5fc3b247a4412dfb180f9f869093d693
|
@@ -1,39 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../shared/
|
3
|
+
require_relative '../shared/route_helper'
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Rails
|
8
8
|
class RouteConsistentSpacing < RuboCop::Cop::Base
|
9
|
+
include RouteHelper
|
10
|
+
|
9
11
|
MSG = 'Do not leave blank lines between routes of the same type at the same namespace level.'
|
10
12
|
|
11
13
|
def on_block(node)
|
12
|
-
|
13
|
-
|
14
|
-
routes = collect_routes(node)
|
15
|
-
return if routes.size < 2
|
14
|
+
process_route_block(node)
|
15
|
+
end
|
16
16
|
|
17
|
-
|
17
|
+
def investigate(processed_source)
|
18
|
+
process_route_file(processed_source)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
send_node = node.send_node
|
26
|
-
receiver = send_node.receiver
|
27
|
-
return false unless receiver
|
28
|
-
|
29
|
-
receiver.source == 'Rails.application.routes' && send_node.method_name == :draw
|
30
|
-
end
|
31
|
-
|
32
|
-
def collect_routes(routes_block)
|
33
|
-
collector = RouteCollector.new
|
34
|
-
body = routes_block.body
|
35
|
-
collector.collect(body) if body
|
36
|
-
collector.routes.sort_by { |route| route[:line] }
|
23
|
+
def check_routes(routes)
|
24
|
+
check_consistent_spacing(routes)
|
37
25
|
end
|
38
26
|
|
39
27
|
def check_consistent_spacing(routes)
|
@@ -1,39 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../shared/
|
3
|
+
require_relative '../shared/route_helper'
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Rails
|
8
8
|
class RouteGrouping < RuboCop::Cop::Base
|
9
|
+
include RouteHelper
|
10
|
+
|
9
11
|
MSG = 'Group routes by type. Keep simple routes, resources, and namespaces grouped together.'
|
10
12
|
|
11
13
|
def on_block(node)
|
12
|
-
|
13
|
-
|
14
|
-
routes = collect_routes(node)
|
15
|
-
return if routes.size < 2
|
14
|
+
process_route_block(node)
|
15
|
+
end
|
16
16
|
|
17
|
-
|
17
|
+
def investigate(processed_source)
|
18
|
+
process_route_file(processed_source)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
send_node = node.send_node
|
26
|
-
receiver = send_node.receiver
|
27
|
-
return false unless receiver
|
28
|
-
|
29
|
-
receiver.source == 'Rails.application.routes' && send_node.method_name == :draw
|
30
|
-
end
|
31
|
-
|
32
|
-
def collect_routes(routes_block)
|
33
|
-
collector = RouteCollector.new
|
34
|
-
body = routes_block.body
|
35
|
-
collector.collect(body) if body
|
36
|
-
collector.routes.sort_by { |route| route[:line] }
|
23
|
+
def check_routes(routes)
|
24
|
+
check_for_scattered_routes(routes)
|
37
25
|
end
|
38
26
|
|
39
27
|
def check_for_scattered_routes(routes)
|
@@ -1,39 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../shared/
|
3
|
+
require_relative '../shared/route_helper'
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Rails
|
8
8
|
class RouteRootPosition < RuboCop::Cop::Base
|
9
|
+
include RouteHelper
|
10
|
+
|
9
11
|
MSG = 'The root route should be positioned at the top of routes within the same namespace level.'
|
10
12
|
|
11
13
|
def on_block(node)
|
12
|
-
|
13
|
-
|
14
|
-
routes = collect_routes(node)
|
15
|
-
return if routes.empty?
|
14
|
+
process_route_block(node)
|
15
|
+
end
|
16
16
|
|
17
|
-
|
17
|
+
def investigate(processed_source)
|
18
|
+
process_route_file(processed_source)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
send_node = node.send_node
|
26
|
-
receiver = send_node.receiver
|
27
|
-
return false unless receiver
|
28
|
-
|
29
|
-
receiver.source == 'Rails.application.routes' && send_node.method_name == :draw
|
23
|
+
def minimum_routes_for_check
|
24
|
+
0
|
30
25
|
end
|
31
26
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
collector.routes.sort_by { |route| route[:line] }
|
27
|
+
def check_routes(routes)
|
28
|
+
return if routes.empty?
|
29
|
+
|
30
|
+
check_root_position(routes)
|
37
31
|
end
|
38
32
|
|
39
33
|
def check_root_position(routes)
|
@@ -1,39 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../shared/
|
3
|
+
require_relative '../shared/route_helper'
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Rails
|
8
8
|
class RouteSeparation < RuboCop::Cop::Base
|
9
|
+
include RouteHelper
|
10
|
+
|
9
11
|
MSG = 'Separate different route types with a blank line.'
|
10
12
|
|
11
13
|
def on_block(node)
|
12
|
-
|
13
|
-
|
14
|
-
routes = collect_routes(node)
|
15
|
-
return if routes.size < 2
|
14
|
+
process_route_block(node)
|
15
|
+
end
|
16
16
|
|
17
|
-
|
17
|
+
def investigate(processed_source)
|
18
|
+
process_route_file(processed_source)
|
18
19
|
end
|
19
20
|
|
20
21
|
private
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
send_node = node.send_node
|
26
|
-
receiver = send_node.receiver
|
27
|
-
return false unless receiver
|
28
|
-
|
29
|
-
receiver.source == 'Rails.application.routes' && send_node.method_name == :draw
|
30
|
-
end
|
31
|
-
|
32
|
-
def collect_routes(routes_block)
|
33
|
-
collector = RouteCollector.new
|
34
|
-
body = routes_block.body
|
35
|
-
collector.collect(body) if body
|
36
|
-
collector.routes.sort_by { |route| route[:line] }
|
23
|
+
def check_routes(routes)
|
24
|
+
check_route_separation(routes)
|
37
25
|
end
|
38
26
|
|
39
27
|
def check_route_separation(routes)
|
@@ -1,40 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '../shared/
|
3
|
+
require_relative '../shared/route_helper'
|
4
4
|
|
5
5
|
module RuboCop
|
6
6
|
module Cop
|
7
7
|
module Rails
|
8
8
|
class RouteSorting < RuboCop::Cop::Base
|
9
|
+
include RouteHelper
|
10
|
+
|
9
11
|
MSG = 'Sort routes of the same type alphabetically within the same namespace level. ' \
|
10
12
|
'Expected order: %<expected>s.'
|
11
13
|
|
12
14
|
def on_block(node)
|
13
|
-
|
14
|
-
|
15
|
-
routes = collect_routes(node)
|
16
|
-
return if routes.size < 2
|
15
|
+
process_route_block(node)
|
16
|
+
end
|
17
17
|
|
18
|
-
|
18
|
+
def investigate(processed_source)
|
19
|
+
process_route_file(processed_source)
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
22
23
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
send_node = node.send_node
|
27
|
-
receiver = send_node.receiver
|
28
|
-
return false unless receiver
|
29
|
-
|
30
|
-
receiver.source == 'Rails.application.routes' && send_node.method_name == :draw
|
31
|
-
end
|
32
|
-
|
33
|
-
def collect_routes(routes_block)
|
34
|
-
collector = RouteCollector.new
|
35
|
-
body = routes_block.body
|
36
|
-
collector.collect(body) if body
|
37
|
-
collector.routes.sort_by { |route| route[:line] }
|
24
|
+
def check_routes(routes)
|
25
|
+
check_route_sorting(routes)
|
38
26
|
end
|
39
27
|
|
40
28
|
def check_route_sorting(routes)
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Rails
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
6
7
|
class CollectionContext
|
7
8
|
ROUTE_CATEGORIES = {
|
8
9
|
simple: [:get, :post, :put, :patch, :delete, :head, :options, :match, :root],
|
@@ -12,6 +13,7 @@ module RuboCop
|
|
12
13
|
}.freeze
|
13
14
|
|
14
15
|
ALL_ROUTE_METHODS = ROUTE_CATEGORIES.values.flatten.freeze
|
16
|
+
SCOPE_OPTIONS = [:module, :path].freeze
|
15
17
|
|
16
18
|
def initialize(collector, namespace_level, namespace_path = [])
|
17
19
|
@collector = collector
|
@@ -44,18 +46,31 @@ module RuboCop
|
|
44
46
|
return unless send_node.send_type? && route_method?(send_node)
|
45
47
|
|
46
48
|
add_route_if_valid(send_node)
|
49
|
+
process_nested_context(node)
|
50
|
+
end
|
47
51
|
|
52
|
+
def process_nested_context(node)
|
48
53
|
body = node.body
|
49
54
|
return unless body
|
50
55
|
|
56
|
+
new_namespace_path = build_namespace_path(node.send_node)
|
57
|
+
nested_context = CollectionContext.new(@collector, @namespace_level + 1, new_namespace_path)
|
58
|
+
nested_context.process_node(body)
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_namespace_path(send_node)
|
51
62
|
new_namespace_path = @namespace_path.dup
|
52
|
-
|
63
|
+
|
64
|
+
case send_node.method_name
|
65
|
+
when :namespace
|
53
66
|
namespace_name = extract_namespace_name(send_node)
|
54
67
|
new_namespace_path << namespace_name if namespace_name
|
68
|
+
when :scope
|
69
|
+
scope_name = extract_scope_name(send_node)
|
70
|
+
new_namespace_path << scope_name if scope_name
|
55
71
|
end
|
56
72
|
|
57
|
-
|
58
|
-
nested_context.process_node(body)
|
73
|
+
new_namespace_path
|
59
74
|
end
|
60
75
|
|
61
76
|
def extract_namespace_name(node)
|
@@ -65,6 +80,47 @@ module RuboCop
|
|
65
80
|
'unknown'
|
66
81
|
end
|
67
82
|
|
83
|
+
def extract_scope_name(node)
|
84
|
+
scope_name = extract_scope_option_value(node)
|
85
|
+
return scope_name if scope_name
|
86
|
+
|
87
|
+
# If no module/path specified, use first argument if it's a symbol/string
|
88
|
+
first_arg = node.arguments.first
|
89
|
+
return first_arg.value.to_s if first_arg&.sym_type? || first_arg&.str_type?
|
90
|
+
|
91
|
+
'scope'
|
92
|
+
end
|
93
|
+
|
94
|
+
def extract_scope_option_value(node)
|
95
|
+
node.arguments.each do |arg|
|
96
|
+
next unless arg.hash_type?
|
97
|
+
|
98
|
+
scope_value = find_scope_option_in_hash(arg)
|
99
|
+
return scope_value if scope_value
|
100
|
+
end
|
101
|
+
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
def find_scope_option_in_hash(hash_arg)
|
106
|
+
hash_arg.pairs.each do |pair|
|
107
|
+
value = extract_scope_value_from_pair(pair)
|
108
|
+
return value if value
|
109
|
+
end
|
110
|
+
|
111
|
+
nil
|
112
|
+
end
|
113
|
+
|
114
|
+
def extract_scope_value_from_pair(pair)
|
115
|
+
key = pair.key
|
116
|
+
return nil unless key&.sym_type? && SCOPE_OPTIONS.include?(key.value)
|
117
|
+
|
118
|
+
value = pair.value
|
119
|
+
return value.value.to_s if value&.sym_type? || value&.str_type?
|
120
|
+
|
121
|
+
nil
|
122
|
+
end
|
123
|
+
|
68
124
|
def route_method?(node)
|
69
125
|
return false unless node.send_type?
|
70
126
|
|
@@ -134,6 +190,7 @@ module RuboCop
|
|
134
190
|
:other
|
135
191
|
end
|
136
192
|
end
|
193
|
+
# rubocop:enable Metrics/ClassLength
|
137
194
|
end
|
138
195
|
end
|
139
196
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'route_collector'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Rails
|
8
|
+
module RouteHelper
|
9
|
+
def route_file?
|
10
|
+
processed_source.file_path&.end_with?('routes.rb')
|
11
|
+
end
|
12
|
+
|
13
|
+
def route_block?(node)
|
14
|
+
return false unless node.block_type?
|
15
|
+
|
16
|
+
send_node = node.send_node
|
17
|
+
return false unless send_node.send_type?
|
18
|
+
return true if send_node.receiver&.source == 'Rails.application.routes' && send_node.method_name == :draw
|
19
|
+
return false unless route_file?
|
20
|
+
|
21
|
+
[:scope, :namespace, :concern].include?(send_node.method_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
def collect_routes(routes_block)
|
25
|
+
collector = RouteCollector.new
|
26
|
+
body = routes_block.body
|
27
|
+
collector.collect(body) if body
|
28
|
+
collector.routes.sort_by { |route| route[:line] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def collect_routes_from_file(ast_node)
|
32
|
+
collector = RouteCollector.new
|
33
|
+
collector.collect(ast_node) if ast_node
|
34
|
+
collector.routes.sort_by { |route| route[:line] }
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_route_block(node)
|
38
|
+
return unless route_block?(node)
|
39
|
+
|
40
|
+
routes = collect_routes(node)
|
41
|
+
return if routes.size < minimum_routes_for_check
|
42
|
+
|
43
|
+
check_routes(routes)
|
44
|
+
end
|
45
|
+
|
46
|
+
def process_route_file(processed_source)
|
47
|
+
return unless route_file?
|
48
|
+
return if processed_source.ast.nil?
|
49
|
+
|
50
|
+
routes = collect_routes_from_file(processed_source.ast)
|
51
|
+
return if routes.size < minimum_routes_for_check
|
52
|
+
|
53
|
+
check_routes(routes)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def minimum_routes_for_check
|
59
|
+
2
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_routes(routes)
|
63
|
+
raise NotImplementedError, 'Subclasses must implement check_routes method'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop-nueca
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tien
|
@@ -160,6 +160,7 @@ files:
|
|
160
160
|
- lib/rubocop/cop/rails/time_zone_today.rb
|
161
161
|
- lib/rubocop/cop/shared/collection_context.rb
|
162
162
|
- lib/rubocop/cop/shared/route_collector.rb
|
163
|
+
- lib/rubocop/cop/shared/route_helper.rb
|
163
164
|
- lib/rubocop/nueca/plugin.rb
|
164
165
|
- lib/rubocop/nueca/version.rb
|
165
166
|
homepage: https://github.com/tieeeeen1994/rubocop-nueca
|