@herb-tools/node 0.8.7 → 0.8.9

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 (36) hide show
  1. package/dist/herb-node.esm.js +1 -1
  2. package/extension/error_helpers.cpp +1 -1
  3. package/extension/error_helpers.h +1 -1
  4. package/extension/libherb/analyze.c +112 -15
  5. package/extension/libherb/analyze_helpers.c +80 -12
  6. package/extension/libherb/analyze_helpers.h +7 -0
  7. package/extension/libherb/analyze_missing_end.c +1 -1
  8. package/extension/libherb/analyze_transform.c +1 -1
  9. package/extension/libherb/analyzed_ruby.c +1 -0
  10. package/extension/libherb/analyzed_ruby.h +1 -0
  11. package/extension/libherb/ast_nodes.c +13 -5
  12. package/extension/libherb/ast_nodes.h +9 -5
  13. package/extension/libherb/ast_pretty_print.c +53 -1
  14. package/extension/libherb/ast_pretty_print.h +1 -1
  15. package/extension/libherb/errors.c +1 -1
  16. package/extension/libherb/errors.h +1 -1
  17. package/extension/libherb/include/analyze_helpers.h +7 -0
  18. package/extension/libherb/include/analyzed_ruby.h +1 -0
  19. package/extension/libherb/include/ast_nodes.h +9 -5
  20. package/extension/libherb/include/ast_pretty_print.h +1 -1
  21. package/extension/libherb/include/errors.h +1 -1
  22. package/extension/libherb/include/location.h +4 -0
  23. package/extension/libherb/include/prism_helpers.h +6 -0
  24. package/extension/libherb/include/version.h +1 -1
  25. package/extension/libherb/location.c +16 -0
  26. package/extension/libherb/location.h +4 -0
  27. package/extension/libherb/parser_match_tags.c +1 -1
  28. package/extension/libherb/prism_helpers.c +188 -0
  29. package/extension/libherb/prism_helpers.h +6 -0
  30. package/extension/libherb/version.h +1 -1
  31. package/extension/libherb/visitor.c +1 -1
  32. package/extension/nodes.cpp +33 -1
  33. package/extension/nodes.h +1 -1
  34. package/extension/prism/include/prism/version.h +2 -2
  35. package/extension/prism/src/prism.c +48 -27
  36. package/package.json +2 -2
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/ast_pretty_print.c.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/ast_pretty_print.c.erb
3
3
 
4
4
  #include "include/analyze_helpers.h"
5
5
  #include "include/ast_node.h"
@@ -265,6 +265,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
265
265
  pretty_print_token_property(erb_if_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
266
266
  pretty_print_token_property(erb_if_node->content, hb_string("content"), indent, relative_indent, false, buffer);
267
267
  pretty_print_token_property(erb_if_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
268
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
269
+ if (erb_if_node->then_keyword) {
270
+ char then_keyword_location_string[128];
271
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
272
+ erb_if_node->then_keyword->start.line,
273
+ erb_if_node->then_keyword->start.column,
274
+ erb_if_node->then_keyword->end.line,
275
+ erb_if_node->then_keyword->end.column);
276
+ hb_buffer_append(buffer, then_keyword_location_string);
277
+ } else {
278
+ hb_buffer_append(buffer, " ∅\n");
279
+ }
280
+
268
281
  pretty_print_array(hb_string("statements"), erb_if_node->statements, indent, relative_indent, false, buffer);
269
282
 
270
283
  pretty_print_label(hb_string("subsequent"), indent, relative_indent, false, buffer);
@@ -330,6 +343,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
330
343
  pretty_print_token_property(erb_when_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
331
344
  pretty_print_token_property(erb_when_node->content, hb_string("content"), indent, relative_indent, false, buffer);
332
345
  pretty_print_token_property(erb_when_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
346
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
347
+ if (erb_when_node->then_keyword) {
348
+ char then_keyword_location_string[128];
349
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
350
+ erb_when_node->then_keyword->start.line,
351
+ erb_when_node->then_keyword->start.column,
352
+ erb_when_node->then_keyword->end.line,
353
+ erb_when_node->then_keyword->end.column);
354
+ hb_buffer_append(buffer, then_keyword_location_string);
355
+ } else {
356
+ hb_buffer_append(buffer, " ∅\n");
357
+ }
358
+
333
359
  pretty_print_array(hb_string("statements"), erb_when_node->statements, indent, relative_indent, true, buffer);
334
360
  } break;
335
361
 
@@ -602,6 +628,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
602
628
  pretty_print_token_property(erb_unless_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
603
629
  pretty_print_token_property(erb_unless_node->content, hb_string("content"), indent, relative_indent, false, buffer);
604
630
  pretty_print_token_property(erb_unless_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
631
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
632
+ if (erb_unless_node->then_keyword) {
633
+ char then_keyword_location_string[128];
634
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
635
+ erb_unless_node->then_keyword->start.line,
636
+ erb_unless_node->then_keyword->start.column,
637
+ erb_unless_node->then_keyword->end.line,
638
+ erb_unless_node->then_keyword->end.column);
639
+ hb_buffer_append(buffer, then_keyword_location_string);
640
+ } else {
641
+ hb_buffer_append(buffer, " ∅\n");
642
+ }
643
+
605
644
  pretty_print_array(hb_string("statements"), erb_unless_node->statements, indent, relative_indent, false, buffer);
606
645
 
607
646
  pretty_print_label(hb_string("else_clause"), indent, relative_indent, false, buffer);
@@ -651,6 +690,19 @@ void ast_pretty_print_node(AST_NODE_T* node, const size_t indent, const size_t r
651
690
  pretty_print_token_property(erb_in_node->tag_opening, hb_string("tag_opening"), indent, relative_indent, false, buffer);
652
691
  pretty_print_token_property(erb_in_node->content, hb_string("content"), indent, relative_indent, false, buffer);
653
692
  pretty_print_token_property(erb_in_node->tag_closing, hb_string("tag_closing"), indent, relative_indent, false, buffer);
693
+ pretty_print_label(hb_string("then_keyword"), indent, relative_indent, false, buffer);
694
+ if (erb_in_node->then_keyword) {
695
+ char then_keyword_location_string[128];
696
+ sprintf(then_keyword_location_string, " (location: (%u:%u)-(%u:%u))\n",
697
+ erb_in_node->then_keyword->start.line,
698
+ erb_in_node->then_keyword->start.column,
699
+ erb_in_node->then_keyword->end.line,
700
+ erb_in_node->then_keyword->end.column);
701
+ hb_buffer_append(buffer, then_keyword_location_string);
702
+ } else {
703
+ hb_buffer_append(buffer, " ∅\n");
704
+ }
705
+
654
706
  pretty_print_array(hb_string("statements"), erb_in_node->statements, indent, relative_indent, true, buffer);
655
707
  } break;
656
708
 
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/include/ast_pretty_print.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/include/ast_pretty_print.h.erb
3
3
 
4
4
  #ifndef HERB_AST_PRETTY_PRINT_H
5
5
  #define HERB_AST_PRETTY_PRINT_H
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/errors.c.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/errors.c.erb
3
3
 
4
4
  #include "include/errors.h"
5
5
  #include "include/location.h"
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/include/errors.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/include/errors.h.erb
3
3
 
4
4
  #ifndef HERB_ERRORS_H
5
5
  #define HERB_ERRORS_H
@@ -25,9 +25,15 @@ bool has_rescue_node(analyzed_ruby_T* analyzed);
25
25
  bool has_ensure_node(analyzed_ruby_T* analyzed);
26
26
  bool has_unless_node(analyzed_ruby_T* analyzed);
27
27
  bool has_yield_node(analyzed_ruby_T* analyzed);
28
+ bool has_then_keyword(analyzed_ruby_T* analyzed);
28
29
 
29
30
  bool has_error_message(analyzed_ruby_T* anlayzed, const char* message);
30
31
 
32
+ bool is_do_block(pm_location_t opening_location);
33
+ bool is_brace_block(pm_location_t opening_location);
34
+ bool is_closing_brace(pm_location_t location);
35
+ bool has_valid_block_closing(pm_location_t opening_loc, pm_location_t closing_loc);
36
+
31
37
  bool search_if_nodes(const pm_node_t* node, void* data);
32
38
  bool search_block_nodes(const pm_node_t* node, void* data);
33
39
  bool search_case_nodes(const pm_node_t* node, void* data);
@@ -46,6 +52,7 @@ bool search_in_nodes(analyzed_ruby_T* analyzed);
46
52
  bool search_rescue_nodes(analyzed_ruby_T* analyzed);
47
53
  bool search_ensure_nodes(analyzed_ruby_T* analyzed);
48
54
  bool search_yield_nodes(const pm_node_t* node, void* data);
55
+ bool search_then_keywords(const pm_node_t* node, void* data);
49
56
  bool search_unclosed_control_flows(const pm_node_t* node, void* data);
50
57
 
51
58
  void check_erb_node_for_missing_end(const AST_NODE_T* node);
@@ -29,6 +29,7 @@ typedef struct ANALYZED_RUBY_STRUCT {
29
29
  int ensure_node_count;
30
30
  int unless_node_count;
31
31
  int yield_node_count;
32
+ int then_keyword_count;
32
33
  int unclosed_control_flow_count;
33
34
  } analyzed_ruby_T;
34
35
 
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/include/ast_nodes.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/include/ast_nodes.h.erb
3
3
 
4
4
  #ifndef HERB_AST_NODES_H
5
5
  #define HERB_AST_NODES_H
@@ -183,6 +183,7 @@ typedef struct AST_ERB_IF_NODE_STRUCT {
183
183
  token_T* tag_opening;
184
184
  token_T* content;
185
185
  token_T* tag_closing;
186
+ location_T* then_keyword;
186
187
  hb_array_T* statements;
187
188
  struct AST_NODE_STRUCT* subsequent;
188
189
  struct AST_ERB_END_NODE_STRUCT* end_node;
@@ -202,6 +203,7 @@ typedef struct AST_ERB_WHEN_NODE_STRUCT {
202
203
  token_T* tag_opening;
203
204
  token_T* content;
204
205
  token_T* tag_closing;
206
+ location_T* then_keyword;
205
207
  hb_array_T* statements;
206
208
  } AST_ERB_WHEN_NODE_T;
207
209
 
@@ -288,6 +290,7 @@ typedef struct AST_ERB_UNLESS_NODE_STRUCT {
288
290
  token_T* tag_opening;
289
291
  token_T* content;
290
292
  token_T* tag_closing;
293
+ location_T* then_keyword;
291
294
  hb_array_T* statements;
292
295
  struct AST_ERB_ELSE_NODE_STRUCT* else_clause;
293
296
  struct AST_ERB_END_NODE_STRUCT* end_node;
@@ -305,6 +308,7 @@ typedef struct AST_ERB_IN_NODE_STRUCT {
305
308
  token_T* tag_opening;
306
309
  token_T* content;
307
310
  token_T* tag_closing;
311
+ location_T* then_keyword;
308
312
  hb_array_T* statements;
309
313
  } AST_ERB_IN_NODE_T;
310
314
 
@@ -325,9 +329,9 @@ AST_WHITESPACE_NODE_T* ast_whitespace_node_init(token_T* value, position_T start
325
329
  AST_ERB_CONTENT_NODE_T* ast_erb_content_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, analyzed_ruby_T* analyzed_ruby, bool parsed, bool valid, position_T start_position, position_T end_position, hb_array_T* errors);
326
330
  AST_ERB_END_NODE_T* ast_erb_end_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, position_T start_position, position_T end_position, hb_array_T* errors);
327
331
  AST_ERB_ELSE_NODE_T* ast_erb_else_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
328
- AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_NODE_STRUCT* subsequent, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
332
+ AST_ERB_IF_NODE_T* ast_erb_if_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, struct AST_NODE_STRUCT* subsequent, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
329
333
  AST_ERB_BLOCK_NODE_T* ast_erb_block_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* body, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
330
- AST_ERB_WHEN_NODE_T* ast_erb_when_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
334
+ AST_ERB_WHEN_NODE_T* ast_erb_when_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
331
335
  AST_ERB_CASE_NODE_T* ast_erb_case_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* children, hb_array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
332
336
  AST_ERB_CASE_MATCH_NODE_T* ast_erb_case_match_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* children, hb_array_T* conditions, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
333
337
  AST_ERB_WHILE_NODE_T* ast_erb_while_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
@@ -336,9 +340,9 @@ AST_ERB_FOR_NODE_T* ast_erb_for_node_init(token_T* tag_opening, token_T* content
336
340
  AST_ERB_RESCUE_NODE_T* ast_erb_rescue_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_RESCUE_NODE_STRUCT* subsequent, position_T start_position, position_T end_position, hb_array_T* errors);
337
341
  AST_ERB_ENSURE_NODE_T* ast_erb_ensure_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
338
342
  AST_ERB_BEGIN_NODE_T* ast_erb_begin_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_RESCUE_NODE_STRUCT* rescue_clause, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_ENSURE_NODE_STRUCT* ensure_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
339
- AST_ERB_UNLESS_NODE_T* ast_erb_unless_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
343
+ AST_ERB_UNLESS_NODE_T* ast_erb_unless_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, struct AST_ERB_ELSE_NODE_STRUCT* else_clause, struct AST_ERB_END_NODE_STRUCT* end_node, position_T start_position, position_T end_position, hb_array_T* errors);
340
344
  AST_ERB_YIELD_NODE_T* ast_erb_yield_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, position_T start_position, position_T end_position, hb_array_T* errors);
341
- AST_ERB_IN_NODE_T* ast_erb_in_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
345
+ AST_ERB_IN_NODE_T* ast_erb_in_node_init(token_T* tag_opening, token_T* content, token_T* tag_closing, location_T* then_keyword, hb_array_T* statements, position_T start_position, position_T end_position, hb_array_T* errors);
342
346
 
343
347
  hb_string_T ast_node_type_to_string(AST_NODE_T* node);
344
348
  hb_string_T ast_node_human_type(AST_NODE_T* node);
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/include/ast_pretty_print.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/include/ast_pretty_print.h.erb
3
3
 
4
4
  #ifndef HERB_AST_PRETTY_PRINT_H
5
5
  #define HERB_AST_PRETTY_PRINT_H
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/include/errors.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/include/errors.h.erb
3
3
 
4
4
  #ifndef HERB_ERRORS_H
5
5
  #define HERB_ERRORS_H
@@ -19,4 +19,8 @@ void location_from(
19
19
  uint32_t end_column
20
20
  );
21
21
 
22
+ void location_from_positions(location_T* location, position_T start, position_T end);
23
+
24
+ location_T* location_create(position_T start, position_T end);
25
+
22
26
  #endif
@@ -1,8 +1,10 @@
1
1
  #ifndef HERB_PRISM_HELPERS_H
2
2
  #define HERB_PRISM_HELPERS_H
3
3
 
4
+ #include "analyzed_ruby.h"
4
5
  #include "ast_nodes.h"
5
6
  #include "errors.h"
7
+ #include "location.h"
6
8
  #include "position.h"
7
9
 
8
10
  #include <prism.h>
@@ -22,4 +24,8 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
22
24
  position_T end
23
25
  );
24
26
 
27
+ location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source);
28
+ location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause);
29
+ location_T* get_then_keyword_location_elsif_wrapped(const char* source);
30
+
25
31
  #endif
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.8.7"
4
+ #define HERB_VERSION "0.8.9"
5
5
 
6
6
  #endif
@@ -11,3 +11,19 @@ void location_from(
11
11
  location->start = (position_T) { .line = start_line, .column = start_column };
12
12
  location->end = (position_T) { .line = end_line, .column = end_column };
13
13
  }
14
+
15
+ void location_from_positions(location_T* location, position_T start, position_T end) {
16
+ location->start = start;
17
+ location->end = end;
18
+ }
19
+
20
+ location_T* location_create(position_T start, position_T end) {
21
+ location_T* location = malloc(sizeof(location_T));
22
+
23
+ if (location != NULL) {
24
+ location->start = start;
25
+ location->end = end;
26
+ }
27
+
28
+ return location;
29
+ }
@@ -19,4 +19,8 @@ void location_from(
19
19
  uint32_t end_column
20
20
  );
21
21
 
22
+ void location_from_positions(location_T* location, position_T start, position_T end);
23
+
24
+ location_T* location_create(position_T start, position_T end);
25
+
22
26
  #endif
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/parser_match_tags.c.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/parser_match_tags.c.erb
3
3
 
4
4
  #include "include/parser.h"
5
5
  #include "include/ast_nodes.h"
@@ -1,10 +1,14 @@
1
1
  #include "include/prism_helpers.h"
2
2
  #include "include/ast_nodes.h"
3
3
  #include "include/errors.h"
4
+ #include "include/location.h"
4
5
  #include "include/position.h"
5
6
  #include "include/util.h"
7
+ #include "include/util/hb_buffer.h"
6
8
 
7
9
  #include <prism.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
8
12
 
9
13
  const char* pm_error_level_to_string(pm_error_level_t level) {
10
14
  switch (level) {
@@ -50,3 +54,187 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
50
54
  end
51
55
  );
52
56
  }
57
+
58
+ typedef struct {
59
+ pm_location_t then_keyword_loc;
60
+ bool found;
61
+ } then_keyword_search_context_T;
62
+
63
+ static bool has_pm_location(pm_location_t location) {
64
+ return location.start != NULL && location.end != NULL && (location.end - location.start) > 0;
65
+ }
66
+
67
+ static bool search_then_keyword_location(const pm_node_t* node, void* data) {
68
+ then_keyword_search_context_T* context = (then_keyword_search_context_T*) data;
69
+
70
+ if (context->found) { return false; }
71
+
72
+ switch (node->type) {
73
+ case PM_IF_NODE: {
74
+ const pm_if_node_t* if_node = (const pm_if_node_t*) node;
75
+ if (has_pm_location(if_node->then_keyword_loc)) {
76
+ context->then_keyword_loc = if_node->then_keyword_loc;
77
+ context->found = true;
78
+ return false;
79
+ }
80
+ break;
81
+ }
82
+
83
+ case PM_UNLESS_NODE: {
84
+ const pm_unless_node_t* unless_node = (const pm_unless_node_t*) node;
85
+ if (has_pm_location(unless_node->then_keyword_loc)) {
86
+ context->then_keyword_loc = unless_node->then_keyword_loc;
87
+ context->found = true;
88
+ return false;
89
+ }
90
+ break;
91
+ }
92
+
93
+ case PM_WHEN_NODE: {
94
+ const pm_when_node_t* when_node = (const pm_when_node_t*) node;
95
+ if (has_pm_location(when_node->then_keyword_loc)) {
96
+ context->then_keyword_loc = when_node->then_keyword_loc;
97
+ context->found = true;
98
+ return false;
99
+ }
100
+ break;
101
+ }
102
+
103
+ case PM_IN_NODE: {
104
+ const pm_in_node_t* in_node = (const pm_in_node_t*) node;
105
+ if (has_pm_location(in_node->then_loc)) {
106
+ context->then_keyword_loc = in_node->then_loc;
107
+ context->found = true;
108
+ return false;
109
+ }
110
+ break;
111
+ }
112
+
113
+ default: break;
114
+ }
115
+
116
+ pm_visit_child_nodes(node, search_then_keyword_location, context);
117
+
118
+ return false;
119
+ }
120
+
121
+ location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source) {
122
+ if (analyzed == NULL || analyzed->root == NULL || source == NULL) { return NULL; }
123
+
124
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
125
+
126
+ pm_visit_child_nodes(analyzed->root, search_then_keyword_location, &context);
127
+
128
+ if (!context.found) { return NULL; }
129
+
130
+ size_t start_offset = (size_t) (context.then_keyword_loc.start - analyzed->parser.start);
131
+ size_t end_offset = (size_t) (context.then_keyword_loc.end - analyzed->parser.start);
132
+
133
+ position_T start_position = position_from_source_with_offset(source, start_offset);
134
+ position_T end_position = position_from_source_with_offset(source, end_offset);
135
+
136
+ return location_create(start_position, end_position);
137
+ }
138
+
139
+ static location_T* parse_wrapped_and_find_then_keyword(
140
+ hb_buffer_T* buffer,
141
+ const char* source,
142
+ size_t source_length,
143
+ size_t prefix_length,
144
+ size_t adjustment_threshold,
145
+ size_t adjustment_amount
146
+ ) {
147
+ pm_parser_t parser;
148
+ pm_parser_init(&parser, (const uint8_t*) hb_buffer_value(buffer), hb_buffer_length(buffer), NULL);
149
+ pm_node_t* root = pm_parse(&parser);
150
+
151
+ if (root == NULL) {
152
+ pm_parser_free(&parser);
153
+
154
+ return NULL;
155
+ }
156
+
157
+ then_keyword_search_context_T context = { .then_keyword_loc = { .start = NULL, .end = NULL }, .found = false };
158
+
159
+ pm_visit_child_nodes(root, search_then_keyword_location, &context);
160
+
161
+ location_T* location = NULL;
162
+
163
+ if (context.found) {
164
+ size_t start_offset = (size_t) (context.then_keyword_loc.start - parser.start);
165
+ size_t end_offset = (size_t) (context.then_keyword_loc.end - parser.start);
166
+
167
+ if (start_offset >= prefix_length && end_offset >= prefix_length) {
168
+ start_offset -= prefix_length;
169
+ end_offset -= prefix_length;
170
+
171
+ if (start_offset > adjustment_threshold) {
172
+ start_offset += adjustment_amount;
173
+ end_offset += adjustment_amount;
174
+ }
175
+
176
+ if (start_offset <= source_length && end_offset <= source_length) {
177
+ position_T start_position = position_from_source_with_offset(source, start_offset);
178
+ position_T end_position = position_from_source_with_offset(source, end_offset);
179
+
180
+ location = location_create(start_position, end_position);
181
+ }
182
+ }
183
+ }
184
+
185
+ pm_node_destroy(&parser, root);
186
+ pm_parser_free(&parser);
187
+
188
+ return location;
189
+ }
190
+
191
+ location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause) {
192
+ if (source == NULL) { return NULL; }
193
+
194
+ size_t source_length = strlen(source);
195
+
196
+ hb_buffer_T buffer;
197
+
198
+ if (!hb_buffer_init(&buffer, source_length + 16)) { return NULL; }
199
+
200
+ hb_buffer_append(&buffer, "case x\n");
201
+ size_t prefix_length = hb_buffer_length(&buffer);
202
+ hb_buffer_append(&buffer, source);
203
+ hb_buffer_append(&buffer, "\nend");
204
+
205
+ location_T* location =
206
+ parse_wrapped_and_find_then_keyword(&buffer, source, source_length, prefix_length, SIZE_MAX, 0);
207
+
208
+ free(buffer.value);
209
+
210
+ return location;
211
+ }
212
+
213
+ location_T* get_then_keyword_location_elsif_wrapped(const char* source) {
214
+ if (source == NULL) { return NULL; }
215
+
216
+ const char* elsif_position = strstr(source, "elsif");
217
+
218
+ if (elsif_position == NULL) { return NULL; }
219
+
220
+ size_t source_length = strlen(source);
221
+ size_t elsif_offset = (size_t) (elsif_position - source);
222
+ size_t replacement_diff = strlen("elsif") - strlen("if");
223
+
224
+ hb_buffer_T buffer;
225
+
226
+ if (!hb_buffer_init(&buffer, source_length + 8)) { return NULL; }
227
+
228
+ hb_buffer_append_with_length(&buffer, source, elsif_offset);
229
+ hb_buffer_append(&buffer, "if");
230
+ size_t if_end_offset = hb_buffer_length(&buffer);
231
+ hb_buffer_append(&buffer, source + elsif_offset + strlen("elsif"));
232
+ hb_buffer_append(&buffer, "\nend");
233
+
234
+ location_T* location =
235
+ parse_wrapped_and_find_then_keyword(&buffer, source, source_length, 0, if_end_offset, replacement_diff);
236
+
237
+ free(buffer.value);
238
+
239
+ return location;
240
+ }
@@ -1,8 +1,10 @@
1
1
  #ifndef HERB_PRISM_HELPERS_H
2
2
  #define HERB_PRISM_HELPERS_H
3
3
 
4
+ #include "analyzed_ruby.h"
4
5
  #include "ast_nodes.h"
5
6
  #include "errors.h"
7
+ #include "location.h"
6
8
  #include "position.h"
7
9
 
8
10
  #include <prism.h>
@@ -22,4 +24,8 @@ RUBY_PARSE_ERROR_T* ruby_parse_error_from_prism_error_with_positions(
22
24
  position_T end
23
25
  );
24
26
 
27
+ location_T* get_then_keyword_location(analyzed_ruby_T* analyzed, const char* source);
28
+ location_T* get_then_keyword_location_wrapped(const char* source, bool is_in_clause);
29
+ location_T* get_then_keyword_location_elsif_wrapped(const char* source);
30
+
25
31
  #endif
@@ -1,6 +1,6 @@
1
1
  #ifndef HERB_VERSION_H
2
2
  #define HERB_VERSION_H
3
3
 
4
- #define HERB_VERSION "0.8.7"
4
+ #define HERB_VERSION "0.8.9"
5
5
 
6
6
  #endif
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/src/visitor.c.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/src/visitor.c.erb
3
3
 
4
4
  #include <stdio.h>
5
5
 
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/javascript/packages/node/extension/nodes.cpp.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/javascript/packages/node/extension/nodes.cpp.erb
3
3
 
4
4
  #include <node_api.h>
5
5
  #include "error_helpers.h"
@@ -581,6 +581,14 @@ napi_value erb_if_nodeNodeFromCStruct(napi_env env, AST_ERB_IF_NODE_T* erb_if_no
581
581
  napi_value tag_closing = CreateToken(env, erb_if_node->tag_closing);
582
582
  napi_set_named_property(env, result, "tag_closing", tag_closing);
583
583
 
584
+ napi_value then_keyword;
585
+ if (erb_if_node->then_keyword != NULL) {
586
+ then_keyword = CreateLocation(env, *erb_if_node->then_keyword);
587
+ } else {
588
+ napi_get_null(env, &then_keyword);
589
+ }
590
+ napi_set_named_property(env, result, "then_keyword", then_keyword);
591
+
584
592
  napi_value statements = NodesArrayFromCArray(env, erb_if_node->statements);
585
593
  napi_set_named_property(env, result, "statements", statements);
586
594
 
@@ -658,6 +666,14 @@ napi_value erb_when_nodeNodeFromCStruct(napi_env env, AST_ERB_WHEN_NODE_T* erb_w
658
666
  napi_value tag_closing = CreateToken(env, erb_when_node->tag_closing);
659
667
  napi_set_named_property(env, result, "tag_closing", tag_closing);
660
668
 
669
+ napi_value then_keyword;
670
+ if (erb_when_node->then_keyword != NULL) {
671
+ then_keyword = CreateLocation(env, *erb_when_node->then_keyword);
672
+ } else {
673
+ napi_get_null(env, &then_keyword);
674
+ }
675
+ napi_set_named_property(env, result, "then_keyword", then_keyword);
676
+
661
677
  napi_value statements = NodesArrayFromCArray(env, erb_when_node->statements);
662
678
  napi_set_named_property(env, result, "statements", statements);
663
679
 
@@ -1006,6 +1022,14 @@ napi_value erb_unless_nodeNodeFromCStruct(napi_env env, AST_ERB_UNLESS_NODE_T* e
1006
1022
  napi_value tag_closing = CreateToken(env, erb_unless_node->tag_closing);
1007
1023
  napi_set_named_property(env, result, "tag_closing", tag_closing);
1008
1024
 
1025
+ napi_value then_keyword;
1026
+ if (erb_unless_node->then_keyword != NULL) {
1027
+ then_keyword = CreateLocation(env, *erb_unless_node->then_keyword);
1028
+ } else {
1029
+ napi_get_null(env, &then_keyword);
1030
+ }
1031
+ napi_set_named_property(env, result, "then_keyword", then_keyword);
1032
+
1009
1033
  napi_value statements = NodesArrayFromCArray(env, erb_unless_node->statements);
1010
1034
  napi_set_named_property(env, result, "statements", statements);
1011
1035
 
@@ -1077,6 +1101,14 @@ napi_value erb_in_nodeNodeFromCStruct(napi_env env, AST_ERB_IN_NODE_T* erb_in_no
1077
1101
  napi_value tag_closing = CreateToken(env, erb_in_node->tag_closing);
1078
1102
  napi_set_named_property(env, result, "tag_closing", tag_closing);
1079
1103
 
1104
+ napi_value then_keyword;
1105
+ if (erb_in_node->then_keyword != NULL) {
1106
+ then_keyword = CreateLocation(env, *erb_in_node->then_keyword);
1107
+ } else {
1108
+ napi_get_null(env, &then_keyword);
1109
+ }
1110
+ napi_set_named_property(env, result, "then_keyword", then_keyword);
1111
+
1080
1112
  napi_value statements = NodesArrayFromCArray(env, erb_in_node->statements);
1081
1113
  napi_set_named_property(env, result, "statements", statements);
1082
1114
 
package/extension/nodes.h CHANGED
@@ -1,5 +1,5 @@
1
1
  // NOTE: This file is generated by the templates/template.rb script and should not
2
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.7/templates/javascript/packages/node/extension/nodes.h.erb
2
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.9/templates/javascript/packages/node/extension/nodes.h.erb
3
3
 
4
4
  #ifndef HERB_EXTENSION_NODES_H
5
5
  #define HERB_EXTENSION_NODES_H
@@ -14,7 +14,7 @@
14
14
  /**
15
15
  * The minor version of the Prism library as an int.
16
16
  */
17
- #define PRISM_VERSION_MINOR 7
17
+ #define PRISM_VERSION_MINOR 8
18
18
 
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "1.7.0"
27
+ #define PRISM_VERSION "1.8.0"
28
28
 
29
29
  #endif