зеркало из https://github.com/github/ruby.git
[ruby/prism] Better error recovery for unwritable nodes
https://github.com/ruby/prism/commit/4828e73263
This commit is contained in:
Родитель
e8f3ea3f87
Коммит
982dfa0793
|
@ -104,6 +104,14 @@ errors:
|
||||||
- EXPECT_STRING_CONTENT
|
- EXPECT_STRING_CONTENT
|
||||||
- EXPECT_WHEN_DELIMITER
|
- EXPECT_WHEN_DELIMITER
|
||||||
- EXPRESSION_BARE_HASH
|
- EXPRESSION_BARE_HASH
|
||||||
|
- EXPRESSION_NOT_WRITABLE
|
||||||
|
- EXPRESSION_NOT_WRITABLE_ENCODING
|
||||||
|
- EXPRESSION_NOT_WRITABLE_FALSE
|
||||||
|
- EXPRESSION_NOT_WRITABLE_FILE
|
||||||
|
- EXPRESSION_NOT_WRITABLE_LINE
|
||||||
|
- EXPRESSION_NOT_WRITABLE_NIL
|
||||||
|
- EXPRESSION_NOT_WRITABLE_SELF
|
||||||
|
- EXPRESSION_NOT_WRITABLE_TRUE
|
||||||
- FLOAT_PARSE
|
- FLOAT_PARSE
|
||||||
- FOR_COLLECTION
|
- FOR_COLLECTION
|
||||||
- FOR_IN
|
- FOR_IN
|
||||||
|
|
|
@ -12945,6 +12945,32 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certain expressions are not writable, but in order to provide a better
|
||||||
|
* experience we give a specific error message. In order to maintain as much
|
||||||
|
* information in the tree as possible, we replace them with local variable
|
||||||
|
* writes.
|
||||||
|
*/
|
||||||
|
static pm_node_t *
|
||||||
|
parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t *equals, pm_node_t *value) {
|
||||||
|
switch (PM_NODE_TYPE(target)) {
|
||||||
|
case PM_SOURCE_ENCODING_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING); break;
|
||||||
|
case PM_FALSE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE); break;
|
||||||
|
case PM_SOURCE_FILE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_FILE); break;
|
||||||
|
case PM_SOURCE_LINE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_LINE); break;
|
||||||
|
case PM_NIL_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_NIL); break;
|
||||||
|
case PM_SELF_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_SELF); break;
|
||||||
|
case PM_TRUE_NODE: pm_parser_err_token(parser, equals, PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pm_constant_id_t name = pm_parser_constant_id_location(parser, target->location.start, target->location.end);
|
||||||
|
pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals);
|
||||||
|
|
||||||
|
pm_node_destroy(parser, target);
|
||||||
|
return (pm_node_t *) result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse a list of targets for assignment. This is used in the case of a for
|
* Parse a list of targets for assignment. This is used in the case of a for
|
||||||
* loop or a multi-assignment. For example, in the following code:
|
* loop or a multi-assignment. For example, in the following code:
|
||||||
|
@ -19357,13 +19383,25 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
|
||||||
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
||||||
return parse_write(parser, (pm_node_t *) multi_target, &token, value);
|
return parse_write(parser, (pm_node_t *) multi_target, &token, value);
|
||||||
}
|
}
|
||||||
default:
|
case PM_SOURCE_ENCODING_NODE:
|
||||||
|
case PM_FALSE_NODE:
|
||||||
|
case PM_SOURCE_FILE_NODE:
|
||||||
|
case PM_SOURCE_LINE_NODE:
|
||||||
|
case PM_NIL_NODE:
|
||||||
|
case PM_SELF_NODE:
|
||||||
|
case PM_TRUE_NODE: {
|
||||||
|
// In these special cases, we have specific error messages
|
||||||
|
// and we will replace them with local variable writes.
|
||||||
parser_lex(parser);
|
parser_lex(parser);
|
||||||
|
pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
||||||
// In this case we have an = sign, but we don't know what it's for. We
|
return parse_unwriteable_write(parser, node, &token, value);
|
||||||
// need to treat it as an error. For now, we'll mark it as an error
|
}
|
||||||
// and just skip right past it.
|
default:
|
||||||
pm_parser_err_token(parser, &token, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
|
// In this case we have an = sign, but we don't know what
|
||||||
|
// it's for. We need to treat it as an error. We'll mark it
|
||||||
|
// as an error and skip past it.
|
||||||
|
parser_lex(parser);
|
||||||
|
pm_parser_err_token(parser, &token, PM_ERR_EXPRESSION_NOT_WRITABLE);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,14 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
|
||||||
[PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_SYNTAX },
|
||||||
[PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_SYNTAX },
|
||||||
[PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE] = { "unexpected '='; target cannot be written", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_ENCODING] = { "Can't assign to __ENCODING__", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_FALSE] = { "Can't assign to false", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_FILE] = { "Can't assign to __FILE__", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_LINE] = { "Can't assign to __LINE__", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_NIL] = { "Can't assign to nil", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_SELF] = { "Can't change the value of self", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
[PM_ERR_EXPRESSION_NOT_WRITABLE_TRUE] = { "Can't assign to true", PM_ERROR_LEVEL_SYNTAX },
|
||||||
[PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_FLOAT_PARSE] = { "could not parse the float '%.*s'", PM_ERROR_LEVEL_SYNTAX },
|
||||||
[PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_FOR_COLLECTION] = { "expected a collection after the `in` in a `for` statement", PM_ERROR_LEVEL_SYNTAX },
|
||||||
[PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_SYNTAX },
|
[PM_ERR_FOR_INDEX] = { "expected an index after `for`", PM_ERROR_LEVEL_SYNTAX },
|
||||||
|
|
Загрузка…
Ссылка в новой задаче