@@ -54,12 +54,14 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
54
54
[PM_ERR_ALIAS_ARGUMENT ] = "Invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable" ,
55
55
[PM_ERR_AMPAMPEQ_MULTI_ASSIGN ] = "Unexpected `&&=` in a multiple assignment" ,
56
56
[PM_ERR_ARGUMENT_AFTER_BLOCK ] = "Unexpected argument after a block argument" ,
57
+ [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES ] = "Unexpected argument after `...`" ,
57
58
[PM_ERR_ARGUMENT_BARE_HASH ] = "Unexpected bare hash argument" ,
58
59
[PM_ERR_ARGUMENT_BLOCK_MULTI ] = "Multiple block arguments; only one block is allowed" ,
59
60
[PM_ERR_ARGUMENT_FORMAL_CLASS ] = "Invalid formal argument; formal argument cannot be a class variable" ,
60
61
[PM_ERR_ARGUMENT_FORMAL_CONSTANT ] = "Invalid formal argument; formal argument cannot be a constant" ,
61
62
[PM_ERR_ARGUMENT_FORMAL_GLOBAL ] = "Invalid formal argument; formal argument cannot be a global variable" ,
62
63
[PM_ERR_ARGUMENT_FORMAL_IVAR ] = "Invalid formal argument; formal argument cannot be an instance variable" ,
64
+ [PM_ERR_ARGUMENT_FORWARDING_UNBOUND ] = "Unexpected `...` in an non-parenthesized call" ,
63
65
[PM_ERR_ARGUMENT_NO_FORWARDING_AMP ] = "Unexpected `&` when the parent method is not forwarding" ,
64
66
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES ] = "Unexpected `...` when the parent method is not forwarding" ,
65
67
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR ] = "Unexpected `*` when the parent method is not forwarding" ,
@@ -85,6 +87,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
85
87
[PM_ERR_CANNOT_PARSE_STRING_PART ] = "Cannot parse the string part" ,
86
88
[PM_ERR_CASE_EXPRESSION_AFTER_CASE ] = "Expected an expression after `case`" ,
87
89
[PM_ERR_CASE_EXPRESSION_AFTER_WHEN ] = "Expected an expression after `when`" ,
90
+ [PM_ERR_CASE_MATCH_MISSING_PREDICATE ] = "Expected a predicate for a case matching statement" ,
88
91
[PM_ERR_CASE_MISSING_CONDITIONS ] = "Expected a `when` or `in` clause after `case`" ,
89
92
[PM_ERR_CASE_TERM ] = "Expected an `end` to close the `case` statement" ,
90
93
[PM_ERR_CLASS_IN_METHOD ] = "Unexpected class definition in a method body" ,
@@ -199,7 +202,7 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
199
202
[PM_ERR_PARAMETER_NAME_REPEAT ] = "Repeated parameter name" ,
200
203
[PM_ERR_PARAMETER_NO_DEFAULT ] = "Expected a default value for the parameter" ,
201
204
[PM_ERR_PARAMETER_NO_DEFAULT_KW ] = "Expected a default value for the keyword parameter" ,
202
- [PM_ERR_PARAMETER_NUMBERED_RESERVED ] = "Token reserved for a numbered parameter" ,
205
+ [PM_ERR_PARAMETER_NUMBERED_RESERVED ] = "%.2s is reserved for a numbered parameter" ,
203
206
[PM_ERR_PARAMETER_ORDER ] = "Unexpected parameter order" ,
204
207
[PM_ERR_PARAMETER_SPLAT_MULTI ] = "Unexpected multiple `*` splat parameters" ,
205
208
[PM_ERR_PARAMETER_STAR ] = "Unexpected parameter `*`" ,
@@ -229,6 +232,10 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
229
232
[PM_ERR_RESCUE_TERM ] = "Expected a closing delimiter for the `rescue` clause" ,
230
233
[PM_ERR_RESCUE_VARIABLE ] = "Expected an exception variable after `=>` in a rescue statement" ,
231
234
[PM_ERR_RETURN_INVALID ] = "Invalid `return` in a class or module body" ,
235
+ [PM_ERR_STATEMENT_ALIAS ] = "Unexpected an `alias` at a non-statement position" ,
236
+ [PM_ERR_STATEMENT_POSTEXE_END ] = "Unexpected an `END` at a non-statement position" ,
237
+ [PM_ERR_STATEMENT_PREEXE_BEGIN ] = "Unexpected a `BEGIN` at a non-statement position" ,
238
+ [PM_ERR_STATEMENT_UNDEF ] = "Unexpected an `undef` at a non-statement position" ,
232
239
[PM_ERR_STRING_CONCATENATION ] = "Expected a string for concatenation" ,
233
240
[PM_ERR_STRING_INTERPOLATED_TERM ] = "Expected a closing delimiter for the interpolated string" ,
234
241
[PM_ERR_STRING_LITERAL_TERM ] = "Expected a closing delimiter for the string literal" ,
@@ -253,13 +260,16 @@ static const char* const diagnostic_messages[PM_DIAGNOSTIC_ID_LEN] = {
253
260
[PM_WARN_AMBIGUOUS_FIRST_ARGUMENT_PLUS ] = "Ambiguous first argument; put parentheses or a space even after `+` operator" ,
254
261
[PM_WARN_AMBIGUOUS_PREFIX_STAR ] = "Ambiguous `*` has been interpreted as an argument prefix" ,
255
262
[PM_WARN_AMBIGUOUS_SLASH ] = "Ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator" ,
263
+ [PM_WARN_END_IN_METHOD ] = "END in method; use at_exit" ,
256
264
};
257
265
258
266
static const char *
259
267
pm_diagnostic_message (pm_diagnostic_id_t diag_id ) {
260
268
assert (diag_id < PM_DIAGNOSTIC_ID_LEN );
269
+
261
270
const char * message = diagnostic_messages [diag_id ];
262
271
assert (message );
272
+
263
273
return message ;
264
274
}
265
275
@@ -271,7 +281,57 @@ pm_diagnostic_list_append(pm_list_t *list, const uint8_t *start, const uint8_t *
271
281
pm_diagnostic_t * diagnostic = (pm_diagnostic_t * ) calloc (sizeof (pm_diagnostic_t ), 1 );
272
282
if (diagnostic == NULL ) return false;
273
283
274
- * diagnostic = (pm_diagnostic_t ) { .start = start , .end = end , .message = pm_diagnostic_message (diag_id ) };
284
+ * diagnostic = (pm_diagnostic_t ) {
285
+ .start = start ,
286
+ .end = end ,
287
+ .message = pm_diagnostic_message (diag_id ),
288
+ .owned = false
289
+ };
290
+
291
+ pm_list_append (list , (pm_list_node_t * ) diagnostic );
292
+ return true;
293
+ }
294
+
295
+ /**
296
+ * Append a diagnostic to the given list of diagnostics that is using a format
297
+ * string for its message.
298
+ */
299
+ bool
300
+ pm_diagnostic_list_append_format (pm_list_t * list , const uint8_t * start , const uint8_t * end , pm_diagnostic_id_t diag_id , ...) {
301
+ va_list arguments ;
302
+ va_start (arguments , diag_id );
303
+
304
+ const char * format = pm_diagnostic_message (diag_id );
305
+ int result = vsnprintf (NULL , 0 , format , arguments );
306
+ va_end (arguments );
307
+
308
+ if (result < 0 ) {
309
+ return false;
310
+ }
311
+
312
+ pm_diagnostic_t * diagnostic = (pm_diagnostic_t * ) calloc (sizeof (pm_diagnostic_t ), 1 );
313
+ if (diagnostic == NULL ) {
314
+ return false;
315
+ }
316
+
317
+ size_t length = (size_t ) (result + 1 );
318
+ char * message = (char * ) malloc (length );
319
+ if (message == NULL ) {
320
+ free (diagnostic );
321
+ return false;
322
+ }
323
+
324
+ va_start (arguments , diag_id );
325
+ vsnprintf (message , length , format , arguments );
326
+ va_end (arguments );
327
+
328
+ * diagnostic = (pm_diagnostic_t ) {
329
+ .start = start ,
330
+ .end = end ,
331
+ .message = message ,
332
+ .owned = true
333
+ };
334
+
275
335
pm_list_append (list , (pm_list_node_t * ) diagnostic );
276
336
return true;
277
337
}
@@ -285,8 +345,9 @@ pm_diagnostic_list_free(pm_list_t *list) {
285
345
286
346
for (node = list -> head ; node != NULL ; node = next ) {
287
347
next = node -> next ;
288
-
289
348
pm_diagnostic_t * diagnostic = (pm_diagnostic_t * ) node ;
349
+
350
+ if (diagnostic -> owned ) free ((void * ) diagnostic -> message );
290
351
free (diagnostic );
291
352
}
292
353
}
0 commit comments