rails-route-checker 0.2.3 → 0.2.4
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 +5 -5
- data/lib/rails-route-checker/app_interface.rb +21 -7
- data/lib/rails-route-checker/loaded_app.rb +13 -7
- data/lib/rails-route-checker/parsers/erb_parser.rb +23 -17
- data/lib/rails-route-checker/parsers/haml_parser/document.rb +3 -4
- data/lib/rails-route-checker/parsers/haml_parser/ruby_extractor.rb +1 -0
- data/lib/rails-route-checker/parsers/haml_parser/tree/tag_node.rb +1 -1
- data/lib/rails-route-checker/parsers/loader.rb +2 -0
- data/lib/rails-route-checker/parsers/ruby_parser.rb +40 -26
- data/lib/rails-route-checker/version.rb +1 -1
- data/rails-route-checker.gemspec +2 -3
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3604e0534bad28fed12e85404774e01507b811767f3b08606963d8db34eeffd1
|
4
|
+
data.tar.gz: 33ac9a2201800a8034242cbee920b693b8dd4772a7b44d4e5834df06f7977e5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b82d44db72af06feda748069d51b060e403559e73ddbe0d8589ff551b086e7477868c9205ee232ae8fe2e81499083aedef70e0c0d572be07a6ee6ca75f0eb094
|
7
|
+
data.tar.gz: baca9417795fb9ad33b776a9e011951f5c78ba5296b6fe189d0a31b94c8787fdeff529c8a899a513f4132899d1b460179d7c58c48d6a6ebec8c8591a34ad5912
|
@@ -10,12 +10,7 @@ module RailsRouteChecker
|
|
10
10
|
action = r.requirements[:action]
|
11
11
|
|
12
12
|
next if options[:ignored_controllers].include?(controller)
|
13
|
-
|
14
|
-
if controller_information.key?(controller)
|
15
|
-
info = controller_information[controller]
|
16
|
-
next if info[:actions].include?(action)
|
17
|
-
next if info[:lookup_context] && info[:lookup_context].template_exists?("#{controller}/#{action}")
|
18
|
-
end
|
13
|
+
next if controller_has_action?(controller, action)
|
19
14
|
|
20
15
|
{
|
21
16
|
controller: controller,
|
@@ -42,6 +37,16 @@ module RailsRouteChecker
|
|
42
37
|
end
|
43
38
|
end
|
44
39
|
|
40
|
+
def controller_has_action?(controller, action)
|
41
|
+
return false unless controller_information.key?(controller)
|
42
|
+
|
43
|
+
info = controller_information[controller]
|
44
|
+
return true if info[:actions].include?(action)
|
45
|
+
return true if info[:lookup_context] && info[:lookup_context].template_exists?("#{controller}/#{action}")
|
46
|
+
|
47
|
+
false
|
48
|
+
end
|
49
|
+
|
45
50
|
def generate_undef_view_path_calls
|
46
51
|
generate_undef_view_path_calls_erb + generate_undef_view_path_calls_haml
|
47
52
|
end
|
@@ -59,6 +64,7 @@ module RailsRouteChecker
|
|
59
64
|
filter = lambda do |path_or_url|
|
60
65
|
return false if match_in_whitelist?(filename, path_or_url)
|
61
66
|
return false if match_defined_in_view?(controller, path_or_url)
|
67
|
+
|
62
68
|
true
|
63
69
|
end
|
64
70
|
|
@@ -85,6 +91,7 @@ module RailsRouteChecker
|
|
85
91
|
filter = lambda do |path_or_url|
|
86
92
|
return false if match_in_whitelist?(filename, path_or_url)
|
87
93
|
return false if match_defined_in_view?(controller, path_or_url)
|
94
|
+
|
88
95
|
true
|
89
96
|
end
|
90
97
|
|
@@ -105,6 +112,7 @@ module RailsRouteChecker
|
|
105
112
|
filter = lambda do |path_or_url|
|
106
113
|
return false if match_in_whitelist?(filename, path_or_url)
|
107
114
|
return false if match_defined_in_ruby?(controller, path_or_url)
|
115
|
+
|
108
116
|
return true
|
109
117
|
end
|
110
118
|
|
@@ -115,18 +123,21 @@ module RailsRouteChecker
|
|
115
123
|
def match_in_whitelist?(filename, path_or_url)
|
116
124
|
possible_route_name = path_or_url.sub(/_(?:url|path)$/, '')
|
117
125
|
return true if options[:ignored_paths].include?(possible_route_name)
|
126
|
+
|
118
127
|
(options[:ignored_path_whitelist][filename] || []).include?(path_or_url)
|
119
128
|
end
|
120
129
|
|
121
130
|
def match_defined_in_view?(controller, path_or_url)
|
122
131
|
possible_route_name = path_or_url.sub(/_(?:url|path)$/, '')
|
123
132
|
return true if loaded_app.all_route_names.include?(possible_route_name)
|
133
|
+
|
124
134
|
controller && controller[:helpers].include?(path_or_url)
|
125
135
|
end
|
126
136
|
|
127
137
|
def match_defined_in_ruby?(controller, path_or_url)
|
128
138
|
possible_route_name = path_or_url.sub(/_(?:url|path)$/, '')
|
129
139
|
return true if loaded_app.all_route_names.include?(possible_route_name)
|
140
|
+
|
130
141
|
controller && controller[:instance_methods].include?(path_or_url)
|
131
142
|
end
|
132
143
|
|
@@ -137,6 +148,7 @@ module RailsRouteChecker
|
|
137
148
|
while possible_controller_path.any?
|
138
149
|
controller_name = possible_controller_path.join('/')
|
139
150
|
return controller_information[controller_name] if controller_exists?(controller_name)
|
151
|
+
|
140
152
|
possible_controller_path = possible_controller_path[0..-2]
|
141
153
|
end
|
142
154
|
controller_information['application']
|
@@ -145,12 +157,14 @@ module RailsRouteChecker
|
|
145
157
|
def controller_from_ruby_file(filename)
|
146
158
|
controller_name = (filename.match(%r{app/controllers/(.*)_controller.rb}) || [])[1]
|
147
159
|
return controller_information[controller_name] if controller_exists?(controller_name)
|
160
|
+
|
148
161
|
controller_information['application']
|
149
162
|
end
|
150
163
|
|
151
164
|
def controller_exists?(controller_name)
|
152
165
|
return false unless controller_name
|
153
|
-
|
166
|
+
|
167
|
+
File.exist?("app/controllers/#{controller_name}_controller.rb")
|
154
168
|
end
|
155
169
|
end
|
156
170
|
end
|
@@ -40,18 +40,13 @@ module RailsRouteChecker
|
|
40
40
|
@controller_information ||= ActionController::Base.descendants.map do |controller|
|
41
41
|
next if controller.controller_path.start_with?('rails/')
|
42
42
|
|
43
|
-
instance_methods = (controller.instance_methods.map(&:to_s) + controller.private_instance_methods.map(&:to_s))
|
44
|
-
lookup_context = ActionView::LookupContext.new(
|
45
|
-
controller._view_paths, {}, controller._prefixes
|
46
|
-
) if controller.instance_methods.include?(:default_render)
|
47
|
-
|
48
43
|
[
|
49
44
|
controller.controller_path,
|
50
45
|
{
|
51
46
|
helpers: controller.helpers.methods.map(&:to_s),
|
52
47
|
actions: controller.action_methods.to_a,
|
53
|
-
instance_methods: instance_methods
|
54
|
-
lookup_context: lookup_context
|
48
|
+
instance_methods: instance_methods(controller),
|
49
|
+
lookup_context: lookup_context(controller)
|
55
50
|
}
|
56
51
|
]
|
57
52
|
end.compact.to_h
|
@@ -61,6 +56,16 @@ module RailsRouteChecker
|
|
61
56
|
|
62
57
|
attr_reader :app
|
63
58
|
|
59
|
+
def lookup_context(controller)
|
60
|
+
return nil unless controller.instance_methods.include?(:default_render)
|
61
|
+
|
62
|
+
ActionView::LookupContext.new(controller._view_paths, {}, controller._prefixes)
|
63
|
+
end
|
64
|
+
|
65
|
+
def instance_methods(controller)
|
66
|
+
(controller.instance_methods.map(&:to_s) + controller.private_instance_methods.map(&:to_s)).compact.uniq
|
67
|
+
end
|
68
|
+
|
64
69
|
def suppress_output
|
65
70
|
begin
|
66
71
|
original_stderr = $stderr.clone
|
@@ -106,6 +111,7 @@ module RailsRouteChecker
|
|
106
111
|
action = route.requirements[:action]
|
107
112
|
return true unless controller && action
|
108
113
|
return true if controller.start_with?('rails/')
|
114
|
+
|
109
115
|
false
|
110
116
|
end
|
111
117
|
end
|
@@ -5,23 +5,7 @@ module RailsRouteChecker
|
|
5
5
|
def run(filename, **opts)
|
6
6
|
file_source = opts[:source] || File.read(filename)
|
7
7
|
|
8
|
-
|
9
|
-
ruby_source = ''
|
10
|
-
source_map = {}
|
11
|
-
|
12
|
-
file_source.split("\n").each_with_index do |line, line_num|
|
13
|
-
ruby_lines = process_line(line)
|
14
|
-
next unless ruby_lines.any?
|
15
|
-
|
16
|
-
ruby_source += ruby_lines.join("\n") + "\n"
|
17
|
-
ruby_lines.length.times do |i|
|
18
|
-
source_map[next_ruby_source_line_num + i] = line_num + 1
|
19
|
-
end
|
20
|
-
next_ruby_source_line_num += ruby_lines.length
|
21
|
-
end
|
22
|
-
|
23
|
-
opts[:source] = ruby_source
|
24
|
-
opts[:source_map] = source_map
|
8
|
+
opts.merge!(process_file(file_source))
|
25
9
|
|
26
10
|
RailsRouteChecker::Parsers::RubyParser.run(filename, **opts)
|
27
11
|
end
|
@@ -46,6 +30,28 @@ module RailsRouteChecker
|
|
46
30
|
end
|
47
31
|
ruby_lines
|
48
32
|
end
|
33
|
+
|
34
|
+
def process_file(source)
|
35
|
+
next_ruby_source_line_num = 1
|
36
|
+
ruby_source = ''
|
37
|
+
source_map = {}
|
38
|
+
|
39
|
+
source.split("\n").each_with_index do |line, line_num|
|
40
|
+
ruby_lines = process_line(line)
|
41
|
+
next unless ruby_lines.any?
|
42
|
+
|
43
|
+
ruby_source += ruby_lines.join("\n") + "\n"
|
44
|
+
ruby_lines.length.times do |i|
|
45
|
+
source_map[next_ruby_source_line_num + i] = line_num + 1
|
46
|
+
end
|
47
|
+
next_ruby_source_line_num += ruby_lines.length
|
48
|
+
end
|
49
|
+
|
50
|
+
{
|
51
|
+
source: ruby_source,
|
52
|
+
source_map: source_map
|
53
|
+
}
|
54
|
+
end
|
49
55
|
end
|
50
56
|
end
|
51
57
|
end
|
@@ -9,8 +9,9 @@ module RailsRouteChecker
|
|
9
9
|
@source_lines = @source.split(/\r\n|\r|\n/)
|
10
10
|
|
11
11
|
version = Gem::Version.new(Haml::VERSION).approximate_recommendation
|
12
|
+
options = Haml::Options.new
|
12
13
|
original_tree = case version
|
13
|
-
when '~> 4.0', '~> 4.1' then Haml::Parser.new(@source,
|
14
|
+
when '~> 4.0', '~> 4.1' then Haml::Parser.new(@source, options).parse
|
14
15
|
when '~> 5.0' then Haml::Parser.new(options).call(@source)
|
15
16
|
else raise "Cannot handle Haml version: #{version}"
|
16
17
|
end
|
@@ -21,9 +22,7 @@ module RailsRouteChecker
|
|
21
22
|
private
|
22
23
|
|
23
24
|
def process_tree(original_tree)
|
24
|
-
if Gem::Requirement.new('~> 4.0.0').satisfied_by?(Gem.loaded_specs['haml'].version)
|
25
|
-
original_tree.children.pop
|
26
|
-
end
|
25
|
+
original_tree.children.pop if Gem::Requirement.new('~> 4.0.0').satisfied_by?(Gem.loaded_specs['haml'].version)
|
27
26
|
|
28
27
|
convert_tree(original_tree)
|
29
28
|
end
|
@@ -18,7 +18,7 @@ module RailsRouteChecker
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def attributes_source
|
21
|
-
@attr_source ||=
|
21
|
+
@attr_source ||= # rubocop:disable Naming/MemoizedInstanceVariableName
|
22
22
|
begin
|
23
23
|
_explicit_tag, static_attrs, rest =
|
24
24
|
source_code.scan(/\A\s*(%[-:\w]+)?([-:\w\.\#]*)(.*)/m)[0]
|
@@ -21,6 +21,7 @@ module RailsRouteChecker
|
|
21
21
|
|
22
22
|
def haml_available?
|
23
23
|
return @haml_available if defined?(@haml_available)
|
24
|
+
|
24
25
|
@haml_available = gem_installed?('haml')
|
25
26
|
end
|
26
27
|
|
@@ -46,6 +47,7 @@ module RailsRouteChecker
|
|
46
47
|
def if_unloaded(parser)
|
47
48
|
@loaded_parsers ||= {}
|
48
49
|
return false if @loaded_parsers[parser]
|
50
|
+
|
49
51
|
yield
|
50
52
|
@loaded_parsers[parser] = true
|
51
53
|
end
|
@@ -6,15 +6,16 @@ module RailsRouteChecker
|
|
6
6
|
class << self
|
7
7
|
def run(filename, **opts)
|
8
8
|
file_source = opts[:source] || File.read(filename)
|
9
|
+
process_file(filename, file_source, opts)
|
10
|
+
end
|
9
11
|
|
10
|
-
|
12
|
+
private
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
next unless %i[vcall fcall].include?(scope[-2])
|
15
|
-
next unless scope[-1] == :@ident
|
16
|
-
next unless item.end_with?('_path', '_url')
|
14
|
+
def process_file(filename, source, opts)
|
15
|
+
items = []
|
17
16
|
|
17
|
+
deep_iterator(Ripper.sexp(source)) do |item, extra_data|
|
18
|
+
next unless item_is_url_call?(item, extra_data)
|
18
19
|
next if opts[:filter].respond_to?(:call) && !opts[:filter].call(item)
|
19
20
|
|
20
21
|
line = extra_data[:position][0]
|
@@ -26,30 +27,43 @@ module RailsRouteChecker
|
|
26
27
|
items
|
27
28
|
end
|
28
29
|
|
29
|
-
|
30
|
+
def item_is_url_call?(item, extra_data)
|
31
|
+
scope = extra_data[:scope]
|
32
|
+
return false unless %i[vcall fcall].include?(scope[-2])
|
33
|
+
return false unless scope[-1] == :@ident
|
34
|
+
return false unless item.end_with?('_path', '_url')
|
35
|
+
|
36
|
+
true
|
37
|
+
end
|
30
38
|
|
31
39
|
def deep_iterator(list, current_scope = [], current_line_num = [], &block)
|
32
|
-
if list.is_a?(Array)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
list[1..-1].each do |item|
|
42
|
-
deep_iterator(item, current_scope, current_line_num, &block)
|
43
|
-
end
|
44
|
-
current_scope.pop
|
45
|
-
else
|
46
|
-
list.each do |item|
|
47
|
-
deep_iterator(item, current_scope, current_line_num, &block)
|
48
|
-
end
|
40
|
+
return deep_iterate_array(list, current_scope, current_line_num, &block) if list.is_a?(Array)
|
41
|
+
|
42
|
+
yield(list, { scope: current_scope, position: current_line_num }) unless list.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def deep_iterate_array(list, current_scope, current_line_num, &block)
|
46
|
+
unless list[0].is_a?(Symbol)
|
47
|
+
list.each do |item|
|
48
|
+
deep_iterator(item, current_scope, current_line_num, &block)
|
49
49
|
end
|
50
|
-
|
51
|
-
|
50
|
+
return
|
51
|
+
end
|
52
|
+
|
53
|
+
current_scope << list[0]
|
54
|
+
|
55
|
+
last_list_item = list[-1]
|
56
|
+
if last_list_item.is_a?(Array) &&
|
57
|
+
last_list_item.length == 2 &&
|
58
|
+
last_list_item.all? { |item| item.is_a?(Integer) }
|
59
|
+
current_line_num = last_list_item
|
60
|
+
list = list[0..-2]
|
61
|
+
end
|
62
|
+
|
63
|
+
list[1..-1].each do |item|
|
64
|
+
deep_iterator(item, current_scope, current_line_num, &block)
|
52
65
|
end
|
66
|
+
current_scope.pop
|
53
67
|
end
|
54
68
|
end
|
55
69
|
end
|
data/rails-route-checker.gemspec
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'rails-route-checker/version'
|
5
4
|
|
@@ -24,5 +23,5 @@ Gem::Specification.new do |spec|
|
|
24
23
|
|
25
24
|
spec.add_development_dependency 'bundler', '~> 1.15'
|
26
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
26
|
+
spec.add_development_dependency 'rubocop', '~> 0.60'
|
28
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-route-checker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dave Allie
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
47
|
+
version: '0.60'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
54
|
+
version: '0.60'
|
55
55
|
description: A linting tool that helps you find any routes defined in your routes.rb
|
56
56
|
file that don't have a corresponding controller action, and find any _path or _url
|
57
57
|
calls that don't have a corresponding route in the routes.rb file.
|
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
105
|
rubyforge_project:
|
106
|
-
rubygems_version: 2.
|
106
|
+
rubygems_version: 2.7.7
|
107
107
|
signing_key:
|
108
108
|
specification_version: 4
|
109
109
|
summary: A linting tool for your Rails routes
|