rails-route-checker 0.2.3 → 0.2.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|