herb 0.11.1 → 0.11.2

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.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +4 -2
  3. data/config.yml +6 -0
  4. data/ext/herb/extconf.rb +8 -31
  5. data/ext/herb/nodes.c +75 -75
  6. data/ext/herb/parser_options_helpers.c +26 -0
  7. data/lib/herb/analysis/partial_index.rb +1 -1
  8. data/lib/herb/analysis/partial_resolution.rb +27 -0
  9. data/lib/herb/ast/helpers.rb +1 -1
  10. data/lib/herb/configuration.rb +11 -1
  11. data/lib/herb/dev/classifier.rb +1 -1
  12. data/lib/herb/engine/compiler.rb +5 -8
  13. data/lib/herb/engine/slots/dynamics_compiler.rb +53 -14
  14. data/lib/herb/engine/slots/subtree_compiler.rb +1 -1
  15. data/lib/herb/engine/slots/visitor.rb +32 -4
  16. data/lib/herb/engine/visitors/instrumentation_visitor.rb +18 -6
  17. data/lib/herb/parser_options.rb +6 -3
  18. data/lib/herb/project.rb +19 -8
  19. data/lib/herb/version.rb +1 -1
  20. data/lib/herb.rb +1 -1
  21. data/sig/herb/analysis/partial_resolution.rbs +8 -0
  22. data/sig/herb/configuration.rbs +3 -0
  23. data/sig/herb/engine/slots/dynamics_compiler.rbs +24 -7
  24. data/sig/herb/engine/slots/visitor.rbs +14 -0
  25. data/sig/herb/engine/visitors/instrumentation_visitor.rbs +5 -1
  26. data/sig/herb/parser_options.rbs +6 -4
  27. data/sig/herb.rbs +2 -2
  28. data/src/analyze/action_view/attribute_extraction_helpers.c +40 -21
  29. data/src/analyze/action_view/generated_handlers.c +36 -36
  30. data/src/analyze/action_view/image_tag.c +7 -3
  31. data/src/analyze/action_view/javascript_include_tag.c +6 -3
  32. data/src/analyze/action_view/link_to.c +23 -23
  33. data/src/analyze/action_view/registry.c +7 -3
  34. data/src/analyze/action_view/tag_helper_node_builders.c +6 -13
  35. data/src/analyze/action_view/tag_helpers.c +139 -90
  36. data/src/analyze/action_view/turbo_frame_tag.c +5 -4
  37. data/src/analyze/analyze.c +35 -19
  38. data/src/analyze/analyze_helpers.c +161 -188
  39. data/src/analyze/analyzed_ruby.c +8 -7
  40. data/src/analyze/control_type.c +29 -22
  41. data/src/analyze/herb_directives.c +16 -20
  42. data/src/analyze/iteration_nodes.c +69 -24
  43. data/src/analyze/parse_errors.c +32 -22
  44. data/src/analyze/postfix_conditionals.c +23 -13
  45. data/src/analyze/prism_annotate.c +29 -28
  46. data/src/analyze/render_nodes.c +51 -41
  47. data/src/analyze/strict_locals.c +14 -15
  48. data/src/analyze/ternary_conditionals.c +14 -10
  49. data/src/herb.c +10 -8
  50. data/src/include/analyze/action_view/tag_helper_handler.h +1 -1
  51. data/src/include/analyze/action_view/tag_helper_node_builders.h +1 -0
  52. data/src/include/analyze/action_view/tag_helpers.h +1 -1
  53. data/src/include/analyze/analyze.h +3 -2
  54. data/src/include/analyze/analyzed_ruby.h +4 -2
  55. data/src/include/analyze/helpers.h +6 -6
  56. data/src/include/herb.h +3 -2
  57. data/src/include/parser/parser_options.h +5 -0
  58. data/src/include/prism/prism_context.h +12 -12
  59. data/src/include/prism/prism_helpers.h +30 -0
  60. data/src/include/prism_version.h +11 -0
  61. data/src/include/version.h +1 -1
  62. data/src/parser/parser_helpers.c +1 -2
  63. data/src/parser.c +6 -7
  64. data/src/parser_options_defaults.c +1 -0
  65. data/src/prism/prism_helpers.c +84 -50
  66. data/src/prism/ruby_parser.c +20 -20
  67. data/templates/ext/herb/nodes.c.erb +5 -5
  68. data/templates/ext/herb/parser_options_helpers.c.erb +33 -0
  69. data/templates/java/nodes.c.erb +6 -6
  70. data/templates/java/parser_options_helpers.c.erb +41 -2
  71. data/templates/java/parser_options_helpers.h.erb +2 -1
  72. data/templates/javascript/packages/node/extension/nodes.cpp.erb +5 -5
  73. data/templates/javascript/packages/node/extension/parser_options_helpers.cpp.erb +34 -2
  74. data/templates/javascript/packages/node/extension/parser_options_helpers.h.erb +1 -1
  75. data/templates/lib/herb/parser_options.rb.erb +1 -1
  76. data/templates/rust/src/prism/generated_deserialize.rs.erb +90 -44
  77. data/templates/rust/src/prism/generated_prettyprint.rs.erb +18 -27
  78. data/templates/src/analyze/action_view/generated_handlers.c.erb +23 -22
  79. data/templates/src/include/parser/parser_options.h.erb +10 -0
  80. data/templates/src/include/prism_version.h.erb +17 -0
  81. data/templates/src/parser_options_defaults.c.erb +1 -1
  82. data/templates/template.rb +17 -2
  83. data/templates/wasm/nodes.cpp.erb +5 -5
  84. data/templates/wasm/parser_options_helpers.cpp.erb +24 -0
  85. data/vendor/prism/Rakefile +76 -7
  86. data/vendor/prism/config.yml +174 -161
  87. data/vendor/prism/include/prism/arena.h +45 -0
  88. data/vendor/prism/include/prism/arena.hpp +42 -0
  89. data/vendor/prism/include/prism/ast.h +2738 -611
  90. data/vendor/prism/include/prism/ast.hpp +641 -0
  91. data/vendor/prism/include/prism/buffer.h +60 -0
  92. data/vendor/prism/include/prism/buffer.hpp +55 -0
  93. data/vendor/prism/include/prism/comments.h +72 -0
  94. data/vendor/prism/include/prism/compiler/accel.h +26 -0
  95. data/vendor/prism/include/prism/compiler/align.h +36 -0
  96. data/vendor/prism/include/prism/compiler/assume.h +25 -0
  97. data/vendor/prism/include/prism/compiler/branch.h +26 -0
  98. data/vendor/prism/include/prism/compiler/bswap.h +46 -0
  99. data/vendor/prism/include/prism/compiler/cplusplus.hpp +16 -0
  100. data/vendor/prism/include/prism/compiler/endianness.h +34 -0
  101. data/vendor/prism/include/prism/compiler/exceptions.hpp +17 -0
  102. data/vendor/prism/include/prism/compiler/exported.h +24 -0
  103. data/vendor/prism/include/prism/compiler/fallthrough.h +22 -0
  104. data/vendor/prism/include/prism/compiler/filesystem.h +32 -0
  105. data/vendor/prism/include/prism/compiler/flex_array.h +19 -0
  106. data/vendor/prism/include/prism/compiler/force_inline.h +21 -0
  107. data/vendor/prism/include/prism/compiler/format.h +27 -0
  108. data/vendor/prism/include/prism/compiler/inline.h +17 -0
  109. data/vendor/prism/include/prism/compiler/lifetimebound.hpp +25 -0
  110. data/vendor/prism/include/prism/compiler/nodiscard.h +22 -0
  111. data/vendor/prism/include/prism/compiler/nonnull.h +18 -0
  112. data/vendor/prism/include/prism/compiler/unused.h +18 -0
  113. data/vendor/prism/include/prism/constant_pool.h +106 -0
  114. data/vendor/prism/include/prism/diagnostic.h +55 -402
  115. data/vendor/prism/include/prism/errors_format.h +61 -0
  116. data/vendor/prism/include/prism/excludes.h +29 -0
  117. data/vendor/prism/include/prism/integer.h +41 -0
  118. data/vendor/prism/include/prism/internal/allocator.h +68 -0
  119. data/vendor/prism/include/prism/internal/allocator_debug.h +88 -0
  120. data/vendor/prism/include/prism/internal/arena.h +108 -0
  121. data/vendor/prism/include/prism/internal/bit.h +42 -0
  122. data/vendor/prism/include/prism/internal/buffer.h +94 -0
  123. data/vendor/prism/include/prism/internal/char.h +145 -0
  124. data/vendor/prism/include/prism/internal/comments.h +54 -0
  125. data/vendor/prism/include/prism/internal/constant_pool.h +152 -0
  126. data/vendor/prism/include/prism/internal/diagnostic.h +389 -0
  127. data/vendor/prism/include/prism/{encoding.h → internal/encoding.h} +27 -68
  128. data/vendor/prism/include/prism/internal/integer.h +68 -0
  129. data/vendor/prism/include/prism/internal/isinf.h +16 -0
  130. data/vendor/prism/include/prism/internal/line_offset_list.h +34 -0
  131. data/vendor/prism/include/prism/{util/pm_list.h → internal/list.h} +11 -52
  132. data/vendor/prism/include/prism/internal/magic_comments.h +23 -0
  133. data/vendor/prism/include/prism/internal/memchr.h +15 -0
  134. data/vendor/prism/include/prism/internal/node.h +42 -0
  135. data/vendor/prism/include/prism/internal/options.h +232 -0
  136. data/vendor/prism/include/prism/internal/parser.h +1015 -0
  137. data/vendor/prism/include/prism/internal/regexp.h +26 -0
  138. data/vendor/prism/include/prism/internal/serialize.h +39 -0
  139. data/vendor/prism/include/prism/internal/source.h +72 -0
  140. data/vendor/prism/include/prism/internal/static_literals.h +60 -0
  141. data/vendor/prism/include/prism/internal/stringy.h +30 -0
  142. data/vendor/prism/include/prism/{util/pm_strncasecmp.h → internal/strncasecmp.h} +3 -17
  143. data/vendor/prism/include/prism/{util/pm_strpbrk.h → internal/strpbrk.h} +7 -20
  144. data/vendor/prism/include/prism/internal/tokens.h +11 -0
  145. data/vendor/prism/include/prism/internal/xxh3.h +16 -0
  146. data/vendor/prism/include/prism/json.h +40 -0
  147. data/vendor/prism/include/prism/line_offset_list.h +69 -0
  148. data/vendor/prism/include/prism/magic_comments.h +53 -0
  149. data/vendor/prism/include/prism/node.h +59 -49
  150. data/vendor/prism/include/prism/node.hpp +272 -0
  151. data/vendor/prism/include/prism/node_type.hpp +38 -0
  152. data/vendor/prism/include/prism/options.h +154 -279
  153. data/vendor/prism/include/prism/options.hpp +43 -0
  154. data/vendor/prism/include/prism/parser.h +367 -870
  155. data/vendor/prism/include/prism/parser.hpp +274 -0
  156. data/vendor/prism/include/prism/prettyprint.h +14 -9
  157. data/vendor/prism/include/prism/serialize.h +123 -0
  158. data/vendor/prism/include/prism/source.h +163 -0
  159. data/vendor/prism/include/prism/stream.h +36 -0
  160. data/vendor/prism/include/prism/string_query.h +82 -0
  161. data/vendor/prism/include/prism/stringy.h +61 -0
  162. data/vendor/prism/include/prism/stringy.hpp +31 -0
  163. data/vendor/prism/include/prism/version.h +20 -3
  164. data/vendor/prism/include/prism.h +35 -320
  165. data/vendor/prism/include/prism.hpp +24 -0
  166. data/vendor/prism/src/arena.c +122 -0
  167. data/vendor/prism/src/{util/pm_buffer.c → buffer.c} +53 -21
  168. data/vendor/prism/src/{util/pm_char.c → char.c} +28 -57
  169. data/vendor/prism/src/comments.c +455 -0
  170. data/vendor/prism/src/constant_pool.c +406 -0
  171. data/vendor/prism/src/diagnostic.c +120 -68
  172. data/vendor/prism/src/encoding.c +8 -3
  173. data/vendor/prism/src/errors_format.c +519 -0
  174. data/vendor/prism/src/{util/pm_integer.c → integer.c} +38 -22
  175. data/vendor/prism/src/json.c +5733 -0
  176. data/vendor/prism/src/line_offset_list.c +100 -0
  177. data/vendor/prism/src/list.c +24 -0
  178. data/vendor/prism/src/{util/pm_memchr.c → memchr.c} +8 -6
  179. data/vendor/prism/src/node.c +3465 -7787
  180. data/vendor/prism/src/options.c +161 -54
  181. data/vendor/prism/src/parser.c +371 -0
  182. data/vendor/prism/src/prettyprint.c +421 -354
  183. data/vendor/prism/src/prism.c +8522 -7280
  184. data/vendor/prism/src/regexp.c +960 -45
  185. data/vendor/prism/src/serialize.c +2434 -2048
  186. data/vendor/prism/src/source.c +524 -0
  187. data/vendor/prism/src/static_literals.c +303 -360
  188. data/vendor/prism/src/string_query.c +180 -0
  189. data/vendor/prism/src/stringy.c +61 -0
  190. data/vendor/prism/src/{util/pm_strncasecmp.c → strncasecmp.c} +5 -4
  191. data/vendor/prism/src/strpbrk.c +447 -0
  192. data/vendor/prism/src/{token_type.c → tokens.c} +39 -18
  193. data/vendor/prism/src/xxh3.c +292 -0
  194. data/vendor/prism/templates/ext/prism/api_node.c.erb +58 -44
  195. data/vendor/prism/templates/include/prism/ast.h.erb +67 -17
  196. data/vendor/prism/templates/include/prism/ast.hpp.erb +31 -0
  197. data/vendor/prism/templates/include/prism/internal/diagnostic.h.erb +60 -0
  198. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/AbstractNodeVisitor.java.erb +1 -1
  199. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Loader.java.erb +232 -133
  200. data/vendor/prism/templates/java/{org → api/src/main/java-templates/org/ruby_lang}/prism/Nodes.java.erb +62 -23
  201. data/vendor/prism/templates/javascript/src/deserialize.js.erb +153 -146
  202. data/vendor/prism/templates/javascript/src/nodes.js.erb +4 -9
  203. data/vendor/prism/templates/lib/prism/compiler.rb.erb +14 -5
  204. data/vendor/prism/templates/lib/prism/dispatcher.rb.erb +20 -12
  205. data/vendor/prism/templates/lib/prism/dot_visitor.rb.erb +37 -11
  206. data/vendor/prism/templates/lib/prism/dsl.rb.erb +43 -4
  207. data/vendor/prism/templates/lib/prism/inspect_visitor.rb.erb +26 -10
  208. data/vendor/prism/templates/lib/prism/mutation_compiler.rb.erb +5 -2
  209. data/vendor/prism/templates/lib/prism/node.rb.erb +283 -105
  210. data/vendor/prism/templates/lib/prism/reflection.rb.erb +11 -2
  211. data/vendor/prism/templates/lib/prism/serialize.rb.erb +291 -134
  212. data/vendor/prism/templates/lib/prism/visitor.rb.erb +18 -0
  213. data/vendor/prism/templates/src/diagnostic.c.erb +114 -63
  214. data/vendor/prism/templates/src/json.c.erb +130 -0
  215. data/vendor/prism/templates/src/node.c.erb +79 -236
  216. data/vendor/prism/templates/src/prettyprint.c.erb +24 -13
  217. data/vendor/prism/templates/src/serialize.c.erb +369 -183
  218. data/vendor/prism/templates/src/{token_type.c.erb → tokens.c.erb} +22 -11
  219. data/vendor/prism/templates/template.rb +193 -91
  220. metadata +100 -42
  221. data/vendor/prism/include/prism/defines.h +0 -260
  222. data/vendor/prism/include/prism/pack.h +0 -163
  223. data/vendor/prism/include/prism/regexp.h +0 -43
  224. data/vendor/prism/include/prism/static_literals.h +0 -121
  225. data/vendor/prism/include/prism/util/pm_buffer.h +0 -236
  226. data/vendor/prism/include/prism/util/pm_char.h +0 -204
  227. data/vendor/prism/include/prism/util/pm_constant_pool.h +0 -218
  228. data/vendor/prism/include/prism/util/pm_integer.h +0 -130
  229. data/vendor/prism/include/prism/util/pm_memchr.h +0 -29
  230. data/vendor/prism/include/prism/util/pm_newline_list.h +0 -113
  231. data/vendor/prism/include/prism/util/pm_string.h +0 -200
  232. data/vendor/prism/src/pack.c +0 -509
  233. data/vendor/prism/src/util/pm_constant_pool.c +0 -342
  234. data/vendor/prism/src/util/pm_list.c +0 -49
  235. data/vendor/prism/src/util/pm_newline_list.c +0 -125
  236. data/vendor/prism/src/util/pm_string.c +0 -381
  237. data/vendor/prism/src/util/pm_strpbrk.c +0 -206
  238. data/vendor/prism/templates/include/prism/diagnostic.h.erb +0 -130
  239. data/vendor/prism/templates/rbi/prism/dsl.rbi.erb +0 -68
  240. data/vendor/prism/templates/rbi/prism/node.rbi.erb +0 -167
  241. data/vendor/prism/templates/rbi/prism/visitor.rbi.erb +0 -18
  242. data/vendor/prism/templates/sig/prism/_private/dot_visitor.rbs.erb +0 -45
  243. data/vendor/prism/templates/sig/prism/dsl.rbs.erb +0 -31
  244. data/vendor/prism/templates/sig/prism/mutation_compiler.rbs.erb +0 -7
  245. data/vendor/prism/templates/sig/prism/node.rbs.erb +0 -136
  246. data/vendor/prism/templates/sig/prism/visitor.rbs.erb +0 -17
  247. data/vendor/prism/templates/sig/prism.rbs.erb +0 -92
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f46fd278cb8e2a63d2b01da3f6774ba977468011af8f7b7a507c93ec5bec185
4
- data.tar.gz: f79d15dfe1eb91d3043c5bb68afc10c0bff3192d2b803e43da90a1c598ca5220
3
+ metadata.gz: 8111ad1345234b5a96f1160876dd46d1c2ff7ed7909d6911231304ce2d21f633
4
+ data.tar.gz: 83b468456e7460ced71ee1db276e3a4be294e3c0fcae2c562b8b6eabfe812e91
5
5
  SHA512:
6
- metadata.gz: 400ea668d34d47125d14c9d993001285ce8cff47a35c7452954b9196bcea8e1ec592dff0fa237060fa3106470ef63edbe3c78da96101ce9b308fe65fc802db52
7
- data.tar.gz: f6df589dbc62c39b363c61aedb0f7e18f5b6f42021b6b76c91ae291f0d2de022957156c0ddfb72dac6d50343891c718af652f822882b7b755f4cefbe4c4aa9cc
6
+ metadata.gz: 1e6e97ebf077cbe5d13b899396b0bda7e41738792660a1fb9f0ae4e9eb94085a4166d88ca11a83e8348d159c41b64b7e8073b8a94729b396003633cbc9d90ac5
7
+ data.tar.gz: 600f96a221124533f445e9df3f8eeed0600b69811c0c8852d861aa33bfa4fedd5632f1cde1d11284afc6bbb006d7a5776251fae5bcb6a05f6091fcb2dc47b476
data/Rakefile CHANGED
@@ -7,7 +7,8 @@ require "rake/testtask"
7
7
  Rake::TestTask.new(:test) do |t|
8
8
  t.libs << "test"
9
9
  t.libs << "lib"
10
- t.test_files = FileList["test/**/*_test.rb"]
10
+ # TODO: Drop the `test/rubocop` exclusion once https://github.com/rubocop/rubocop-ast/pull/420 is released and RuboCop is back in the main `Gemfile`.
11
+ t.test_files = FileList["test/**/*_test.rb"].exclude("test/rubocop/**/*")
11
12
  end
12
13
 
13
14
  Rake::TestTask.new("test:engine") do |t|
@@ -25,7 +26,8 @@ end
25
26
  Rake::TestTask.new("test:all") do |t|
26
27
  t.libs << "test"
27
28
  t.libs << "lib"
28
- t.test_files = FileList["test/**/*_test.rb"]
29
+ # TODO: Drop the `test/rubocop` exclusion once https://github.com/rubocop/rubocop-ast/pull/420 is released and RuboCop is back in the main `Gemfile`.
30
+ t.test_files = FileList["test/**/*_test.rb"].exclude("test/rubocop/**/*")
29
31
  end
30
32
 
31
33
  task "make" do
data/config.yml CHANGED
@@ -759,6 +759,12 @@ parser_options:
759
759
  default: false
760
760
  description: "Whether ActionView render call detection was enabled during parsing."
761
761
 
762
+ - name: "ruby_version"
763
+ type: "string"
764
+ default: "4.0"
765
+ validator: "herb_ruby_version_supported"
766
+ description: "Ruby version whose syntax Prism parses the ERB content with, such as `\"3.4\"`. Defaults to the latest released Ruby."
767
+
762
768
  - name: "strict"
763
769
  type: "boolean"
764
770
  default: true
data/ext/herb/extconf.rb CHANGED
@@ -11,6 +11,7 @@ if Herb::Bootstrap.git_source? && !Herb::Bootstrap.templates_generated?
11
11
  unless Herb::Bootstrap.prism_vendored?
12
12
  prism_path = Herb::Bootstrap.find_prism_gem_path
13
13
 
14
+ # TODO: Point this back at the `ruby/prism` release tag the `Gemfile` uses once it moves off the fork.
14
15
  abort <<~MSG unless prism_path
15
16
  ERROR: Could not find Prism C source files.
16
17
 
@@ -19,7 +20,7 @@ if Herb::Bootstrap.git_source? && !Herb::Bootstrap.templates_generated?
19
20
 
20
21
  Add it to your Gemfile before the herb git reference:
21
22
 
22
- gem "prism", github: "ruby/prism", tag: "v1.9.0"
23
+ gem "prism", github: "marcoroth/prism", ref: "4691667e2215831ae855add71d9925c0b871a709"
23
24
  gem "herb", github: "...", branch: "..."
24
25
 
25
26
  Then run `bundle install` again.
@@ -55,13 +56,10 @@ $VPATH << "$(srcdir)/../../src/parser"
55
56
  $VPATH << "$(srcdir)/../../src/prism"
56
57
  $VPATH << "$(srcdir)/../../src/lib"
57
58
  $VPATH << "$(srcdir)/../../src/util"
58
- $VPATH << prism_src_path
59
- $VPATH << "#{prism_src_path}/util"
60
59
 
61
60
  $INCFLAGS << " -I#{prism_include_path}"
62
61
  $INCFLAGS << " -I#{include_path}"
63
62
  $INCFLAGS << " -I#{prism_src_path}"
64
- $INCFLAGS << " -I#{prism_src_path}/util"
65
63
 
66
64
  $CFLAGS << " -fvisibility=hidden"
67
65
  $CFLAGS << " -DHERB_EXCLUDE_PRETTYPRINT"
@@ -71,32 +69,11 @@ $CFLAGS << " -DPRISM_EXCLUDE_PACK"
71
69
 
72
70
  herb_src_files = Dir.glob("#{$srcdir}/../../src/**/*.c").map { |file| file.delete_prefix("../../../../ext/herb/") }.sort
73
71
 
74
- prism_main_files = [
75
- "diagnostic.c",
76
- "encoding.c",
77
- "node.c",
78
- "options.c",
79
- "pack.c",
80
- "prettyprint.c",
81
- "prism.c",
82
- "regexp.c",
83
- "serialize.c",
84
- "static_literals.c",
85
- "token_type.c"
86
- ]
87
-
88
- prism_util_files = [
89
- "pm_buffer.c",
90
- "pm_char.c",
91
- "pm_constant_pool.c",
92
- "pm_integer.c",
93
- "pm_list.c",
94
- "pm_memchr.c",
95
- "pm_newline_list.c",
96
- "pm_string.c",
97
- "pm_strncasecmp.c",
98
- "pm_strpbrk.c"
99
- ]
72
+ prism_src_files = Dir.glob("#{prism_src_path}/*.c").map do |file|
73
+ wrapper = "prism_#{File.basename(file)}"
74
+ File.write(wrapper, "#include \"#{file}\"\n")
75
+ wrapper
76
+ end
100
77
 
101
78
  core_src_files = [
102
79
  "extension.c",
@@ -106,7 +83,7 @@ core_src_files = [
106
83
  "parser_options_helpers.c"
107
84
  ]
108
85
 
109
- $srcs = core_src_files + herb_src_files + prism_main_files + prism_util_files
86
+ $srcs = core_src_files + herb_src_files + prism_src_files
110
87
 
111
88
  puts "Sources to be compiled: #{$srcs.inspect}"
112
89
 
data/ext/herb/nodes.c CHANGED
@@ -140,17 +140,17 @@ static VALUE rb_document_node_from_c_struct(AST_DOCUMENT_NODE_T* document_node,
140
140
  VALUE document_node_prism_context = Qnil;
141
141
  VALUE document_node_prism_node;
142
142
  if (document_node->prism_node.node != NULL && document_node->prism_node.parser != NULL) {
143
- pm_buffer_t pm_buffer = { 0 };
144
- herb_prism_node_serialize(document_node->prism_node, &pm_buffer);
143
+ pm_buffer_t* pm_buffer = pm_buffer_new();
144
+ herb_prism_node_serialize(document_node->prism_node, pm_buffer);
145
145
 
146
- if (pm_buffer.length > 0) {
147
- document_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
146
+ if (pm_buffer_length(pm_buffer) > 0) {
147
+ document_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
148
148
  rb_enc_associate(document_node_prism_node, rb_ascii8bit_encoding());
149
149
  OBJ_FREEZE(document_node_prism_node);
150
150
  } else {
151
151
  document_node_prism_node = Qnil;
152
152
  }
153
- pm_buffer_free(&pm_buffer);
153
+ pm_buffer_free(pm_buffer);
154
154
  } else {
155
155
  document_node_prism_node = Qnil;
156
156
  }
@@ -820,17 +820,17 @@ static VALUE rb_erb_content_node_from_c_struct(AST_ERB_CONTENT_NODE_T* erb_conte
820
820
  VALUE erb_content_node_valid = (erb_content_node->valid) ? Qtrue : Qfalse;
821
821
  VALUE erb_content_node_prism_node;
822
822
  if (erb_content_node->prism_node.node != NULL && erb_content_node->prism_node.parser != NULL) {
823
- pm_buffer_t pm_buffer = { 0 };
824
- herb_prism_node_serialize(erb_content_node->prism_node, &pm_buffer);
823
+ pm_buffer_t* pm_buffer = pm_buffer_new();
824
+ herb_prism_node_serialize(erb_content_node->prism_node, pm_buffer);
825
825
 
826
- if (pm_buffer.length > 0) {
827
- erb_content_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
826
+ if (pm_buffer_length(pm_buffer) > 0) {
827
+ erb_content_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
828
828
  rb_enc_associate(erb_content_node_prism_node, rb_ascii8bit_encoding());
829
829
  OBJ_FREEZE(erb_content_node_prism_node);
830
830
  } else {
831
831
  erb_content_node_prism_node = Qnil;
832
832
  }
833
- pm_buffer_free(&pm_buffer);
833
+ pm_buffer_free(pm_buffer);
834
834
  } else {
835
835
  erb_content_node_prism_node = Qnil;
836
836
  }
@@ -933,17 +933,17 @@ static VALUE rb_erb_if_node_from_c_struct(AST_ERB_IF_NODE_T* erb_if_node, const
933
933
  VALUE erb_if_node_then_keyword = (options->track_locations && erb_if_node->then_keyword != NULL) ? rb_location_from_c_struct(*erb_if_node->then_keyword) : Qnil;
934
934
  VALUE erb_if_node_prism_node;
935
935
  if (erb_if_node->prism_node.node != NULL && erb_if_node->prism_node.parser != NULL) {
936
- pm_buffer_t pm_buffer = { 0 };
937
- herb_prism_node_serialize(erb_if_node->prism_node, &pm_buffer);
936
+ pm_buffer_t* pm_buffer = pm_buffer_new();
937
+ herb_prism_node_serialize(erb_if_node->prism_node, pm_buffer);
938
938
 
939
- if (pm_buffer.length > 0) {
940
- erb_if_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
939
+ if (pm_buffer_length(pm_buffer) > 0) {
940
+ erb_if_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
941
941
  rb_enc_associate(erb_if_node_prism_node, rb_ascii8bit_encoding());
942
942
  OBJ_FREEZE(erb_if_node_prism_node);
943
943
  } else {
944
944
  erb_if_node_prism_node = Qnil;
945
945
  }
946
- pm_buffer_free(&pm_buffer);
946
+ pm_buffer_free(pm_buffer);
947
947
  } else {
948
948
  erb_if_node_prism_node = Qnil;
949
949
  }
@@ -987,17 +987,17 @@ static VALUE rb_erb_block_node_from_c_struct(AST_ERB_BLOCK_NODE_T* erb_block_nod
987
987
  VALUE erb_block_node_tag_closing = rb_token_from_c_struct(erb_block_node->tag_closing, options);
988
988
  VALUE erb_block_node_prism_node;
989
989
  if (erb_block_node->prism_node.node != NULL && erb_block_node->prism_node.parser != NULL) {
990
- pm_buffer_t pm_buffer = { 0 };
991
- herb_prism_node_serialize(erb_block_node->prism_node, &pm_buffer);
990
+ pm_buffer_t* pm_buffer = pm_buffer_new();
991
+ herb_prism_node_serialize(erb_block_node->prism_node, pm_buffer);
992
992
 
993
- if (pm_buffer.length > 0) {
994
- erb_block_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
993
+ if (pm_buffer_length(pm_buffer) > 0) {
994
+ erb_block_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
995
995
  rb_enc_associate(erb_block_node_prism_node, rb_ascii8bit_encoding());
996
996
  OBJ_FREEZE(erb_block_node_prism_node);
997
997
  } else {
998
998
  erb_block_node_prism_node = Qnil;
999
999
  }
1000
- pm_buffer_free(&pm_buffer);
1000
+ pm_buffer_free(pm_buffer);
1001
1001
  } else {
1002
1002
  erb_block_node_prism_node = Qnil;
1003
1003
  }
@@ -1046,17 +1046,17 @@ static VALUE rb_erb_iteration_block_node_from_c_struct(AST_ERB_ITERATION_BLOCK_N
1046
1046
  VALUE erb_iteration_block_node_tag_closing = rb_token_from_c_struct(erb_iteration_block_node->tag_closing, options);
1047
1047
  VALUE erb_iteration_block_node_prism_node;
1048
1048
  if (erb_iteration_block_node->prism_node.node != NULL && erb_iteration_block_node->prism_node.parser != NULL) {
1049
- pm_buffer_t pm_buffer = { 0 };
1050
- herb_prism_node_serialize(erb_iteration_block_node->prism_node, &pm_buffer);
1049
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1050
+ herb_prism_node_serialize(erb_iteration_block_node->prism_node, pm_buffer);
1051
1051
 
1052
- if (pm_buffer.length > 0) {
1053
- erb_iteration_block_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1052
+ if (pm_buffer_length(pm_buffer) > 0) {
1053
+ erb_iteration_block_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1054
1054
  rb_enc_associate(erb_iteration_block_node_prism_node, rb_ascii8bit_encoding());
1055
1055
  OBJ_FREEZE(erb_iteration_block_node_prism_node);
1056
1056
  } else {
1057
1057
  erb_iteration_block_node_prism_node = Qnil;
1058
1058
  }
1059
- pm_buffer_free(&pm_buffer);
1059
+ pm_buffer_free(pm_buffer);
1060
1060
  } else {
1061
1061
  erb_iteration_block_node_prism_node = Qnil;
1062
1062
  }
@@ -1150,17 +1150,17 @@ static VALUE rb_erb_case_node_from_c_struct(AST_ERB_CASE_NODE_T* erb_case_node,
1150
1150
  VALUE erb_case_node_children = rb_nodes_array_from_c_array(erb_case_node->children, options);
1151
1151
  VALUE erb_case_node_prism_node;
1152
1152
  if (erb_case_node->prism_node.node != NULL && erb_case_node->prism_node.parser != NULL) {
1153
- pm_buffer_t pm_buffer = { 0 };
1154
- herb_prism_node_serialize(erb_case_node->prism_node, &pm_buffer);
1153
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1154
+ herb_prism_node_serialize(erb_case_node->prism_node, pm_buffer);
1155
1155
 
1156
- if (pm_buffer.length > 0) {
1157
- erb_case_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1156
+ if (pm_buffer_length(pm_buffer) > 0) {
1157
+ erb_case_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1158
1158
  rb_enc_associate(erb_case_node_prism_node, rb_ascii8bit_encoding());
1159
1159
  OBJ_FREEZE(erb_case_node_prism_node);
1160
1160
  } else {
1161
1161
  erb_case_node_prism_node = Qnil;
1162
1162
  }
1163
- pm_buffer_free(&pm_buffer);
1163
+ pm_buffer_free(pm_buffer);
1164
1164
  } else {
1165
1165
  erb_case_node_prism_node = Qnil;
1166
1166
  }
@@ -1205,17 +1205,17 @@ static VALUE rb_erb_case_match_node_from_c_struct(AST_ERB_CASE_MATCH_NODE_T* erb
1205
1205
  VALUE erb_case_match_node_children = rb_nodes_array_from_c_array(erb_case_match_node->children, options);
1206
1206
  VALUE erb_case_match_node_prism_node;
1207
1207
  if (erb_case_match_node->prism_node.node != NULL && erb_case_match_node->prism_node.parser != NULL) {
1208
- pm_buffer_t pm_buffer = { 0 };
1209
- herb_prism_node_serialize(erb_case_match_node->prism_node, &pm_buffer);
1208
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1209
+ herb_prism_node_serialize(erb_case_match_node->prism_node, pm_buffer);
1210
1210
 
1211
- if (pm_buffer.length > 0) {
1212
- erb_case_match_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1211
+ if (pm_buffer_length(pm_buffer) > 0) {
1212
+ erb_case_match_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1213
1213
  rb_enc_associate(erb_case_match_node_prism_node, rb_ascii8bit_encoding());
1214
1214
  OBJ_FREEZE(erb_case_match_node_prism_node);
1215
1215
  } else {
1216
1216
  erb_case_match_node_prism_node = Qnil;
1217
1217
  }
1218
- pm_buffer_free(&pm_buffer);
1218
+ pm_buffer_free(pm_buffer);
1219
1219
  } else {
1220
1220
  erb_case_match_node_prism_node = Qnil;
1221
1221
  }
@@ -1259,17 +1259,17 @@ static VALUE rb_erb_while_node_from_c_struct(AST_ERB_WHILE_NODE_T* erb_while_nod
1259
1259
  VALUE erb_while_node_tag_closing = rb_token_from_c_struct(erb_while_node->tag_closing, options);
1260
1260
  VALUE erb_while_node_prism_node;
1261
1261
  if (erb_while_node->prism_node.node != NULL && erb_while_node->prism_node.parser != NULL) {
1262
- pm_buffer_t pm_buffer = { 0 };
1263
- herb_prism_node_serialize(erb_while_node->prism_node, &pm_buffer);
1262
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1263
+ herb_prism_node_serialize(erb_while_node->prism_node, pm_buffer);
1264
1264
 
1265
- if (pm_buffer.length > 0) {
1266
- erb_while_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1265
+ if (pm_buffer_length(pm_buffer) > 0) {
1266
+ erb_while_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1267
1267
  rb_enc_associate(erb_while_node_prism_node, rb_ascii8bit_encoding());
1268
1268
  OBJ_FREEZE(erb_while_node_prism_node);
1269
1269
  } else {
1270
1270
  erb_while_node_prism_node = Qnil;
1271
1271
  }
1272
- pm_buffer_free(&pm_buffer);
1272
+ pm_buffer_free(pm_buffer);
1273
1273
  } else {
1274
1274
  erb_while_node_prism_node = Qnil;
1275
1275
  }
@@ -1310,17 +1310,17 @@ static VALUE rb_erb_until_node_from_c_struct(AST_ERB_UNTIL_NODE_T* erb_until_nod
1310
1310
  VALUE erb_until_node_tag_closing = rb_token_from_c_struct(erb_until_node->tag_closing, options);
1311
1311
  VALUE erb_until_node_prism_node;
1312
1312
  if (erb_until_node->prism_node.node != NULL && erb_until_node->prism_node.parser != NULL) {
1313
- pm_buffer_t pm_buffer = { 0 };
1314
- herb_prism_node_serialize(erb_until_node->prism_node, &pm_buffer);
1313
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1314
+ herb_prism_node_serialize(erb_until_node->prism_node, pm_buffer);
1315
1315
 
1316
- if (pm_buffer.length > 0) {
1317
- erb_until_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1316
+ if (pm_buffer_length(pm_buffer) > 0) {
1317
+ erb_until_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1318
1318
  rb_enc_associate(erb_until_node_prism_node, rb_ascii8bit_encoding());
1319
1319
  OBJ_FREEZE(erb_until_node_prism_node);
1320
1320
  } else {
1321
1321
  erb_until_node_prism_node = Qnil;
1322
1322
  }
1323
- pm_buffer_free(&pm_buffer);
1323
+ pm_buffer_free(pm_buffer);
1324
1324
  } else {
1325
1325
  erb_until_node_prism_node = Qnil;
1326
1326
  }
@@ -1361,17 +1361,17 @@ static VALUE rb_erb_for_node_from_c_struct(AST_ERB_FOR_NODE_T* erb_for_node, con
1361
1361
  VALUE erb_for_node_tag_closing = rb_token_from_c_struct(erb_for_node->tag_closing, options);
1362
1362
  VALUE erb_for_node_prism_node;
1363
1363
  if (erb_for_node->prism_node.node != NULL && erb_for_node->prism_node.parser != NULL) {
1364
- pm_buffer_t pm_buffer = { 0 };
1365
- herb_prism_node_serialize(erb_for_node->prism_node, &pm_buffer);
1364
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1365
+ herb_prism_node_serialize(erb_for_node->prism_node, pm_buffer);
1366
1366
 
1367
- if (pm_buffer.length > 0) {
1368
- erb_for_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1367
+ if (pm_buffer_length(pm_buffer) > 0) {
1368
+ erb_for_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1369
1369
  rb_enc_associate(erb_for_node_prism_node, rb_ascii8bit_encoding());
1370
1370
  OBJ_FREEZE(erb_for_node_prism_node);
1371
1371
  } else {
1372
1372
  erb_for_node_prism_node = Qnil;
1373
1373
  }
1374
- pm_buffer_free(&pm_buffer);
1374
+ pm_buffer_free(pm_buffer);
1375
1375
  } else {
1376
1376
  erb_for_node_prism_node = Qnil;
1377
1377
  }
@@ -1478,17 +1478,17 @@ static VALUE rb_erb_begin_node_from_c_struct(AST_ERB_BEGIN_NODE_T* erb_begin_nod
1478
1478
  VALUE erb_begin_node_tag_closing = rb_token_from_c_struct(erb_begin_node->tag_closing, options);
1479
1479
  VALUE erb_begin_node_prism_node;
1480
1480
  if (erb_begin_node->prism_node.node != NULL && erb_begin_node->prism_node.parser != NULL) {
1481
- pm_buffer_t pm_buffer = { 0 };
1482
- herb_prism_node_serialize(erb_begin_node->prism_node, &pm_buffer);
1481
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1482
+ herb_prism_node_serialize(erb_begin_node->prism_node, pm_buffer);
1483
1483
 
1484
- if (pm_buffer.length > 0) {
1485
- erb_begin_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1484
+ if (pm_buffer_length(pm_buffer) > 0) {
1485
+ erb_begin_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1486
1486
  rb_enc_associate(erb_begin_node_prism_node, rb_ascii8bit_encoding());
1487
1487
  OBJ_FREEZE(erb_begin_node_prism_node);
1488
1488
  } else {
1489
1489
  erb_begin_node_prism_node = Qnil;
1490
1490
  }
1491
- pm_buffer_free(&pm_buffer);
1491
+ pm_buffer_free(pm_buffer);
1492
1492
  } else {
1493
1493
  erb_begin_node_prism_node = Qnil;
1494
1494
  }
@@ -1536,17 +1536,17 @@ static VALUE rb_erb_unless_node_from_c_struct(AST_ERB_UNLESS_NODE_T* erb_unless_
1536
1536
  VALUE erb_unless_node_then_keyword = (options->track_locations && erb_unless_node->then_keyword != NULL) ? rb_location_from_c_struct(*erb_unless_node->then_keyword) : Qnil;
1537
1537
  VALUE erb_unless_node_prism_node;
1538
1538
  if (erb_unless_node->prism_node.node != NULL && erb_unless_node->prism_node.parser != NULL) {
1539
- pm_buffer_t pm_buffer = { 0 };
1540
- herb_prism_node_serialize(erb_unless_node->prism_node, &pm_buffer);
1539
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1540
+ herb_prism_node_serialize(erb_unless_node->prism_node, pm_buffer);
1541
1541
 
1542
- if (pm_buffer.length > 0) {
1543
- erb_unless_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1542
+ if (pm_buffer_length(pm_buffer) > 0) {
1543
+ erb_unless_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1544
1544
  rb_enc_associate(erb_unless_node_prism_node, rb_ascii8bit_encoding());
1545
1545
  OBJ_FREEZE(erb_unless_node_prism_node);
1546
1546
  } else {
1547
1547
  erb_unless_node_prism_node = Qnil;
1548
1548
  }
1549
- pm_buffer_free(&pm_buffer);
1549
+ pm_buffer_free(pm_buffer);
1550
1550
  } else {
1551
1551
  erb_unless_node_prism_node = Qnil;
1552
1552
  }
@@ -1684,17 +1684,17 @@ static VALUE rb_erb_render_node_from_c_struct(AST_ERB_RENDER_NODE_T* erb_render_
1684
1684
  VALUE erb_render_node_analyzed_ruby = Qnil;
1685
1685
  VALUE erb_render_node_prism_node;
1686
1686
  if (erb_render_node->prism_node.node != NULL && erb_render_node->prism_node.parser != NULL) {
1687
- pm_buffer_t pm_buffer = { 0 };
1688
- herb_prism_node_serialize(erb_render_node->prism_node, &pm_buffer);
1687
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1688
+ herb_prism_node_serialize(erb_render_node->prism_node, pm_buffer);
1689
1689
 
1690
- if (pm_buffer.length > 0) {
1691
- erb_render_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1690
+ if (pm_buffer_length(pm_buffer) > 0) {
1691
+ erb_render_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1692
1692
  rb_enc_associate(erb_render_node_prism_node, rb_ascii8bit_encoding());
1693
1693
  OBJ_FREEZE(erb_render_node_prism_node);
1694
1694
  } else {
1695
1695
  erb_render_node_prism_node = Qnil;
1696
1696
  }
1697
- pm_buffer_free(&pm_buffer);
1697
+ pm_buffer_free(pm_buffer);
1698
1698
  } else {
1699
1699
  erb_render_node_prism_node = Qnil;
1700
1700
  }
@@ -1780,17 +1780,17 @@ static VALUE rb_erb_strict_locals_node_from_c_struct(AST_ERB_STRICT_LOCALS_NODE_
1780
1780
  VALUE erb_strict_locals_node_analyzed_ruby = Qnil;
1781
1781
  VALUE erb_strict_locals_node_prism_node;
1782
1782
  if (erb_strict_locals_node->prism_node.node != NULL && erb_strict_locals_node->prism_node.parser != NULL) {
1783
- pm_buffer_t pm_buffer = { 0 };
1784
- herb_prism_node_serialize(erb_strict_locals_node->prism_node, &pm_buffer);
1783
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1784
+ herb_prism_node_serialize(erb_strict_locals_node->prism_node, pm_buffer);
1785
1785
 
1786
- if (pm_buffer.length > 0) {
1787
- erb_strict_locals_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1786
+ if (pm_buffer_length(pm_buffer) > 0) {
1787
+ erb_strict_locals_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1788
1788
  rb_enc_associate(erb_strict_locals_node_prism_node, rb_ascii8bit_encoding());
1789
1789
  OBJ_FREEZE(erb_strict_locals_node_prism_node);
1790
1790
  } else {
1791
1791
  erb_strict_locals_node_prism_node = Qnil;
1792
1792
  }
1793
- pm_buffer_free(&pm_buffer);
1793
+ pm_buffer_free(pm_buffer);
1794
1794
  } else {
1795
1795
  erb_strict_locals_node_prism_node = Qnil;
1796
1796
  }
@@ -1830,17 +1830,17 @@ static VALUE rb_erb_yield_node_from_c_struct(AST_ERB_YIELD_NODE_T* erb_yield_nod
1830
1830
  VALUE erb_yield_node_tag_closing = rb_token_from_c_struct(erb_yield_node->tag_closing, options);
1831
1831
  VALUE erb_yield_node_prism_node;
1832
1832
  if (erb_yield_node->prism_node.node != NULL && erb_yield_node->prism_node.parser != NULL) {
1833
- pm_buffer_t pm_buffer = { 0 };
1834
- herb_prism_node_serialize(erb_yield_node->prism_node, &pm_buffer);
1833
+ pm_buffer_t* pm_buffer = pm_buffer_new();
1834
+ herb_prism_node_serialize(erb_yield_node->prism_node, pm_buffer);
1835
1835
 
1836
- if (pm_buffer.length > 0) {
1837
- erb_yield_node_prism_node = rb_str_new(pm_buffer.value, pm_buffer.length);
1836
+ if (pm_buffer_length(pm_buffer) > 0) {
1837
+ erb_yield_node_prism_node = rb_str_new(pm_buffer_value(pm_buffer), pm_buffer_length(pm_buffer));
1838
1838
  rb_enc_associate(erb_yield_node_prism_node, rb_ascii8bit_encoding());
1839
1839
  OBJ_FREEZE(erb_yield_node_prism_node);
1840
1840
  } else {
1841
1841
  erb_yield_node_prism_node = Qnil;
1842
1842
  }
1843
- pm_buffer_free(&pm_buffer);
1843
+ pm_buffer_free(pm_buffer);
1844
1844
  } else {
1845
1845
  erb_yield_node_prism_node = Qnil;
1846
1846
  }
@@ -3,6 +3,8 @@
3
3
 
4
4
  #include "parser_options_helpers.h"
5
5
 
6
+ #include <string.h>
7
+
6
8
  void herb_extract_parser_options(VALUE options, parser_options_T* parser_options) {
7
9
  if (NIL_P(options)) { return; }
8
10
 
@@ -74,6 +76,25 @@ void herb_extract_parser_options(VALUE options, parser_options_T* parser_options
74
76
  if (!NIL_P(value)) { parser_options->render_nodes = RTEST(value); }
75
77
  }
76
78
 
79
+ {
80
+ VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("ruby_version"));
81
+ if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("ruby_version"))); }
82
+
83
+ if (!NIL_P(value)) {
84
+ Check_Type(value, T_STRING);
85
+
86
+ const char* data = RSTRING_PTR(value);
87
+ size_t length = (size_t) RSTRING_LEN(value);
88
+
89
+ if (!herb_ruby_version_supported(data, length)) {
90
+ rb_raise(rb_eArgError, "ruby_version %+" PRIsVALUE " is not supported", value);
91
+ }
92
+
93
+ memcpy(parser_options->ruby_version, data, length);
94
+ parser_options->ruby_version[length] = '\0';
95
+ }
96
+ }
97
+
77
98
  {
78
99
  VALUE value = rb_hash_lookup(options, rb_utf8_str_new_cstr("strict"));
79
100
  if (NIL_P(value)) { value = rb_hash_lookup(options, ID2SYM(rb_intern("strict"))); }
@@ -140,6 +161,11 @@ VALUE herb_build_parser_options_hash(const parser_options_T* options) {
140
161
  rb_hash_aset(kwargs, ID2SYM(rb_intern("prism_nodes_deep")), options->prism_nodes_deep ? Qtrue : Qfalse);
141
162
  rb_hash_aset(kwargs, ID2SYM(rb_intern("prism_program")), options->prism_program ? Qtrue : Qfalse);
142
163
  rb_hash_aset(kwargs, ID2SYM(rb_intern("render_nodes")), options->render_nodes ? Qtrue : Qfalse);
164
+ rb_hash_aset(
165
+ kwargs,
166
+ ID2SYM(rb_intern("ruby_version")),
167
+ options->ruby_version[0] == '\0' ? Qnil : rb_utf8_str_new_cstr(options->ruby_version)
168
+ );
143
169
  rb_hash_aset(kwargs, ID2SYM(rb_intern("strict")), options->strict ? Qtrue : Qfalse);
144
170
  rb_hash_aset(kwargs, ID2SYM(rb_intern("strict_locals")), options->strict_locals ? Qtrue : Qfalse);
145
171
  rb_hash_aset(kwargs, ID2SYM(rb_intern("timeout")), DBL2NUM((double) options->timeout_ms / 1000.0));
@@ -83,7 +83,7 @@ module Herb
83
83
 
84
84
  #: (String?, String?) -> PartialDeclaration?
85
85
  def lookup(partial_name, source_file)
86
- file = resolve(partial_name, source_file).first
86
+ file = PartialResolution.preferred_for(resolve(partial_name, source_file), source_file)
87
87
 
88
88
  return nil unless file
89
89
 
@@ -6,6 +6,7 @@ module Herb
6
6
  module Analysis
7
7
  module PartialResolution
8
8
  PARTIAL_PREFIX = "_" #: String
9
+ VARIANT_SEPARATOR = "+" #: String
9
10
 
10
11
  EXTENSIONS = [
11
12
  ".html.erb",
@@ -84,6 +85,32 @@ module Herb
84
85
  files.sort { |a, b| outranks_template?(a, b) ? -1 : 1 }
85
86
  end
86
87
 
88
+ #: (String?) -> String?
89
+ def template_variant(file)
90
+ return nil unless file
91
+
92
+ basename = File.basename(file)
93
+ start = basename.index(VARIANT_SEPARATOR)
94
+
95
+ return nil unless start
96
+
97
+ variant = basename[(start + 1)..].to_s.sub(/\..*\z/, "")
98
+
99
+ variant.empty? ? nil : variant
100
+ end
101
+
102
+ #: (Array[String], String?) -> String?
103
+ def preferred_for(files, source_file)
104
+ variant = template_variant(source_file)
105
+
106
+ return files.first unless variant
107
+
108
+ matching = files.select { |file| template_variant(file) == variant }
109
+ preferred = matching.min_by { |file| [template_rank(File.basename(file).sub("#{VARIANT_SEPARATOR}#{variant}", "")), file] }
110
+
111
+ preferred || files.first
112
+ end
113
+
87
114
  #: (String, String | Pathname) -> String?
88
115
  def template_name_for(file, view_root)
89
116
  return nil if partial_path?(file)
@@ -32,7 +32,7 @@ module Herb
32
32
 
33
33
  opening = erb_opening(node)
34
34
 
35
- opening.start_with?("<%") && !erb_output?(opening) && !erb_comment?(opening)
35
+ opening.start_with?("<%") && !erb_output?(opening) && !erb_omitted?(opening)
36
36
  end
37
37
 
38
38
  #: (String) -> bool
@@ -100,11 +100,21 @@ module Herb
100
100
  parser["erb_openers"] || []
101
101
  end
102
102
 
103
+ #: () -> String?
104
+ def ruby_version
105
+ parser["ruby_version"]
106
+ end
107
+
103
108
  #: () -> Hash[Symbol, untyped]
104
109
  def parser_options
110
+ options = {} #: Hash[Symbol, untyped]
105
111
  openers = erb_openers
112
+ version = ruby_version
113
+
114
+ options[:erb_openers] = openers unless openers.empty?
115
+ options[:ruby_version] = version if version
106
116
 
107
- openers.empty? ? {} : { erb_openers: openers }
117
+ options
108
118
  end
109
119
 
110
120
  def linter
@@ -61,7 +61,7 @@ module Herb
61
61
 
62
62
  return classification(:whitespace, operations: operations) if significant.empty?
63
63
 
64
- kind = self.class.can_patch?(significant) && @parser_options.empty? ? :static : :dynamic
64
+ kind = self.class.can_patch?(significant) && @parser_options.except(:ruby_version).empty? ? :static : :dynamic
65
65
 
66
66
  classification(kind, operations: operations, node_path: covering_path(significant))
67
67
  end
@@ -875,10 +875,8 @@ module Herb
875
875
  @tokens << [:code, "#{effective_leading_space}#{code}#{right_space}", current_context]
876
876
  @trim_next_whitespace = true
877
877
 
878
- if right_space.end_with?(" \n")
879
- @pending_trim_newline_index = @tokens.length - 1
880
- @pending_trim_owns_next_whitespace = true
881
- end
878
+ @pending_trim_newline_index = @tokens.length - 1 if right_space.end_with?(" \n")
879
+ @pending_trim_owns_next_whitespace = true if right_space.end_with?(" \n") || without_source?(node)
882
880
  else
883
881
  @tokens << [:code, code, current_context]
884
882
  end
@@ -911,17 +909,16 @@ module Herb
911
909
  #: (bool) -> void
912
910
  def settle_pending_trim_newline!(keep)
913
911
  index = @pending_trim_newline_index
914
-
915
- return unless index
916
-
917
912
  owned = @pending_trim_owns_next_whitespace
918
913
 
914
+ return unless index || owned
915
+
919
916
  @pending_trim_newline_index = nil
920
917
  @pending_trim_owns_next_whitespace = false
921
918
 
922
919
  return if keep
923
920
 
924
- @tokens[index][1] = @tokens[index][1].chomp
921
+ @tokens[index][1] = @tokens[index][1].chomp if index
925
922
  @trim_next_whitespace = false if owned
926
923
  end
927
924