This repository has been archived by the owner on Jul 27, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 95
/
Copy pathunused_snippet.rb
85 lines (68 loc) · 2.33 KB
/
unused_snippet.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# frozen_string_literal: true
require "set"
module ThemeCheck
class UnusedSnippet < LiquidCheck
severity :suggestion
category :liquid
doc docs_url(__FILE__)
def initialize
@used_snippets = Set.new
end
def on_render(node)
if node.value.template_name_expr.is_a?(String)
@used_snippets << "snippets/#{node.value.template_name_expr}"
elsif might_have_a_block_as_variable_lookup?(node)
# We ignore this case, because that's a "proper" use case for
# the render tag with OS 2.0
# {% render block %} shouldn't turn off the UnusedSnippet check
else
# Can't reliably track unused snippets if an expression is used, ignore this check
@used_snippets.clear
ignore!
end
end
alias_method :on_include, :on_render
def on_end
missing_snippets.each do |theme_file|
add_offense("This snippet is not used", theme_file: theme_file) do |corrector|
corrector.remove_file(@theme.storage, theme_file.relative_path.to_s)
end
end
end
def missing_snippets
theme.snippets.reject { |t| @used_snippets.include?(t.name) }
end
private
# This function returns true when the render node passed might have a
# variable lookup that refers to a block as template_name_expr.
#
# e.g.
#
# {% for block in col %}
# {% render block %}
# {% endfor %}
#
# In this case, the `block` variable_lookup in the render tag might be
# a Block because col might be an array of blocks.
#
# @param node [Node]
def might_have_a_block_as_variable_lookup?(node)
return false unless node.type_name == :render
return false unless node.value.template_name_expr.is_a?(Liquid::VariableLookup)
name = node.value.template_name_expr.name
return false unless name.is_a?(String)
# We're going through all the parents of the nodes until we find
# a For node with variable_name === to the template_name_expr's name
find_parent(node.parent) do |parent_node|
next false unless parent_node.type_name == :for
parent_node.value.variable_name == name
end
end
# @param node [Node]
def find_parent(node, &pred)
return nil unless node
return node if yield node
find_parent(node.parent, &pred)
end
end
end