rubocop-nueca 1.0.0
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 +7 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/LICENSE.txt +21 -0
- data/README.md +26 -0
- data/config/default.yml +106 -0
- data/lib/rubocop/cop/rails/date_time_conversion.rb +22 -0
- data/lib/rubocop/cop/rails/date_time_current.rb +23 -0
- data/lib/rubocop/cop/rails/migration_table_variable.rb +40 -0
- data/lib/rubocop/cop/rails/model_association_consistent_spacing.rb +71 -0
- data/lib/rubocop/cop/rails/model_association_grouping.rb +114 -0
- data/lib/rubocop/cop/rails/model_association_scattering.rb +97 -0
- data/lib/rubocop/cop/rails/model_association_separation.rb +92 -0
- data/lib/rubocop/cop/rails/model_association_sorting.rb +91 -0
- data/lib/rubocop/cop/rails/postgres_timestamp.rb +33 -0
- data/lib/rubocop/cop/rails/route_consistent_spacing.rb +64 -0
- data/lib/rubocop/cop/rails/route_grouping.rb +88 -0
- data/lib/rubocop/cop/rails/route_root_position.rb +103 -0
- data/lib/rubocop/cop/rails/route_separation.rb +84 -0
- data/lib/rubocop/cop/rails/route_sorting.rb +73 -0
- data/lib/rubocop/cop/rails/time_zone_today.rb +24 -0
- data/lib/rubocop/cop/shared/collection_context.rb +139 -0
- data/lib/rubocop/cop/shared/route_collector.rb +26 -0
- data/lib/rubocop/nueca/plugin.rb +30 -0
- data/lib/rubocop/nueca/version.rb +7 -0
- data/lib/rubocop-nueca.rb +12 -0
- metadata +185 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Rails
|
6
|
+
class CollectionContext
|
7
|
+
ROUTE_CATEGORIES = {
|
8
|
+
simple: [:get, :post, :put, :patch, :delete, :head, :options, :match, :root],
|
9
|
+
resource: [:resource, :resources],
|
10
|
+
namespace: [:namespace, :scope, :concern],
|
11
|
+
draw: [:draw]
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
ALL_ROUTE_METHODS = ROUTE_CATEGORIES.values.flatten.freeze
|
15
|
+
|
16
|
+
def initialize(collector, namespace_level, namespace_path = [])
|
17
|
+
@collector = collector
|
18
|
+
@namespace_level = namespace_level
|
19
|
+
@namespace_path = namespace_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_node(node)
|
23
|
+
case node.type
|
24
|
+
when :begin
|
25
|
+
node.children.each { |child| process_node(child) }
|
26
|
+
when :send
|
27
|
+
add_route_if_valid(node)
|
28
|
+
when :block
|
29
|
+
process_block(node)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def add_route_if_valid(node)
|
36
|
+
return unless route_method?(node)
|
37
|
+
|
38
|
+
route_info = build_route_info(node)
|
39
|
+
@collector.add_route(route_info) if route_info
|
40
|
+
end
|
41
|
+
|
42
|
+
def process_block(node)
|
43
|
+
send_node = node.send_node
|
44
|
+
return unless send_node.send_type? && route_method?(send_node)
|
45
|
+
|
46
|
+
add_route_if_valid(send_node)
|
47
|
+
|
48
|
+
body = node.body
|
49
|
+
return unless body
|
50
|
+
|
51
|
+
new_namespace_path = @namespace_path.dup
|
52
|
+
if send_node.method_name == :namespace
|
53
|
+
namespace_name = extract_namespace_name(send_node)
|
54
|
+
new_namespace_path << namespace_name if namespace_name
|
55
|
+
end
|
56
|
+
|
57
|
+
nested_context = CollectionContext.new(@collector, @namespace_level + 1, new_namespace_path)
|
58
|
+
nested_context.process_node(body)
|
59
|
+
end
|
60
|
+
|
61
|
+
def extract_namespace_name(node)
|
62
|
+
first_arg = node.arguments.first
|
63
|
+
return first_arg.value.to_s if first_arg&.sym_type? || first_arg&.str_type?
|
64
|
+
|
65
|
+
'unknown'
|
66
|
+
end
|
67
|
+
|
68
|
+
def route_method?(node)
|
69
|
+
return false unless node.send_type?
|
70
|
+
|
71
|
+
receiver = node.receiver
|
72
|
+
return false if receiver && !simple_receiver?(receiver)
|
73
|
+
|
74
|
+
ALL_ROUTE_METHODS.include?(node.method_name)
|
75
|
+
end
|
76
|
+
|
77
|
+
def simple_receiver?(receiver)
|
78
|
+
receiver.nil? || receiver.send_type?
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_route_info(node)
|
82
|
+
method_name = node.method_name
|
83
|
+
route_name = extract_route_name(node)
|
84
|
+
return nil unless route_name
|
85
|
+
|
86
|
+
source_range = node.source_range
|
87
|
+
{
|
88
|
+
node: node,
|
89
|
+
method: method_name,
|
90
|
+
name: route_name,
|
91
|
+
line: source_range.line,
|
92
|
+
end_line: source_range.last_line,
|
93
|
+
namespace_level: @namespace_level,
|
94
|
+
namespace_path: @namespace_path.dup,
|
95
|
+
type: categorize_route_method(method_name)
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def extract_route_name(node)
|
100
|
+
method_name = node.method_name
|
101
|
+
first_arg = node.arguments.first
|
102
|
+
|
103
|
+
case method_name
|
104
|
+
when :root then 'root'
|
105
|
+
when :draw then extract_symbol_or_default(first_arg, 'draw')
|
106
|
+
when *ROUTE_CATEGORIES[:simple] then extract_simple_route_name(first_arg)
|
107
|
+
when *ROUTE_CATEGORIES[:resource], *ROUTE_CATEGORIES[:namespace]
|
108
|
+
extract_symbol_or_default(first_arg, 'unknown')
|
109
|
+
else
|
110
|
+
'unknown'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def extract_symbol_or_default(arg, default)
|
115
|
+
arg&.sym_type? ? arg.value.to_s : default
|
116
|
+
end
|
117
|
+
|
118
|
+
def extract_simple_route_name(first_arg)
|
119
|
+
return first_arg.value.to_s if first_arg&.str_type?
|
120
|
+
return extract_hash_route_name(first_arg) if first_arg&.hash_type?
|
121
|
+
|
122
|
+
'unknown'
|
123
|
+
end
|
124
|
+
|
125
|
+
def extract_hash_route_name(hash_arg)
|
126
|
+
first_pair = hash_arg.pairs.first
|
127
|
+
first_pair&.key&.value&.to_s || 'unknown' # rubocop:disable Style/SafeNavigationChainLength
|
128
|
+
end
|
129
|
+
|
130
|
+
def categorize_route_method(method_name)
|
131
|
+
ROUTE_CATEGORIES.each do |category, methods|
|
132
|
+
return category if methods.include?(method_name)
|
133
|
+
end
|
134
|
+
:other
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'collection_context'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Rails
|
8
|
+
class RouteCollector
|
9
|
+
attr_reader :routes
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@routes = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def collect(node, namespace_level = 0, namespace_path = [])
|
16
|
+
context = CollectionContext.new(self, namespace_level, namespace_path)
|
17
|
+
context.process_node(node)
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_route(route_info)
|
21
|
+
@routes << route_info
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'lint_roller'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Nueca
|
7
|
+
class Plugin < LintRoller::Plugin
|
8
|
+
def about
|
9
|
+
LintRoller::About.new(
|
10
|
+
name: 'rubocop-nueca',
|
11
|
+
version: VERSION,
|
12
|
+
homepage: 'https://github.com/tieeeeen1994/rubocop-nueca',
|
13
|
+
description: 'Custom RuboCop rules for Nueca according to culture.'
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def supported?(context)
|
18
|
+
context.engine == :rubocop
|
19
|
+
end
|
20
|
+
|
21
|
+
def rules(_context)
|
22
|
+
LintRoller::Rules.new(
|
23
|
+
type: :path,
|
24
|
+
config_format: :rubocop,
|
25
|
+
value: Pathname.new(__dir__).join('../../../config/default.yml')
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'rubocop/nueca/version'
|
4
|
+
require 'rubocop'
|
5
|
+
|
6
|
+
# Load the plugin
|
7
|
+
require_relative 'rubocop/nueca/plugin'
|
8
|
+
|
9
|
+
# Load all custom Rails cops
|
10
|
+
Dir[File.join(__dir__, 'rubocop', 'cop', 'rails', '*.rb')].each do |file|
|
11
|
+
require file
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,185 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rubocop-nueca
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tien
|
8
|
+
bindir: exe
|
9
|
+
cert_chain: []
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
|
+
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: lint_roller
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '1.1'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - "~>"
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '1.1'
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: rubocop
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.72'
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 1.72.0
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "~>"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '1.72'
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.72.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rubocop-capybara
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - "~>"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.22'
|
53
|
+
type: :runtime
|
54
|
+
prerelease: false
|
55
|
+
version_requirements: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '2.22'
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: rubocop-factory_bot
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '2.27'
|
67
|
+
type: :runtime
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '2.27'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: rubocop-performance
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '1.25'
|
81
|
+
type: :runtime
|
82
|
+
prerelease: false
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.25'
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: rubocop-rails
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '2.33'
|
95
|
+
type: :runtime
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '2.33'
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rubocop-rspec
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '3.7'
|
109
|
+
type: :runtime
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '3.7'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: rubocop-rspec_rails
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '2.31'
|
123
|
+
type: :runtime
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '2.31'
|
130
|
+
email:
|
131
|
+
- tieeeeen1994@gmail.com
|
132
|
+
executables: []
|
133
|
+
extensions: []
|
134
|
+
extra_rdoc_files: []
|
135
|
+
files:
|
136
|
+
- CODE_OF_CONDUCT.md
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- config/default.yml
|
140
|
+
- lib/rubocop-nueca.rb
|
141
|
+
- lib/rubocop/cop/rails/date_time_conversion.rb
|
142
|
+
- lib/rubocop/cop/rails/date_time_current.rb
|
143
|
+
- lib/rubocop/cop/rails/migration_table_variable.rb
|
144
|
+
- lib/rubocop/cop/rails/model_association_consistent_spacing.rb
|
145
|
+
- lib/rubocop/cop/rails/model_association_grouping.rb
|
146
|
+
- lib/rubocop/cop/rails/model_association_scattering.rb
|
147
|
+
- lib/rubocop/cop/rails/model_association_separation.rb
|
148
|
+
- lib/rubocop/cop/rails/model_association_sorting.rb
|
149
|
+
- lib/rubocop/cop/rails/postgres_timestamp.rb
|
150
|
+
- lib/rubocop/cop/rails/route_consistent_spacing.rb
|
151
|
+
- lib/rubocop/cop/rails/route_grouping.rb
|
152
|
+
- lib/rubocop/cop/rails/route_root_position.rb
|
153
|
+
- lib/rubocop/cop/rails/route_separation.rb
|
154
|
+
- lib/rubocop/cop/rails/route_sorting.rb
|
155
|
+
- lib/rubocop/cop/rails/time_zone_today.rb
|
156
|
+
- lib/rubocop/cop/shared/collection_context.rb
|
157
|
+
- lib/rubocop/cop/shared/route_collector.rb
|
158
|
+
- lib/rubocop/nueca/plugin.rb
|
159
|
+
- lib/rubocop/nueca/version.rb
|
160
|
+
homepage: https://github.com/tieeeeen1994/rubocop-nueca
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata:
|
164
|
+
source_code_uri: https://github.com/tieeeeen1994/rubocop-nueca
|
165
|
+
rubygems_mfa_required: 'true'
|
166
|
+
default_lint_roller_plugin: RuboCop::Nueca::Plugin
|
167
|
+
rubocop_extension: 'true'
|
168
|
+
rdoc_options: []
|
169
|
+
require_paths:
|
170
|
+
- lib
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: 3.2.0
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
requirements: []
|
182
|
+
rubygems_version: 3.6.9
|
183
|
+
specification_version: 4
|
184
|
+
summary: This enforces custom rules for Nueca according to culture.
|
185
|
+
test_files: []
|