herb 0.9.3-arm-linux-gnu → 0.9.5-arm-linux-gnu

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/config.yml +57 -21
  3. data/ext/herb/nodes.c +93 -55
  4. data/lib/herb/3.0/herb.so +0 -0
  5. data/lib/herb/3.1/herb.so +0 -0
  6. data/lib/herb/3.2/herb.so +0 -0
  7. data/lib/herb/3.3/herb.so +0 -0
  8. data/lib/herb/3.4/herb.so +0 -0
  9. data/lib/herb/4.0/herb.so +0 -0
  10. data/lib/herb/ast/nodes.rb +212 -78
  11. data/lib/herb/engine/compiler.rb +52 -26
  12. data/lib/herb/engine.rb +3 -0
  13. data/lib/herb/project.rb +58 -17
  14. data/lib/herb/version.rb +1 -1
  15. data/lib/herb/visitor.rb +8 -2
  16. data/sig/herb/ast/nodes.rbs +85 -34
  17. data/sig/herb/engine/compiler.rbs +16 -0
  18. data/sig/herb/engine.rbs +3 -0
  19. data/sig/herb/visitor.rbs +5 -2
  20. data/sig/serialized_ast_nodes.rbs +20 -9
  21. data/src/analyze/action_view/javascript_tag.c +38 -0
  22. data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
  23. data/src/analyze/action_view/tag_helpers.c +53 -14
  24. data/src/analyze/analyze.c +23 -3
  25. data/src/analyze/analyze_helpers.c +406 -0
  26. data/src/analyze/builders.c +1 -0
  27. data/src/analyze/missing_end.c +16 -0
  28. data/src/analyze/parse_errors.c +43 -1
  29. data/src/analyze/render_nodes.c +231 -35
  30. data/src/analyze/strict_locals.c +22 -324
  31. data/src/analyze/transform.c +23 -2
  32. data/src/ast/ast_nodes.c +114 -57
  33. data/src/ast/ast_pretty_print.c +109 -25
  34. data/src/include/analyze/action_view/tag_helper_handler.h +3 -0
  35. data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
  36. data/src/include/analyze/analyze.h +6 -1
  37. data/src/include/analyze/helpers.h +18 -0
  38. data/src/include/ast/ast_nodes.h +27 -13
  39. data/src/include/version.h +1 -1
  40. data/src/parser/match_tags.c +37 -6
  41. data/src/parser.c +8 -0
  42. data/src/visitor.c +50 -7
  43. metadata +1 -1
@@ -2,12 +2,14 @@
2
2
  #include "../include/analyze/action_view/tag_helper_node_builders.h"
3
3
  #include "../include/analyze/action_view/tag_helpers.h"
4
4
  #include "../include/analyze/analyze.h"
5
+ #include "../include/analyze/helpers.h"
5
6
  #include "../include/ast/ast_nodes.h"
6
7
  #include "../include/errors.h"
7
8
  #include "../include/lib/hb_allocator.h"
8
9
  #include "../include/lib/hb_array.h"
9
10
  #include "../include/lib/hb_buffer.h"
10
11
  #include "../include/lib/hb_string.h"
12
+ #include "../include/lib/string.h"
11
13
  #include "../include/util/util.h"
12
14
  #include "../include/visitor.h"
13
15
 
@@ -101,40 +103,9 @@ static pm_parameters_node_t* find_parameters_node(pm_node_t* root) {
101
103
  return def_node->parameters;
102
104
  }
103
105
 
104
- static token_T* create_strict_local_token(
105
- const uint8_t* prism_node_start,
106
- const uint8_t* prism_node_end,
107
- const char* name,
108
- token_type_T type,
109
- const char* source,
110
- size_t erb_content_byte_offset,
111
- const char* content_bytes,
112
- const char* params_open,
113
- const uint8_t* synthetic_start,
114
- hb_allocator_T* allocator
115
- ) {
116
- size_t params_in_content = (size_t) (params_open - content_bytes);
117
- size_t prism_start_in_synthetic = (size_t) (prism_node_start - synthetic_start);
118
- size_t prism_end_in_synthetic = (size_t) (prism_node_end - synthetic_start);
119
- size_t content_start = params_in_content + (prism_start_in_synthetic - strlen(SYNTHETIC_PREFIX));
120
- size_t content_end = params_in_content + (prism_end_in_synthetic - strlen(SYNTHETIC_PREFIX));
121
-
122
- position_T start = byte_offset_to_position(source, erb_content_byte_offset + content_start);
123
- position_T end = byte_offset_to_position(source, erb_content_byte_offset + content_end);
124
-
125
- return create_synthetic_token(allocator, name, type, start, end);
126
- }
127
-
128
- static char* extract_name_from_location(pm_location_t name_location, hb_allocator_T* allocator) {
129
- size_t length = (size_t) (name_location.end - name_location.start);
130
-
131
- if (length > 0 && name_location.start[length - 1] == ':') { length--; }
132
-
133
- return hb_allocator_strndup(allocator, (const char*) name_location.start, length);
134
- }
135
-
136
106
  static hb_array_T* extract_strict_locals(
137
107
  pm_parameters_node_t* params,
108
+ pm_parser_t* parser,
138
109
  const char* source,
139
110
  size_t erb_content_byte_offset,
140
111
  const char* content_bytes,
@@ -143,303 +114,29 @@ static hb_array_T* extract_strict_locals(
143
114
  hb_array_T* errors,
144
115
  hb_allocator_T* allocator
145
116
  ) {
146
- hb_array_T* locals = hb_array_init(4, allocator);
147
-
148
- if (!params) { return locals; }
149
-
150
- for (size_t index = 0; index < params->optionals.size; index++) {
151
- pm_node_t* optional = params->optionals.nodes[index];
152
- if (!optional || optional->type != PM_OPTIONAL_PARAMETER_NODE) { continue; }
153
-
154
- pm_optional_parameter_node_t* optional_param = (pm_optional_parameter_node_t*) optional;
155
- pm_location_t location = optional_param->name_loc;
156
- size_t length = (size_t) (location.end - location.start);
157
- char* name = hb_allocator_strndup(allocator, (const char*) location.start, length);
158
-
159
- token_T* name_token = create_strict_local_token(
160
- location.start,
161
- location.end,
162
- name,
163
- TOKEN_IDENTIFIER,
164
- source,
165
- erb_content_byte_offset,
166
- content_bytes,
167
- params_open,
168
- synthetic_start,
169
- allocator
170
- );
171
-
172
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
173
- position_T end = name_token ? name_token->location.end : start;
174
-
175
- size_t value_prism_start = (size_t) (optional_param->value->location.start - synthetic_start);
176
- size_t value_prism_end = (size_t) (optional_param->value->location.end - synthetic_start);
177
- size_t params_in_content = (size_t) (params_open - content_bytes);
178
- size_t value_content_start = params_in_content + (value_prism_start - strlen(SYNTHETIC_PREFIX));
179
- size_t value_content_end = params_in_content + (value_prism_end - strlen(SYNTHETIC_PREFIX));
180
-
181
- size_t value_length = value_prism_end - value_prism_start;
182
- char* value_string =
183
- hb_allocator_strndup(allocator, (const char*) optional_param->value->location.start, value_length);
184
-
185
- position_T value_start = byte_offset_to_position(source, erb_content_byte_offset + value_content_start);
186
- position_T value_end = byte_offset_to_position(source, erb_content_byte_offset + value_content_end);
187
-
188
- AST_RUBY_LITERAL_NODE_T* value_node = ast_ruby_literal_node_init(
189
- hb_string_from_c_string(value_string),
190
- value_start,
191
- value_end,
192
- hb_array_init(0, allocator),
193
- allocator
194
- );
195
-
196
- hb_array_T* node_errors = hb_array_init(1, allocator);
197
- append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors);
198
-
199
- AST_RUBY_STRICT_LOCAL_NODE_T* local =
200
- ast_ruby_strict_local_node_init(name_token, value_node, false, false, start, value_end, node_errors, allocator);
201
-
202
- hb_array_append(locals, local);
203
- hb_allocator_dealloc(allocator, name);
204
- hb_allocator_dealloc(allocator, value_string);
205
- }
206
-
207
- for (size_t index = 0; index < params->requireds.size; index++) {
208
- pm_node_t* required = params->requireds.nodes[index];
209
- if (!required) { continue; }
210
-
211
- pm_location_t location = required->location;
212
- size_t length = (size_t) (location.end - location.start);
213
- char* name = hb_allocator_strndup(allocator, (const char*) location.start, length);
214
-
215
- token_T* name_token = create_strict_local_token(
216
- location.start,
217
- location.end,
218
- name,
219
- TOKEN_IDENTIFIER,
220
- source,
221
- erb_content_byte_offset,
222
- content_bytes,
223
- params_open,
224
- synthetic_start,
225
- allocator
226
- );
227
-
228
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
229
- position_T end = name_token ? name_token->location.end : start;
230
-
231
- hb_array_T* node_errors = hb_array_init(1, allocator);
232
- append_strict_locals_positional_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors);
233
-
234
- AST_RUBY_STRICT_LOCAL_NODE_T* local =
235
- ast_ruby_strict_local_node_init(name_token, NULL, true, false, start, end, node_errors, allocator);
236
-
237
- hb_array_append(locals, local);
238
- hb_allocator_dealloc(allocator, name);
239
- }
240
-
241
- if (params->block) {
242
- pm_block_parameter_node_t* block_param = params->block;
243
-
244
- if (block_param->name) {
245
- size_t length = (size_t) (block_param->name_loc.end - block_param->name_loc.start);
246
- char* name = hb_allocator_strndup(allocator, (const char*) block_param->name_loc.start, length);
247
-
248
- token_T* name_token = create_strict_local_token(
249
- block_param->name_loc.start,
250
- block_param->name_loc.end,
251
- name,
252
- TOKEN_IDENTIFIER,
253
- source,
254
- erb_content_byte_offset,
255
- content_bytes,
256
- params_open,
257
- synthetic_start,
258
- allocator
259
- );
260
-
261
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
262
- position_T end = name_token ? name_token->location.end : start;
263
-
264
- hb_array_T* node_errors = hb_array_init(1, allocator);
265
- append_strict_locals_block_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors);
117
+ if (!params) { return hb_array_init(0, allocator); }
266
118
 
267
- AST_RUBY_STRICT_LOCAL_NODE_T* local =
268
- ast_ruby_strict_local_node_init(name_token, NULL, false, false, start, end, node_errors, allocator);
269
-
270
- hb_array_append(locals, local);
271
- hb_allocator_dealloc(allocator, name);
272
- }
273
- }
274
-
275
- if (params->rest && params->rest->type == PM_REST_PARAMETER_NODE) {
276
- pm_rest_parameter_node_t* splat_param = (pm_rest_parameter_node_t*) params->rest;
277
-
278
- if (splat_param->name) {
279
- size_t length = (size_t) (splat_param->name_loc.end - splat_param->name_loc.start);
280
- char* name = hb_allocator_strndup(allocator, (const char*) splat_param->name_loc.start, length);
281
-
282
- token_T* name_token = create_strict_local_token(
283
- splat_param->name_loc.start,
284
- splat_param->name_loc.end,
285
- name,
286
- TOKEN_IDENTIFIER,
287
- source,
288
- erb_content_byte_offset,
289
- content_bytes,
290
- params_open,
291
- synthetic_start,
292
- allocator
293
- );
294
-
295
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
296
- position_T end = name_token ? name_token->location.end : start;
297
-
298
- hb_array_T* node_errors = hb_array_init(1, allocator);
299
- append_strict_locals_splat_argument_error(hb_string_from_c_string(name), start, end, allocator, node_errors);
300
-
301
- AST_RUBY_STRICT_LOCAL_NODE_T* local =
302
- ast_ruby_strict_local_node_init(name_token, NULL, false, false, start, end, node_errors, allocator);
303
-
304
- hb_array_append(locals, local);
305
- hb_allocator_dealloc(allocator, name);
306
- }
307
- }
308
-
309
- for (size_t index = 0; index < params->keywords.size; index++) {
310
- pm_node_t* keyword_node = params->keywords.nodes[index];
311
-
312
- if (keyword_node->type == PM_REQUIRED_KEYWORD_PARAMETER_NODE) {
313
- pm_required_keyword_parameter_node_t* keyword_param = (pm_required_keyword_parameter_node_t*) keyword_node;
314
-
315
- char* name = extract_name_from_location(keyword_param->name_loc, allocator);
316
- if (!name) { continue; }
317
-
318
- token_T* name_token = create_strict_local_token(
319
- keyword_param->name_loc.start,
320
- keyword_param->name_loc.end,
321
- name,
322
- TOKEN_IDENTIFIER,
323
- source,
324
- erb_content_byte_offset,
325
- content_bytes,
326
- params_open,
327
- synthetic_start,
328
- allocator
329
- );
330
-
331
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
332
- position_T end = name_token ? name_token->location.end : start;
333
-
334
- AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(
335
- name_token,
336
- NULL,
337
- true,
338
- false,
339
- start,
340
- end,
341
- hb_array_init(0, allocator),
342
- allocator
343
- );
344
-
345
- hb_array_append(locals, local);
346
- hb_allocator_dealloc(allocator, name);
347
-
348
- } else if (keyword_node->type == PM_OPTIONAL_KEYWORD_PARAMETER_NODE) {
349
- pm_optional_keyword_parameter_node_t* keyword_param = (pm_optional_keyword_parameter_node_t*) keyword_node;
350
-
351
- char* name = extract_name_from_location(keyword_param->name_loc, allocator);
352
- if (!name) { continue; }
353
-
354
- size_t value_prism_start = (size_t) (keyword_param->value->location.start - synthetic_start);
355
- size_t value_prism_end = (size_t) (keyword_param->value->location.end - synthetic_start);
356
- size_t params_in_content = (size_t) (params_open - content_bytes);
357
- size_t value_content_start = params_in_content + (value_prism_start - strlen(SYNTHETIC_PREFIX));
358
- size_t value_content_end = params_in_content + (value_prism_end - strlen(SYNTHETIC_PREFIX));
359
-
360
- size_t value_length = value_prism_end - value_prism_start;
361
- char* value_string =
362
- hb_allocator_strndup(allocator, (const char*) keyword_param->value->location.start, value_length);
363
-
364
- position_T value_start = byte_offset_to_position(source, erb_content_byte_offset + value_content_start);
365
- position_T value_end = byte_offset_to_position(source, erb_content_byte_offset + value_content_end);
366
-
367
- AST_RUBY_LITERAL_NODE_T* value_node = ast_ruby_literal_node_init(
368
- hb_string_from_c_string(value_string),
369
- value_start,
370
- value_end,
371
- hb_array_init(0, allocator),
372
- allocator
373
- );
374
-
375
- token_T* name_token = create_strict_local_token(
376
- keyword_param->name_loc.start,
377
- keyword_param->name_loc.end,
378
- name,
379
- TOKEN_IDENTIFIER,
380
- source,
381
- erb_content_byte_offset,
382
- content_bytes,
383
- params_open,
384
- synthetic_start,
385
- allocator
386
- );
387
-
388
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
389
-
390
- AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(
391
- name_token,
392
- value_node,
393
- false,
394
- false,
395
- start,
396
- value_end,
397
- hb_array_init(0, allocator),
398
- allocator
399
- );
119
+ size_t params_in_content = (size_t) (params_open - content_bytes);
120
+ size_t prefix_length = strlen(SYNTHETIC_PREFIX);
121
+ size_t source_base_offset = erb_content_byte_offset + params_in_content - prefix_length;
400
122
 
401
- hb_array_append(locals, local);
402
- hb_allocator_dealloc(allocator, name);
403
- hb_allocator_dealloc(allocator, value_string);
404
- }
405
- }
123
+ hb_array_T* locals =
124
+ extract_parameters_from_prism(params, parser, source, source_base_offset, synthetic_start, allocator);
406
125
 
407
- if (params->keyword_rest && params->keyword_rest->type == PM_KEYWORD_REST_PARAMETER_NODE) {
408
- pm_keyword_rest_parameter_node_t* keyword_rest_param = (pm_keyword_rest_parameter_node_t*) params->keyword_rest;
409
-
410
- if (keyword_rest_param->name) {
411
- char* name = extract_name_from_location(keyword_rest_param->name_loc, allocator);
412
- if (!name) { return locals; }
413
-
414
- token_T* name_token = create_strict_local_token(
415
- keyword_rest_param->name_loc.start,
416
- keyword_rest_param->name_loc.end,
417
- name,
418
- TOKEN_IDENTIFIER,
419
- source,
420
- erb_content_byte_offset,
421
- content_bytes,
422
- params_open,
423
- synthetic_start,
424
- allocator
425
- );
126
+ for (size_t index = 0; index < hb_array_size(locals); index++) {
127
+ AST_RUBY_PARAMETER_NODE_T* local = hb_array_get(locals, index);
128
+ if (!local) { continue; }
426
129
 
427
- position_T start = name_token ? name_token->location.start : (position_T) { .line = 1, .column = 1 };
428
- position_T end = name_token ? name_token->location.end : start;
429
-
430
- AST_RUBY_STRICT_LOCAL_NODE_T* local = ast_ruby_strict_local_node_init(
431
- name_token,
432
- NULL,
433
- false,
434
- true,
435
- start,
436
- end,
437
- hb_array_init(0, allocator),
438
- allocator
439
- );
130
+ position_T start = local->base.location.start;
131
+ position_T end = local->base.location.end;
132
+ hb_string_T name = local->name ? local->name->value : hb_string("");
440
133
 
441
- hb_array_append(locals, local);
442
- hb_allocator_dealloc(allocator, name);
134
+ if (string_equals(local->kind.data, "positional")) {
135
+ append_strict_locals_positional_argument_error(name, start, end, allocator, local->base.errors);
136
+ } else if (string_equals(local->kind.data, "rest")) {
137
+ append_strict_locals_splat_argument_error(name, start, end, allocator, local->base.errors);
138
+ } else if (string_equals(local->kind.data, "block")) {
139
+ append_strict_locals_block_argument_error(name, start, end, allocator, local->base.errors);
443
140
  }
444
141
  }
445
142
 
@@ -561,6 +258,7 @@ static AST_ERB_STRICT_LOCALS_NODE_T* create_strict_locals_node(
561
258
  } else {
562
259
  locals = extract_strict_locals(
563
260
  params_node,
261
+ &parser,
564
262
  source,
565
263
  erb_content_byte_offset,
566
264
  content_bytes,
@@ -113,6 +113,13 @@ bool transform_erb_nodes(const AST_NODE_T* node, void* data) {
113
113
  hb_array_free(&old_array);
114
114
  }
115
115
 
116
+ if (node->type == AST_ERB_BLOCK_NODE) {
117
+ AST_ERB_BLOCK_NODE_T* erb_block_node = (AST_ERB_BLOCK_NODE_T*) node;
118
+ hb_array_T* old_array = erb_block_node->block_arguments;
119
+ erb_block_node->block_arguments = rewrite_node_array((AST_NODE_T*) node, erb_block_node->block_arguments, context);
120
+ hb_array_free(&old_array);
121
+ }
122
+
116
123
  if (node->type == AST_ERB_WHEN_NODE) {
117
124
  AST_ERB_WHEN_NODE_T* erb_when_node = (AST_ERB_WHEN_NODE_T*) node;
118
125
  hb_array_T* old_array = erb_when_node->statements;
@@ -197,10 +204,24 @@ bool transform_erb_nodes(const AST_NODE_T* node, void* data) {
197
204
  hb_array_free(&old_array);
198
205
  }
199
206
 
207
+ if (node->type == AST_RUBY_RENDER_KEYWORDS_NODE) {
208
+ AST_RUBY_RENDER_KEYWORDS_NODE_T* ruby_render_keywords_node = (AST_RUBY_RENDER_KEYWORDS_NODE_T*) node;
209
+ hb_array_T* old_array = ruby_render_keywords_node->locals;
210
+ ruby_render_keywords_node->locals = rewrite_node_array((AST_NODE_T*) node, ruby_render_keywords_node->locals, context);
211
+ hb_array_free(&old_array);
212
+ }
213
+
214
+ if (node->type == AST_ERB_RENDER_NODE) {
215
+ AST_ERB_RENDER_NODE_T* erb_render_node = (AST_ERB_RENDER_NODE_T*) node;
216
+ hb_array_T* old_array = erb_render_node->body;
217
+ erb_render_node->body = rewrite_node_array((AST_NODE_T*) node, erb_render_node->body, context);
218
+ hb_array_free(&old_array);
219
+ }
220
+
200
221
  if (node->type == AST_ERB_RENDER_NODE) {
201
222
  AST_ERB_RENDER_NODE_T* erb_render_node = (AST_ERB_RENDER_NODE_T*) node;
202
- hb_array_T* old_array = erb_render_node->locals;
203
- erb_render_node->locals = rewrite_node_array((AST_NODE_T*) node, erb_render_node->locals, context);
223
+ hb_array_T* old_array = erb_render_node->block_arguments;
224
+ erb_render_node->block_arguments = rewrite_node_array((AST_NODE_T*) node, erb_render_node->block_arguments, context);
204
225
  hb_array_free(&old_array);
205
226
  }
206
227