theme-check 1.6.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/data/shopify_liquid/tags.yml +9 -9
  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 +41 -17
  9. data/lib/theme_check/asset_file.rb +1 -1
  10. data/lib/theme_check/check.rb +2 -2
  11. data/lib/theme_check/checks/html_parsing_error.rb +2 -2
  12. data/lib/theme_check/checks/matching_translations.rb +1 -1
  13. data/lib/theme_check/checks/missing_template.rb +6 -6
  14. data/lib/theme_check/checks/nested_snippet.rb +2 -2
  15. data/lib/theme_check/checks/required_layout_theme_object.rb +2 -2
  16. data/lib/theme_check/checks/syntax_error.rb +5 -5
  17. data/lib/theme_check/checks/template_length.rb +2 -2
  18. data/lib/theme_check/checks/translation_key_exists.rb +1 -13
  19. data/lib/theme_check/checks/undefined_object.rb +7 -7
  20. data/lib/theme_check/checks/unused_assign.rb +4 -4
  21. data/lib/theme_check/checks/unused_snippet.rb +7 -7
  22. data/lib/theme_check/checks/valid_json.rb +1 -1
  23. data/lib/theme_check/checks.rb +4 -2
  24. data/lib/theme_check/cli.rb +1 -1
  25. data/lib/theme_check/corrector.rb +6 -6
  26. data/lib/theme_check/disabled_check.rb +3 -3
  27. data/lib/theme_check/disabled_checks.rb +9 -9
  28. data/lib/theme_check/exceptions.rb +1 -0
  29. data/lib/theme_check/file_system_storage.rb +4 -0
  30. data/lib/theme_check/html_node.rb +36 -28
  31. data/lib/theme_check/html_visitor.rb +6 -6
  32. data/lib/theme_check/in_memory_storage.rb +1 -1
  33. data/lib/theme_check/json_check.rb +2 -2
  34. data/lib/theme_check/language_server/bridge.rb +128 -0
  35. data/lib/theme_check/language_server/channel.rb +69 -0
  36. data/lib/theme_check/language_server/completion_providers/tag_completion_provider.rb +3 -1
  37. data/lib/theme_check/language_server/diagnostics_engine.rb +125 -0
  38. data/lib/theme_check/language_server/diagnostics_tracker.rb +8 -8
  39. data/lib/theme_check/language_server/handler.rb +20 -117
  40. data/lib/theme_check/language_server/io_messenger.rb +97 -0
  41. data/lib/theme_check/language_server/messenger.rb +27 -0
  42. data/lib/theme_check/language_server/server.rb +95 -104
  43. data/lib/theme_check/language_server.rb +6 -1
  44. data/lib/theme_check/{template.rb → liquid_file.rb} +2 -2
  45. data/lib/theme_check/liquid_node.rb +291 -0
  46. data/lib/theme_check/{visitor.rb → liquid_visitor.rb} +4 -4
  47. data/lib/theme_check/locale_diff.rb +14 -7
  48. data/lib/theme_check/node.rb +12 -225
  49. data/lib/theme_check/offense.rb +15 -15
  50. data/lib/theme_check/position.rb +1 -1
  51. data/lib/theme_check/shopify_liquid/system_translations.rb +35 -0
  52. data/lib/theme_check/shopify_liquid/tag.rb +19 -1
  53. data/lib/theme_check/shopify_liquid.rb +1 -0
  54. data/lib/theme_check/theme.rb +1 -1
  55. data/lib/theme_check/{template_rewriter.rb → theme_file_rewriter.rb} +1 -1
  56. data/lib/theme_check/version.rb +1 -1
  57. data/lib/theme_check.rb +11 -10
  58. data/theme-check.gemspec +1 -1
  59. metadata +14 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 713459ed0c35e11e175e51d42237fceb583184af08a00f8f56cdecbbb1c494b8
4
- data.tar.gz: aa2059da0b820755eee1a8778748d7c7758fef705e29f5def5c74905743553d8
3
+ metadata.gz: 0c0071563941bd1e62d174c317667f7b1258a5154fdd0b9e65531a667aafbb53
4
+ data.tar.gz: fba3428de01a76fc042ee5c9fefe5acdcc1b446c02eafd5a2d187d503d863433
5
5
  SHA512:
6
- metadata.gz: fa6216908fb067365d11ef7c0ea1c2e0a847de124f81ad43824eb49f9373093b6fc54dabbc1062dd9068af11724abc9dad020c6bebc2c71702f4750a8829aa78
7
- data.tar.gz: f0412fbb0407d75e33ac96f66c760dd39ddb5cd18c751b8f6cb8a6edb4da1d0867147d929b7bae1401eb5837ee1c4aa0f40f60340d70c4a75c5f47a0753ebf58
6
+ metadata.gz: 9ebf3e7d3f24ca2d5d4f7b815199755bc997b94e870b3e60a2d24bc39f863974f7838f69548d11ccca9882335b3cf1522384b56f4bd3184d526ca968909cb192
7
+ data.tar.gz: dd9d5079b4adc9be6c13eb9cdf42e049e87988337e7881631eb0ee1163c8680930cb6efee863856221b1f8fd76fc81d9d848cd10969752f170cd032e371a42d0
data/CHANGELOG.md CHANGED
@@ -1,4 +1,31 @@
1
1
 
2
+ v1.7.1 / 2021-09-24
3
+ ===================
4
+
5
+ * Handle Errno::EADDRNOTAVAIL in RemoteAsset ([#465](https://github.com/shopify/theme-check/issues/465))
6
+ * Complete end tags ([#277](https://github.com/shopify/theme-check/issues/277))
7
+ * Do not flag shopify translations as missing or extra ([#407](https://github.com/shopify/theme-check/issues/407))
8
+
9
+ v1.7.0 / 2021-09-20
10
+ ===================
11
+
12
+ ### Features
13
+
14
+ * Handle LSP messages concurrently in the Language Server ([#459](https://github.com/shopify/theme-check/issues/459))
15
+ * Adds progress reporting while checking (:eyes: VS Code status bar)
16
+ * Makes completions work while checking (more noticeable on Windows since ruby is 3x slower on Windows)
17
+
18
+ v1.6.2 / 2021-09-16
19
+ ===================
20
+
21
+ * SpaceInsideBraces fixup for tags without arguments ([#458](https://github.com/shopify/theme-check/issues/458))
22
+ * Fix UnusedAssign bug when variable used in for loop range by bumping Liquid to 5.1 ([#456](https://github.com/shopify/theme-check/issues/456))
23
+
24
+ v1.6.1 / 2021-09-15
25
+ ===================
26
+
27
+ * Fix `Undefined method `-' for nil:NilClass` in Node when tag was missing surrounding spaces ([#454](https://github.com/shopify/theme-check/issues/454), [#452](https://github.com/shopify/theme-check/issues/452))
28
+
2
29
  v1.6.0 / 2021-09-14
3
30
  ===================
4
31
 
@@ -2,28 +2,28 @@
2
2
  - assign
3
3
  - break
4
4
  - capture
5
- - case
6
- - comment
5
+ - case: endcase
6
+ - comment: endcomment
7
7
  - continue
8
8
  - cycle
9
9
  - decrement
10
10
  - echo
11
11
  - else
12
12
  - elsif
13
- - for
14
- - form
15
- - if
13
+ - for: endfor
14
+ - form: endform
15
+ - if: endif
16
16
  - ifchanged
17
17
  - increment
18
- - javascript
18
+ - javascript: endjavascript
19
19
  - layout
20
20
  - liquid
21
- - paginate
21
+ - paginate: endpaginate
22
22
  - raw
23
23
  - render
24
- - schema
24
+ - schema: endschema
25
25
  - section
26
- - style
26
+ - style: endstyle
27
27
  - stylesheet
28
28
  - tablerow
29
29
  - unless
@@ -16,18 +16,18 @@ module ThemeCheck
16
16
  severity :suggestion # :error or :style
17
17
 
18
18
  def on_document(node)
19
- # Called with the root node of all templates
20
- node.value # is an instance of Nokogiri::XML::Node
21
- node.template # is the template being analyzed, See lib/theme_check/template.rb.
22
- node.parent # is the parent node.
23
- node.children # are the children nodes.
19
+ # Called with the root node of all theme files
20
+ node.value # is an instance of Nokogiri::XML::Node
21
+ node.theme_file # is the html_file being analyzed, See lib/theme_check/theme_file.rb.
22
+ node.parent # is the parent node.
23
+ node.children # are the children nodes.
24
24
  # See lib/theme_check/html_node.rb for more helper methods
25
- theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
25
+ theme # Gives you access to all the theme files in the theme. See lib/theme_check/theme.rb.
26
26
  end
27
27
 
28
28
  def on_img(node)
29
29
  # Called for every <img> element in the file.
30
- node.attrbutes["class"] # Get the class attribute of the img element.
30
+ node.attributes["class"] # Get the class attribute of the img element.
31
31
  end
32
32
 
33
33
  def on_a(node)
@@ -16,13 +16,13 @@ module ThemeCheck
16
16
  severity :suggestion # :error or :style
17
17
 
18
18
  def on_document(node)
19
- # Called with the root node of all templates
20
- node.value # is the original Liquid object for this node. See Liquid source code for details.
21
- node.template # is the template being analyzed, See lib/theme_check/template.rb.
22
- node.parent # is the parent node.
23
- node.children # are the children nodes.
19
+ # Called with the root node of all liquid_file
20
+ node.value # is the original Liquid object for this node. See Liquid source code for details.
21
+ node.theme_file # is the liquid_file being analyzed, See lib/theme_check/liquid_file.rb.
22
+ node.parent # is the parent node.
23
+ node.children # are the children nodes.
24
24
  # See lib/theme_check/node.rb for more helper methods
25
- theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
25
+ theme # Gives you access to all the theme files in the theme. See lib/theme_check/theme.rb.
26
26
  end
27
27
 
28
28
  def on_node(node)
@@ -38,8 +38,8 @@ module ThemeCheck
38
38
 
39
39
  # If you find an issue, add an offense:
40
40
  add_offense("Describe the problem...", node: node)
41
- # Or, if the offense is related to the whole template:
42
- add_offense("Describe the problem...", template: node.template)
41
+ # Or, if the offense is related to the whole theme file:
42
+ add_offense("Describe the problem...", theme_file: node.theme_file)
43
43
  end
44
44
 
45
45
  def on_assign(node)
@@ -50,7 +50,7 @@ module ThemeCheck
50
50
  # Called for every `String` (including inside if conditions).
51
51
  if node.parent.block?
52
52
  # If parent is a block, `node.value` is a String written directly to the output when
53
- # the template is rendered.
53
+ # the theme file is rendered.
54
54
  end
55
55
  end
56
56
 
@@ -59,7 +59,7 @@ module ThemeCheck
59
59
  end
60
60
 
61
61
  def on_error(exception)
62
- # Called each time a Liquid exception is raised while parsing the template
62
+ # Called each time a Liquid exception is raised while parsing the theme file
63
63
  end
64
64
 
65
65
  def on_end
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `include` tag is [deprecated][deprecated]. This tag exists to enforce the use of the `render` tag instead of `include`.
4
4
 
5
- The `include` tag works similarly to the `render` tag, but it lets the code inside of the snippet to access and overwrite the variables within its parent template. The `include` tag has been deprecated because the way that it handles variables reduces performance and makes theme code harder to both read and maintain.
5
+ The `include` tag works similarly to the `render` tag, but it lets the code inside of the snippet to access and overwrite the variables within its parent theme file. The `include` tag has been deprecated because the way that it handles variables reduces performance and makes theme code harder to both read and maintain.
6
6
 
7
7
  ## Check Details
8
8
 
@@ -1,6 +1,6 @@
1
1
  # Prevent missing theme-check-enable comments (`MissingEnableComment`)
2
2
 
3
- When `theme-check-disable` is used in the middle of a template, the corresponding `theme-check-enable` comment should also be included.
3
+ When `theme-check-disable` is used in the middle of a theme file, the corresponding `theme-check-enable` comment should also be included.
4
4
 
5
5
  ## Check Details
6
6
 
@@ -29,19 +29,36 @@ module ThemeCheck
29
29
  @html_checks.flat_map(&:offenses)
30
30
  end
31
31
 
32
+ def json_file_count
33
+ @json_file_count ||= @theme.json.size
34
+ end
35
+
36
+ def liquid_file_count
37
+ @liquid_file_count ||= @theme.liquid.size
38
+ end
39
+
40
+ def total_file_count
41
+ json_file_count + liquid_file_count
42
+ end
43
+
32
44
  def analyze_theme
33
45
  reset
34
46
 
35
- liquid_visitor = Visitor.new(@liquid_checks, @disabled_checks)
47
+ liquid_visitor = LiquidVisitor.new(@liquid_checks, @disabled_checks)
36
48
  html_visitor = HtmlVisitor.new(@html_checks)
49
+
37
50
  ThemeCheck.with_liquid_c_disabled do
38
- @theme.liquid.each do |template|
39
- liquid_visitor.visit_template(template)
40
- html_visitor.visit_template(template)
51
+ @theme.liquid.each_with_index do |liquid_file, i|
52
+ yield(liquid_file.relative_path.to_s, i, total_file_count) if block_given?
53
+ liquid_visitor.visit_liquid_file(liquid_file)
54
+ html_visitor.visit_liquid_file(liquid_file)
41
55
  end
42
56
  end
43
57
 
44
- @theme.json.each { |json_file| @json_checks.call(:on_file, json_file) }
58
+ @theme.json.each_with_index do |json_file, i|
59
+ yield(json_file.relative_path.to_s, liquid_file_count + i, total_file_count) if block_given?
60
+ @json_checks.call(:on_file, json_file)
61
+ end
45
62
 
46
63
  finish
47
64
  end
@@ -51,23 +68,30 @@ module ThemeCheck
51
68
 
52
69
  ThemeCheck.with_liquid_c_disabled do
53
70
  # Call all checks that run on the whole theme
54
- liquid_visitor = Visitor.new(@liquid_checks.whole_theme, @disabled_checks)
71
+ liquid_visitor = LiquidVisitor.new(@liquid_checks.whole_theme, @disabled_checks)
55
72
  html_visitor = HtmlVisitor.new(@html_checks.whole_theme)
56
- @theme.liquid.each do |template|
57
- liquid_visitor.visit_template(template)
58
- html_visitor.visit_template(template)
73
+ total = total_file_count + files.size
74
+ @theme.liquid.each_with_index do |liquid_file, i|
75
+ yield(liquid_file.relative_path.to_s, i, total) if block_given?
76
+ liquid_visitor.visit_liquid_file(liquid_file)
77
+ html_visitor.visit_liquid_file(liquid_file)
78
+ end
79
+
80
+ @theme.json.each_with_index do |json_file, i|
81
+ yield(json_file.relative_path.to_s, liquid_file_count + i, total) if block_given?
82
+ @json_checks.whole_theme.call(:on_file, json_file)
59
83
  end
60
- @theme.json.each { |json_file| @json_checks.whole_theme.call(:on_file, json_file) }
61
84
 
62
85
  # Call checks that run on a single files, only on specified file
63
- liquid_visitor = Visitor.new(@liquid_checks.single_file, @disabled_checks)
86
+ liquid_visitor = LiquidVisitor.new(@liquid_checks.single_file, @disabled_checks)
64
87
  html_visitor = HtmlVisitor.new(@html_checks.single_file)
65
- files.each do |file|
66
- if file.liquid?
67
- liquid_visitor.visit_template(file)
68
- html_visitor.visit_template(file)
69
- elsif file.json?
70
- @json_checks.single_file.call(:on_file, file)
88
+ files.each_with_index do |theme_file, i|
89
+ yield(theme_file.relative_path.to_s, total_file_count + i, total) if block_given?
90
+ if theme_file.liquid?
91
+ liquid_visitor.visit_liquid_file(theme_file)
92
+ html_visitor.visit_liquid_file(theme_file)
93
+ elsif theme_file.json?
94
+ @json_checks.single_file.call(:on_file, theme_file)
71
95
  end
72
96
  end
73
97
  end
@@ -10,7 +10,7 @@ module ThemeCheck
10
10
  end
11
11
 
12
12
  def rewriter
13
- @rewriter ||= TemplateRewriter.new(@relative_path, source)
13
+ @rewriter ||= ThemeFileRewriter.new(@relative_path, source)
14
14
  end
15
15
 
16
16
  def write
@@ -91,8 +91,8 @@ module ThemeCheck
91
91
  @offenses ||= []
92
92
  end
93
93
 
94
- def add_offense(message, node: nil, template: node&.template, markup: nil, line_number: nil, node_markup_offset: 0, &block)
95
- offenses << Offense.new(check: self, message: message, template: template, node: node, markup: markup, line_number: line_number, node_markup_offset: node_markup_offset, correction: block)
94
+ def add_offense(message, node: nil, theme_file: node&.theme_file, markup: nil, line_number: nil, node_markup_offset: 0, &block)
95
+ offenses << Offense.new(check: self, message: message, theme_file: theme_file, node: node, markup: markup, line_number: line_number, node_markup_offset: node_markup_offset, correction: block)
96
96
  end
97
97
 
98
98
  def severity
@@ -5,8 +5,8 @@ module ThemeCheck
5
5
  category :html
6
6
  doc docs_url(__FILE__)
7
7
 
8
- def on_parse_error(exception, template)
9
- add_offense("HTML in this template can not be parsed: #{exception.message}", template: template)
8
+ def on_parse_error(exception, theme_file)
9
+ add_offense("HTML in this template can not be parsed: #{exception.message}", theme_file: theme_file)
10
10
  end
11
11
  end
12
12
  end
@@ -23,7 +23,7 @@ module ThemeCheck
23
23
 
24
24
  @files.each do |file|
25
25
  diff = LocaleDiff.new(@theme.default_locale_json.content, file.content)
26
- diff.add_as_offenses(self, template: file)
26
+ diff.add_as_offenses(self, theme_file: file)
27
27
  end
28
28
  end
29
29
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- # Reports missing include/render/section template
3
+ # Reports missing include/render/section liquid file
4
4
  class MissingTemplate < LiquidCheck
5
5
  severity :suggestion
6
6
  category :liquid
@@ -12,17 +12,17 @@ module ThemeCheck
12
12
  end
13
13
 
14
14
  def on_include(node)
15
- template = node.value.template_name_expr
16
- if template.is_a?(String)
17
- add_missing_offense("snippets/#{template}", node: node)
15
+ snippet = node.value.template_name_expr
16
+ if snippet.is_a?(String)
17
+ add_missing_offense("snippets/#{snippet}", node: node)
18
18
  end
19
19
  end
20
20
 
21
21
  alias_method :on_render, :on_include
22
22
 
23
23
  def on_section(node)
24
- template = node.value.section_name
25
- add_missing_offense("sections/#{template}", node: node)
24
+ section = node.value.section_name
25
+ add_missing_offense("sections/#{section}", node: node)
26
26
  end
27
27
 
28
28
  private
@@ -26,12 +26,12 @@ module ThemeCheck
26
26
  end
27
27
 
28
28
  def on_document(node)
29
- @templates[node.template.name] = TemplateInfo.new(Set.new)
29
+ @templates[node.theme_file.name] = TemplateInfo.new(Set.new)
30
30
  end
31
31
 
32
32
  def on_include(node)
33
33
  if node.value.template_name_expr.is_a?(String)
34
- @templates[node.template.name].includes << node
34
+ @templates[node.theme_file.name].includes << node
35
35
  end
36
36
  end
37
37
  alias_method :on_render, :on_include
@@ -14,7 +14,7 @@ module ThemeCheck
14
14
  end
15
15
 
16
16
  def on_document(node)
17
- @layout_theme_node = node if node.template.name == LAYOUT_FILENAME
17
+ @layout_theme_node = node if node.theme_file.name == LAYOUT_FILENAME
18
18
  end
19
19
 
20
20
  def on_variable(node)
@@ -25,7 +25,7 @@ module ThemeCheck
25
25
  end
26
26
 
27
27
  def after_document(node)
28
- return unless node.template.name == LAYOUT_FILENAME
28
+ return unless node.theme_file.name == LAYOUT_FILENAME
29
29
 
30
30
  add_missing_object_offense("content_for_layout") unless @content_for_layout_found
31
31
  add_missing_object_offense("content_for_header") unless @content_for_header_found
@@ -7,23 +7,23 @@ module ThemeCheck
7
7
  doc docs_url(__FILE__)
8
8
 
9
9
  def on_document(node)
10
- node.template.warnings.each do |warning|
11
- add_exception_as_offense(warning, template: node.template)
10
+ node.theme_file.warnings.each do |warning|
11
+ add_exception_as_offense(warning, theme_file: node.theme_file)
12
12
  end
13
13
  end
14
14
 
15
15
  def on_error(exception)
16
- add_exception_as_offense(exception, template: theme[exception.template_name])
16
+ add_exception_as_offense(exception, theme_file: theme[exception.template_name])
17
17
  end
18
18
 
19
19
  private
20
20
 
21
- def add_exception_as_offense(exception, template:)
21
+ def add_exception_as_offense(exception, theme_file:)
22
22
  add_offense(
23
23
  exception.to_s(false).sub(/ in ".*"$/, ''),
24
24
  line_number: exception.line_number,
25
25
  markup: exception.markup_context&.sub(/^in "(.*)"$/, '\1'),
26
- template: template,
26
+ theme_file: theme_file,
27
27
  )
28
28
  end
29
29
  end
@@ -29,9 +29,9 @@ module ThemeCheck
29
29
  end
30
30
 
31
31
  def after_document(node)
32
- lines = node.template.source.count("\n") - @excluded_lines
32
+ lines = node.theme_file.source.count("\n") - @excluded_lines
33
33
  if lines > @max_length
34
- add_offense("Template has too many lines [#{lines}/#{@max_length}]", template: node.template)
34
+ add_offense("Template has too many lines [#{lines}/#{@max_length}]", theme_file: node.theme_file)
35
35
  end
36
36
  end
37
37
 
@@ -1,17 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- module SystemTranslations
4
- extend self
5
-
6
- def translations
7
- @translations ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_translation_keys.yml")).to_set
8
- end
9
-
10
- def include?(key)
11
- translations.include?(key)
12
- end
13
- end
14
-
15
3
  class TranslationKeyExists < LiquidCheck
16
4
  severity :error
17
5
  category :translation
@@ -24,7 +12,7 @@ module ThemeCheck
24
12
  return unless (key_node = node.children.first)
25
13
  return unless key_node.value.is_a?(String)
26
14
 
27
- unless key_exists?(key_node.value) || SystemTranslations.include?(key_node.value)
15
+ unless key_exists?(key_node.value) || ShopifyLiquid::SystemTranslations.include?(key_node.value)
28
16
  add_offense(
29
17
  "'#{key_node.value}' does not have a matching entry in '#{@theme.default_locale_json.relative_path}'",
30
18
  node: node,
@@ -62,22 +62,22 @@ module ThemeCheck
62
62
 
63
63
  def on_document(node)
64
64
  return if ignore?(node)
65
- @files[node.template.name] = TemplateInfo.new
65
+ @files[node.theme_file.name] = TemplateInfo.new
66
66
  end
67
67
 
68
68
  def on_assign(node)
69
69
  return if ignore?(node)
70
- @files[node.template.name].all_assigns[node.value.to] = node
70
+ @files[node.theme_file.name].all_assigns[node.value.to] = node
71
71
  end
72
72
 
73
73
  def on_capture(node)
74
74
  return if ignore?(node)
75
- @files[node.template.name].all_captures[node.value.instance_variable_get('@to')] = node
75
+ @files[node.theme_file.name].all_captures[node.value.instance_variable_get('@to')] = node
76
76
  end
77
77
 
78
78
  def on_for(node)
79
79
  return if ignore?(node)
80
- @files[node.template.name].all_forloops[node.value.variable_name] = node
80
+ @files[node.theme_file.name].all_forloops[node.value.variable_name] = node
81
81
  end
82
82
 
83
83
  def on_include(_node)
@@ -90,7 +90,7 @@ module ThemeCheck
90
90
  return unless node.value.template_name_expr.is_a?(String)
91
91
 
92
92
  snippet_name = "snippets/#{node.value.template_name_expr}"
93
- @files[node.template.name].add_render(
93
+ @files[node.theme_file.name].add_render(
94
94
  name: snippet_name,
95
95
  node: node,
96
96
  )
@@ -98,7 +98,7 @@ module ThemeCheck
98
98
 
99
99
  def on_variable_lookup(node)
100
100
  return if ignore?(node)
101
- @files[node.template.name].add_variable_lookup(
101
+ @files[node.theme_file.name].add_variable_lookup(
102
102
  name: node.value.name,
103
103
  node: node,
104
104
  )
@@ -130,7 +130,7 @@ module ThemeCheck
130
130
  private
131
131
 
132
132
  def ignore?(node)
133
- @exclude_snippets && node.template.snippet?
133
+ @exclude_snippets && node.theme_file.snippet?
134
134
  end
135
135
 
136
136
  def each_template
@@ -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,30 +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) do |corrector|
28
- corrector.remove(@theme, template.relative_path.to_s)
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
29
  end
30
30
  end
31
31
  end
32
32
 
33
33
  def missing_snippets
34
- theme.snippets.reject { |t| @used_templates.include?(t.name) }
34
+ theme.snippets.reject { |t| @used_snippets.include?(t.name) }
35
35
  end
36
36
  end
37
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
@@ -186,7 +186,7 @@ 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
@@ -2,25 +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
- @template.rewriter.insert_after(node, content)
10
+ @theme_file.rewriter.insert_after(node, content)
11
11
  end
12
12
 
13
13
  def insert_before(node, content)
14
- @template.rewriter.insert_before(node, content)
14
+ @theme_file.rewriter.insert_before(node, content)
15
15
  end
16
16
 
17
17
  def replace(node, content)
18
- @template.rewriter.replace(node, content)
18
+ @theme_file.rewriter.replace(node, content)
19
19
  node.markup = content
20
20
  end
21
21
 
22
22
  def wrap(node, insert_before, insert_after)
23
- @template.rewriter.wrap(node, insert_before, insert_after)
23
+ @theme_file.rewriter.wrap(node, insert_before, insert_after)
24
24
  end
25
25
 
26
26
  def create(theme, relative_path, content)