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.
@@ -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,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Nueca
5
+ VERSION = '1.0.0'
6
+ end
7
+ 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: []