theme-check 1.5.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/theme-check.yml +12 -4
  3. data/CHANGELOG.md +37 -0
  4. data/docs/api/html_check.md +7 -7
  5. data/docs/api/liquid_check.md +10 -10
  6. data/docs/checks/convert_include_to_render.md +1 -1
  7. data/docs/checks/missing_enable_comment.md +1 -1
  8. data/lib/theme_check/analyzer.rb +46 -17
  9. data/lib/theme_check/asset_file.rb +13 -2
  10. data/lib/theme_check/check.rb +3 -3
  11. data/lib/theme_check/checks/asset_size_css.rb +15 -0
  12. data/lib/theme_check/checks/asset_size_css_stylesheet_tag.rb +18 -1
  13. data/lib/theme_check/checks/convert_include_to_render.rb +2 -1
  14. data/lib/theme_check/checks/html_parsing_error.rb +2 -2
  15. data/lib/theme_check/checks/matching_translations.rb +1 -1
  16. data/lib/theme_check/checks/missing_required_template_files.rb +21 -7
  17. data/lib/theme_check/checks/missing_template.rb +6 -6
  18. data/lib/theme_check/checks/nested_snippet.rb +2 -2
  19. data/lib/theme_check/checks/required_layout_theme_object.rb +2 -2
  20. data/lib/theme_check/checks/syntax_error.rb +5 -5
  21. data/lib/theme_check/checks/template_length.rb +2 -2
  22. data/lib/theme_check/checks/translation_key_exists.rb +3 -1
  23. data/lib/theme_check/checks/undefined_object.rb +7 -7
  24. data/lib/theme_check/checks/unused_assign.rb +4 -4
  25. data/lib/theme_check/checks/unused_snippet.rb +8 -6
  26. data/lib/theme_check/checks/valid_json.rb +1 -1
  27. data/lib/theme_check/checks.rb +4 -2
  28. data/lib/theme_check/cli.rb +7 -4
  29. data/lib/theme_check/corrector.rb +21 -12
  30. data/lib/theme_check/disabled_check.rb +3 -3
  31. data/lib/theme_check/disabled_checks.rb +9 -9
  32. data/lib/theme_check/file_system_storage.rb +7 -2
  33. data/lib/theme_check/html_node.rb +40 -32
  34. data/lib/theme_check/html_visitor.rb +24 -12
  35. data/lib/theme_check/in_memory_storage.rb +5 -1
  36. data/lib/theme_check/json_check.rb +2 -2
  37. data/lib/theme_check/json_file.rb +9 -4
  38. data/lib/theme_check/language_server/diagnostics_tracker.rb +8 -8
  39. data/lib/theme_check/language_server/handler.rb +88 -6
  40. data/lib/theme_check/language_server/messenger.rb +57 -0
  41. data/lib/theme_check/language_server/server.rb +105 -40
  42. data/lib/theme_check/language_server.rb +1 -0
  43. data/lib/theme_check/{template.rb → liquid_file.rb} +6 -20
  44. data/lib/theme_check/liquid_node.rb +291 -0
  45. data/lib/theme_check/{visitor.rb → liquid_visitor.rb} +4 -4
  46. data/lib/theme_check/locale_diff.rb +5 -5
  47. data/lib/theme_check/node.rb +12 -230
  48. data/lib/theme_check/offense.rb +41 -15
  49. data/lib/theme_check/position.rb +1 -1
  50. data/lib/theme_check/regex_helpers.rb +1 -15
  51. data/lib/theme_check/theme.rb +1 -1
  52. data/lib/theme_check/theme_file.rb +18 -1
  53. data/lib/theme_check/theme_file_rewriter.rb +57 -0
  54. data/lib/theme_check/version.rb +1 -1
  55. data/lib/theme_check.rb +11 -9
  56. data/theme-check.gemspec +2 -1
  57. metadata +23 -6
@@ -25,21 +25,21 @@ module ThemeCheck
25
25
  end
26
26
 
27
27
  def on_document(node)
28
- @templates[node.template.name] = TemplateInfo.new(Set.new, {}, Set.new)
28
+ @templates[node.theme_file.name] = TemplateInfo.new(Set.new, {}, Set.new)
29
29
  end
30
30
 
31
31
  def on_assign(node)
32
- @templates[node.template.name].assign_nodes[node.value.to] = node
32
+ @templates[node.theme_file.name].assign_nodes[node.value.to] = node
33
33
  end
34
34
 
35
35
  def on_include(node)
36
36
  if node.value.template_name_expr.is_a?(String)
37
- @templates[node.template.name].includes << "snippets/#{node.value.template_name_expr}"
37
+ @templates[node.theme_file.name].includes << "snippets/#{node.value.template_name_expr}"
38
38
  end
39
39
  end
40
40
 
41
41
  def on_variable_lookup(node)
42
- @templates[node.template.name].used_assigns << node.value.name
42
+ @templates[node.theme_file.name].used_assigns << node.value.name
43
43
  end
44
44
 
45
45
  def on_end
@@ -8,28 +8,30 @@ module ThemeCheck
8
8
  doc docs_url(__FILE__)
9
9
 
10
10
  def initialize
11
- @used_templates = Set.new
11
+ @used_snippets = Set.new
12
12
  end
13
13
 
14
14
  def on_include(node)
15
15
  if node.value.template_name_expr.is_a?(String)
16
- @used_templates << "snippets/#{node.value.template_name_expr}"
16
+ @used_snippets << "snippets/#{node.value.template_name_expr}"
17
17
  else
18
18
  # Can't reliably track unused snippets if an expression is used, ignore this check
19
- @used_templates.clear
19
+ @used_snippets.clear
20
20
  ignore!
21
21
  end
22
22
  end
23
23
  alias_method :on_render, :on_include
24
24
 
25
25
  def on_end
26
- missing_snippets.each do |template|
27
- add_offense("This template is not used", template: template)
26
+ missing_snippets.each do |theme_file|
27
+ add_offense("This snippet is not used", theme_file: theme_file) do |corrector|
28
+ corrector.remove(@theme, theme_file.relative_path.to_s)
29
+ end
28
30
  end
29
31
  end
30
32
 
31
33
  def missing_snippets
32
- theme.snippets.reject { |t| @used_templates.include?(t.name) }
34
+ theme.snippets.reject { |t| @used_snippets.include?(t.name) }
33
35
  end
34
36
  end
35
37
  end
@@ -8,7 +8,7 @@ module ThemeCheck
8
8
  def on_file(file)
9
9
  if file.parse_error
10
10
  message = format_json_parse_error(file.parse_error)
11
- add_offense(message, template: file)
11
+ add_offense(message, theme_file: file)
12
12
  end
13
13
  end
14
14
  end
@@ -47,9 +47,10 @@ module ThemeCheck
47
47
  raise
48
48
  rescue => e
49
49
  node = args.first
50
- template = node.respond_to?(:template) ? node.template.relative_path : "?"
50
+ theme_file = node.respond_to?(:theme_file) ? node.theme_file.relative_path : "?"
51
51
  markup = node.respond_to?(:markup) ? node.markup : ""
52
52
  node_class = node.respond_to?(:value) ? node.value.class : "?"
53
+ line_number = node.respond_to?(:line_number) ? node.line_number : "?"
53
54
 
54
55
  ThemeCheck.bug(<<~EOS)
55
56
  Exception while running `#{check.code_name}##{method}`:
@@ -58,12 +59,13 @@ module ThemeCheck
58
59
  #{e.backtrace.join("\n ")}
59
60
  ```
60
61
 
61
- Template: `#{template}`
62
+ Theme File: `#{theme_file}`
62
63
  Node: `#{node_class}`
63
64
  Markup:
64
65
  ```
65
66
  #{markup}
66
67
  ```
68
+ Line number: #{line_number}
67
69
  Check options: `#{check.options.pretty_inspect}`
68
70
  EOS
69
71
  end
@@ -49,7 +49,7 @@ module ThemeCheck
49
49
  "Automatically fix offenses"
50
50
  ) { @auto_correct = true }
51
51
  @option_parser.on(
52
- "--fail-level SEVERITY", Check::SEVERITIES,
52
+ "--fail-level SEVERITY", [:crash] + Check::SEVERITIES,
53
53
  "Minimum severity (error|suggestion|style) for exit with error code"
54
54
  ) do |severity|
55
55
  @fail_level = severity.to_sym
@@ -186,12 +186,15 @@ module ThemeCheck
186
186
  storage = ThemeCheck::FileSystemStorage.new(@config.root, ignored_patterns: @config.ignored_patterns)
187
187
  theme = ThemeCheck::Theme.new(storage)
188
188
  if theme.all.empty?
189
- raise Abort, "No templates found."
189
+ raise Abort, "No theme files found."
190
190
  end
191
191
  analyzer = ThemeCheck::Analyzer.new(theme, @config.enabled_checks, @config.auto_correct)
192
192
  analyzer.analyze_theme
193
193
  analyzer.correct_offenses
194
- output_with_format(theme, analyzer, out_stream)
194
+ print_with_format(theme, analyzer, out_stream)
195
+ # corrections are committed after printing so that the
196
+ # source_excerpts are still pointing to the uncorrected source.
197
+ analyzer.write_corrections
195
198
  raise Abort, "" if analyzer.uncorrectable_offenses.any? do |offense|
196
199
  offense.check.severity_value <= Check.severity_value(@fail_level)
197
200
  end
@@ -211,7 +214,7 @@ module ThemeCheck
211
214
  STDERR.puts "Profiling is only available in development"
212
215
  end
213
216
 
214
- def output_with_format(theme, analyzer, out_stream)
217
+ def print_with_format(theme, analyzer, out_stream)
215
218
  case @format
216
219
  when :text
217
220
  ThemeCheck::Printer.new(out_stream).print(theme, analyzer.offenses, @config.auto_correct)
@@ -2,30 +2,25 @@
2
2
 
3
3
  module ThemeCheck
4
4
  class Corrector
5
- def initialize(template:)
6
- @template = template
5
+ def initialize(theme_file:)
6
+ @theme_file = theme_file
7
7
  end
8
8
 
9
9
  def insert_after(node, content)
10
- line = @template.full_line(node.line_number)
11
- line.insert(node.range[1] + 1, content)
10
+ @theme_file.rewriter.insert_after(node, content)
12
11
  end
13
12
 
14
13
  def insert_before(node, content)
15
- line = @template.full_line(node.line_number)
16
- line.insert(node.range[0], content)
14
+ @theme_file.rewriter.insert_before(node, content)
17
15
  end
18
16
 
19
17
  def replace(node, content)
20
- line = @template.full_line(node.line_number)
21
- line[node.range[0]..node.range[1]] = content
18
+ @theme_file.rewriter.replace(node, content)
22
19
  node.markup = content
23
20
  end
24
21
 
25
22
  def wrap(node, insert_before, insert_after)
26
- line = @template.full_line(node.line_number)
27
- line.insert(node.range[0], insert_before)
28
- line.insert(node.range[1] + 1 + insert_before.length, insert_after)
23
+ @theme_file.rewriter.wrap(node, insert_before, insert_after)
29
24
  end
30
25
 
31
26
  def create(theme, relative_path, content)
@@ -34,11 +29,25 @@ module ThemeCheck
34
29
 
35
30
  def create_default_locale_json(theme)
36
31
  theme.default_locale_json = JsonFile.new("locales/#{theme.default_locale}.default.json", theme.storage)
37
- theme.default_locale_json.update_contents('{}')
32
+ theme.default_locale_json.update_contents({})
33
+ end
34
+
35
+ def remove(theme, relative_path)
36
+ theme.storage.remove(relative_path)
38
37
  end
39
38
 
40
39
  def mkdir(theme, relative_path)
41
40
  theme.storage.mkdir(relative_path)
42
41
  end
42
+
43
+ def add_default_translation_key(file, key, value)
44
+ hash = file.content
45
+ key.reduce(hash) do |pointer, token|
46
+ return pointer[token] = value if token == key.last
47
+ pointer[token] = {} unless pointer.key?(token)
48
+ pointer[token]
49
+ end
50
+ file.update_contents(hash)
51
+ end
43
52
  end
44
53
  end
@@ -4,11 +4,11 @@
4
4
  # We'll use the node position to figure out if the test is disabled or not.
5
5
  module ThemeCheck
6
6
  class DisabledCheck
7
- attr_reader :name, :template, :ranges
7
+ attr_reader :name, :theme_file, :ranges
8
8
  attr_accessor :first_line
9
9
 
10
- def initialize(template, name)
11
- @template = template
10
+ def initialize(theme_file, name)
11
+ @theme_file = theme_file
12
12
  @name = name
13
13
  @ranges = []
14
14
  @first_line = false
@@ -11,8 +11,8 @@ module ThemeCheck
11
11
 
12
12
  def initialize
13
13
  @disabled_checks = Hash.new do |hash, key|
14
- template, check_name = key
15
- hash[key] = DisabledCheck.new(template, check_name)
14
+ theme_file, check_name = key
15
+ hash[key] = DisabledCheck.new(theme_file, check_name)
16
16
  end
17
17
  end
18
18
 
@@ -20,26 +20,26 @@ module ThemeCheck
20
20
  text = comment_text(node)
21
21
  if start_disabling?(text)
22
22
  checks_from_text(text).each do |check_name|
23
- disabled = @disabled_checks[[node.template, check_name]]
23
+ disabled = @disabled_checks[[node.theme_file, check_name]]
24
24
  disabled.start_index = node.start_index
25
25
  disabled.first_line = true if node.line_number == 1
26
26
  end
27
27
  elsif stop_disabling?(text)
28
28
  checks_from_text(text).each do |check_name|
29
- disabled = @disabled_checks[[node.template, check_name]]
29
+ disabled = @disabled_checks[[node.theme_file, check_name]]
30
30
  next unless disabled
31
31
  disabled.end_index = node.end_index
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
- def disabled?(check, template, check_name, index)
36
+ def disabled?(check, theme_file, check_name, index)
37
37
  return true if check.ignored_patterns&.any? do |pattern|
38
- template.relative_path.fnmatch?(pattern)
38
+ theme_file.relative_path.fnmatch?(pattern)
39
39
  end
40
40
 
41
- @disabled_checks[[template, :all]]&.disabled?(index) ||
42
- @disabled_checks[[template, check_name]]&.disabled?(index)
41
+ @disabled_checks[[theme_file, :all]]&.disabled?(index) ||
42
+ @disabled_checks[[theme_file, check_name]]&.disabled?(index)
43
43
  end
44
44
 
45
45
  def checks_missing_end_index
@@ -51,7 +51,7 @@ module ThemeCheck
51
51
  def remove_disabled_offenses(checks)
52
52
  checks.disableable.each do |check|
53
53
  check.offenses.reject! do |offense|
54
- disabled?(check, offense.template, offense.code_name, offense.start_index)
54
+ disabled?(check, offense.theme_file, offense.code_name, offense.start_index)
55
55
  end
56
56
  end
57
57
  end
@@ -16,14 +16,19 @@ module ThemeCheck
16
16
  end
17
17
 
18
18
  def read(relative_path)
19
- file(relative_path).read
19
+ file(relative_path).read(mode: 'rb', encoding: 'UTF-8')
20
20
  end
21
21
 
22
22
  def write(relative_path, content)
23
23
  reset_memoizers unless file_exists?(relative_path)
24
24
 
25
25
  file(relative_path).dirname.mkpath unless file(relative_path).dirname.directory?
26
- file(relative_path).write(content)
26
+ file(relative_path).write(content, mode: 'w+b', encoding: 'UTF-8')
27
+ end
28
+
29
+ def remove(relative_path)
30
+ file(relative_path).delete
31
+ reset_memoizers
27
32
  end
28
33
 
29
34
  def mkdir(relative_path)
@@ -2,18 +2,50 @@
2
2
  require "forwardable"
3
3
 
4
4
  module ThemeCheck
5
- class HtmlNode
5
+ class HtmlNode < Node
6
6
  extend Forwardable
7
7
  include RegexHelpers
8
- attr_reader :template, :parent
8
+ attr_reader :theme_file, :parent
9
9
 
10
- def initialize(value, template, placeholder_values = [], parent = nil)
10
+ def initialize(value, theme_file, placeholder_values = [], parent = nil)
11
11
  @value = value
12
- @template = template
12
+ @theme_file = theme_file
13
13
  @placeholder_values = placeholder_values
14
14
  @parent = parent
15
15
  end
16
16
 
17
+ # @value is not forwarded because we _need_ to replace the
18
+ # placeholders for the HtmlNode to make sense.
19
+ def value
20
+ if literal?
21
+ content
22
+ else
23
+ markup
24
+ end
25
+ end
26
+
27
+ def children
28
+ @children ||= @value
29
+ .children
30
+ .map { |child| HtmlNode.new(child, theme_file, @placeholder_values, self) }
31
+ end
32
+
33
+ def markup
34
+ @markup ||= replace_placeholders(@value.to_html)
35
+ end
36
+
37
+ def line_number
38
+ @value.line
39
+ end
40
+
41
+ def start_index
42
+ raise NotImplementedError
43
+ end
44
+
45
+ def end_index
46
+ raise NotImplementedError
47
+ end
48
+
17
49
  def literal?
18
50
  @value.name == "text"
19
51
  end
@@ -22,12 +54,6 @@ module ThemeCheck
22
54
  @value.element?
23
55
  end
24
56
 
25
- def children
26
- @children ||= @value
27
- .children
28
- .map { |child| HtmlNode.new(child, template, @placeholder_values, self) }
29
- end
30
-
31
57
  def attributes
32
58
  @attributes ||= @value.attributes
33
59
  .map { |k, v| [replace_placeholders(k), replace_placeholders(v.value)] }
@@ -38,16 +64,6 @@ module ThemeCheck
38
64
  @content ||= replace_placeholders(@value.content)
39
65
  end
40
66
 
41
- # @value is not forwarded because we _need_ to replace the
42
- # placeholders for the HtmlNode to make sense.
43
- def value
44
- if literal?
45
- content
46
- else
47
- markup
48
- end
49
- end
50
-
51
67
  def name
52
68
  if @value.name == "#document-fragment"
53
69
  "document"
@@ -56,21 +72,13 @@ module ThemeCheck
56
72
  end
57
73
  end
58
74
 
59
- def markup
60
- @markup ||= replace_placeholders(@value.to_html)
61
- end
62
-
63
- def line_number
64
- @value.line
65
- end
66
-
67
75
  private
68
76
 
69
77
  def replace_placeholders(string)
70
- # Replace all {%#{i}####%} with the actual content.
71
- string.gsub(LIQUID_TAG) do |match|
72
- key = /\d+/.match(match)[0]
73
- @placeholder_values[key.to_i]
78
+ # Replace all {i}####≬ with the actual content.
79
+ string.gsub(HTML_LIQUID_PLACEHOLDER) do |match|
80
+ key = /[0-9a-z]+/.match(match)[0]
81
+ @placeholder_values[key.to_i(36)]
74
82
  end
75
83
  end
76
84
  end
@@ -9,32 +9,44 @@ module ThemeCheck
9
9
 
10
10
  def initialize(checks)
11
11
  @checks = checks
12
- @placeholder_values = []
13
12
  end
14
13
 
15
- def visit_template(template)
16
- doc = parse(template)
17
- visit(HtmlNode.new(doc, template, @placeholder_values))
14
+ def visit_liquid_file(liquid_file)
15
+ doc, placeholder_values = parse(liquid_file)
16
+ visit(HtmlNode.new(doc, liquid_file, placeholder_values))
18
17
  rescue ArgumentError => e
19
- call_checks(:on_parse_error, e, template)
18
+ call_checks(:on_parse_error, e, liquid_file)
20
19
  end
21
20
 
22
21
  private
23
22
 
24
- def parse(template)
25
- parseable_source = +template.source.clone
23
+ def parse(liquid_file)
24
+ placeholder_values = []
25
+ parseable_source = +liquid_file.source.clone
26
26
 
27
- # Replace all liquid tags with {%#{i}######%} to prevent the HTML
27
+ # Replace all non-empty liquid tags with {i}######≬ to prevent the HTML
28
28
  # parser from freaking out. We transparently replace those placeholders in
29
29
  # HtmlNode.
30
+ #
31
+ # We're using base36 to prevent index bleeding on 36^3 tags.
32
+ # `{{x}}` -> `≬#{i}≬` would properly be transformed for 46656 tags in a single file.
33
+ # Should be enough.
34
+ #
35
+ # The base10 alternative would have overflowed at 1000 (`{{x}}` -> `≬1000≬`) which seemed more likely.
36
+ #
37
+ # Didn't go with base64 because of the `=` character that would have messed with HTML parsing.
30
38
  matches(parseable_source, LIQUID_TAG_OR_VARIABLE).each do |m|
31
39
  value = m[0]
32
- @placeholder_values.push(value)
33
- key = (@placeholder_values.size - 1).to_s
34
- parseable_source[m.begin(0)...m.end(0)] = "{%#{key.ljust(m.end(0) - m.begin(0) - 4, '#')}%}"
40
+ next unless value.size > 4 # skip empty tags/variables {%%} and {{}}
41
+ placeholder_values.push(value)
42
+ key = (placeholder_values.size - 1).to_s(36)
43
+ parseable_source[m.begin(0)...m.end(0)] = "≬#{key.ljust(m.end(0) - m.begin(0) - 2, '#')}≬"
35
44
  end
36
45
 
37
- Nokogiri::HTML5.fragment(parseable_source, max_tree_depth: 400, max_attributes: 400)
46
+ [
47
+ Nokogiri::HTML5.fragment(parseable_source, max_tree_depth: 400, max_attributes: 400),
48
+ placeholder_values,
49
+ ]
38
50
  end
39
51
 
40
52
  def visit(node)
@@ -2,7 +2,7 @@
2
2
 
3
3
  # An in-memory storage is not written to disk. The reasons why you'd
4
4
  # want to do that are your own. The idea is to not write to disk
5
- # something that doesn't need to be there. If you have your template
5
+ # something that doesn't need to be there. If you have your theme
6
6
  # as a big hash already, leave it like that and save yourself some IO.
7
7
  module ThemeCheck
8
8
  class InMemoryStorage < Storage
@@ -23,6 +23,10 @@ module ThemeCheck
23
23
  @files[relative_path] = content
24
24
  end
25
25
 
26
+ def remove(relative_path)
27
+ @files.delete(relative_path)
28
+ end
29
+
26
30
  def mkdir(relative_path)
27
31
  @files[relative_path] = nil
28
32
  end
@@ -4,8 +4,8 @@ module ThemeCheck
4
4
  class JsonCheck < Check
5
5
  extend ChecksTracking
6
6
 
7
- def add_offense(message, markup: nil, line_number: nil, template: nil, &block)
8
- offenses << Offense.new(check: self, message: message, markup: markup, line_number: line_number, template: template, correction: block)
7
+ def add_offense(message, markup: nil, line_number: nil, theme_file: nil, &block)
8
+ offenses << Offense.new(check: self, message: message, markup: markup, line_number: line_number, theme_file: theme_file, correction: block)
9
9
  end
10
10
  end
11
11
  end
@@ -20,14 +20,19 @@ module ThemeCheck
20
20
  @parser_error
21
21
  end
22
22
 
23
- def update_contents(new_content = '{}')
23
+ def update_contents(new_content = {})
24
+ raise ArgumentError if new_content.is_a?(String)
24
25
  @content = new_content
25
26
  end
26
27
 
27
28
  def write
28
- if source != @content
29
- @storage.write(@relative_path, content)
30
- @source = content
29
+ pretty = JSON.pretty_generate(@content)
30
+ if source.rstrip != pretty.rstrip
31
+ # Most editors add a trailing \n at the end of files. Here we
32
+ # try to maintain the convention.
33
+ eof = source.end_with?("\n") ? "\n" : ""
34
+ @storage.write(@relative_path, pretty.gsub("\n", @eol) + eof)
35
+ @source = pretty
31
36
  end
32
37
  end
33
38
 
@@ -19,22 +19,22 @@ module ThemeCheck
19
19
  new_single_file_offenses = {}
20
20
  analyzed_files = analyzed_files.map { |path| Pathname.new(path) } if analyzed_files
21
21
 
22
- offenses.group_by(&:template).each do |template, template_offenses|
23
- next unless template
22
+ offenses.group_by(&:theme_file).each do |theme_file, template_offenses|
23
+ next unless theme_file
24
24
  reported_offenses = template_offenses
25
- previous_offenses = @single_files_offenses[template.path]
26
- if analyzed_files.nil? || analyzed_files.include?(template.path)
25
+ previous_offenses = @single_files_offenses[theme_file.path]
26
+ if analyzed_files.nil? || analyzed_files.include?(theme_file.path)
27
27
  # We re-analyzed the file, so we know the template_offenses are update to date.
28
28
  reported_single_file_offenses = reported_offenses.select(&:single_file?)
29
29
  if reported_single_file_offenses.any?
30
- new_single_file_offenses[template.path] = reported_single_file_offenses
30
+ new_single_file_offenses[theme_file.path] = reported_single_file_offenses
31
31
  end
32
32
  elsif previous_offenses
33
33
  # Merge in the previous ones, if some
34
34
  reported_offenses |= previous_offenses
35
35
  end
36
- yield template.path, reported_offenses
37
- reported_files << template.path
36
+ yield theme_file.path, reported_offenses
37
+ reported_files << theme_file.path
38
38
  end
39
39
 
40
40
  @single_files_offenses.each do |path, _|
@@ -51,7 +51,7 @@ module ThemeCheck
51
51
  reported_files << path
52
52
  end
53
53
 
54
- # Publish diagnostics with empty array if all issues on a previously reported template
54
+ # Publish diagnostics with empty array if all issues on a previously reported theme_file
55
55
  # have been fixed.
56
56
  (@previously_reported_files - reported_files).each do |path|
57
57
  yield path, []