Skip to content

Commit cfdf428

Browse files
committed
Bump Prism to v1.5.2
[Backport #21187]
1 parent 955decc commit cfdf428

27 files changed

Lines changed: 216 additions & 56 deletions

lib/prism/polyfill/warn.rb

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,29 @@
77
Kernel.prepend(
88
Module.new {
99
def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
10-
uplevel =
11-
case uplevel
12-
when nil
13-
1
14-
when Integer
15-
uplevel + 1
16-
else
17-
uplevel.to_int + 1
18-
end
19-
20-
super(*msgs, uplevel: uplevel)
10+
case uplevel
11+
when nil
12+
super(*msgs)
13+
when Integer
14+
super(*msgs, uplevel: uplevel + 1)
15+
else
16+
super(*msgs, uplevel: uplevel.to_int + 1)
17+
end
2118
end
2219
}
2320
)
2421

2522
Object.prepend(
2623
Module.new {
2724
def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
28-
uplevel =
29-
case uplevel
30-
when nil
31-
1
32-
when Integer
33-
uplevel + 1
34-
else
35-
uplevel.to_int + 1
36-
end
37-
38-
super(*msgs, uplevel: uplevel)
25+
case uplevel
26+
when nil
27+
super(*msgs)
28+
when Integer
29+
super(*msgs, uplevel: uplevel + 1)
30+
else
31+
super(*msgs, uplevel: uplevel.to_int + 1)
32+
end
3933
end
4034
}
4135
)

lib/prism/prism.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Gem::Specification.new do |spec|
44
spec.name = "prism"
5-
spec.version = "1.5.1"
5+
spec.version = "1.5.2"
66
spec.authors = ["Shopify"]
77
spec.email = ["ruby@shopify.com"]
88

lib/prism/translation/parser.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@ module Translation
1919
# whitequark/parser gem's syntax tree. It inherits from the base parser for
2020
# the parser gem, and overrides the parse* methods to parse with prism and
2121
# then translate.
22+
#
23+
# Note that this version of the parser always parses using the latest
24+
# version of Ruby syntax supported by Prism. If you want specific version
25+
# support, use one of the version-specific subclasses, such as
26+
# `Prism::Translation::Parser34`. If you want to parse using the same
27+
# version of Ruby syntax as the currently running version of Ruby, use
28+
# `Prism::Translation::ParserCurrent`.
2229
class Parser < ::Parser::Base
2330
Diagnostic = ::Parser::Diagnostic # :nodoc:
2431
private_constant :Diagnostic
@@ -77,7 +84,7 @@ def initialize(builder = Prism::Translation::Parser::Builder.new, parser: Prism)
7784
end
7885

7986
def version # :nodoc:
80-
34
87+
35
8188
end
8289

8390
# The default encoding for Ruby files is UTF-8.

lib/prism/translation/ruby_parser.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def visit_assoc_splat_node(node)
152152
# ^^
153153
# ```
154154
def visit_back_reference_read_node(node)
155-
s(node, :back_ref, node.name.name.delete_prefix("$").to_sym)
155+
s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym)
156156
end
157157

158158
# ```

prism/config.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ errors:
6060
- CONDITIONAL_WHILE_PREDICATE
6161
- CONSTANT_PATH_COLON_COLON_CONSTANT
6262
- DEF_ENDLESS
63+
- DEF_ENDLESS_PARAMETERS
6364
- DEF_ENDLESS_SETTER
6465
- DEF_NAME
6566
- DEF_PARAMS_TERM
@@ -1800,7 +1801,7 @@ nodes:
18001801
Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
18011802
18021803
case true; when false; end
1803-
^^^^
1804+
^^^^
18041805
- name: conditions
18051806
type: node[]
18061807
kind: WhenNode

prism/extension.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef PRISM_EXT_NODE_H
22
#define PRISM_EXT_NODE_H
33

4-
#define EXPECTED_PRISM_VERSION "1.5.1"
4+
#define EXPECTED_PRISM_VERSION "1.5.2"
55

66
#include <ruby.h>
77
#include <ruby/encoding.h>

prism/prism.c

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2622,10 +2622,11 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
26222622
// There are certain flags that we want to use internally but don't want to
26232623
// expose because they are not relevant beyond parsing. Therefore we'll define
26242624
// them here and not define them in config.yml/a header file.
2625-
static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = 0x4;
2626-
static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = 0x40;
2627-
static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = 0x80;
2628-
static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x100;
2625+
static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = (1 << 2);
2626+
2627+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = ((PM_CALL_NODE_FLAGS_LAST - 1) << 1);
2628+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = ((PM_CALL_NODE_FLAGS_LAST - 1) << 2);
2629+
static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAST - 1) << 3);
26292630

26302631
/**
26312632
* Allocate and initialize a new CallNode node. This sets everything to NULL or
@@ -5279,6 +5280,12 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
52795280

52805281
switch (PM_NODE_TYPE(part)) {
52815282
case PM_STRING_NODE:
5283+
// If inner string is not frozen, it stops being a static literal. We should *not* clear other flags,
5284+
// because concatenating two frozen strings (`'foo' 'bar'`) is still frozen. This holds true for
5285+
// as long as this interpolation only consists of other string literals.
5286+
if (!PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) {
5287+
pm_node_flag_unset((pm_node_t *) node, PM_NODE_FLAG_STATIC_LITERAL);
5288+
}
52825289
part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
52835290
break;
52845291
case PM_INTERPOLATED_STRING_NODE:
@@ -14443,6 +14450,17 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
1444314450
if (accepted_newline) {
1444414451
pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
1444514452
}
14453+
14454+
// If this is a command call and an argument takes a block,
14455+
// there can be no further arguments. For example,
14456+
// `foo(bar 1 do end, 2)` should be rejected.
14457+
if (PM_NODE_TYPE_P(argument, PM_CALL_NODE)) {
14458+
pm_call_node_t *call = (pm_call_node_t *) argument;
14459+
if (call->opening_loc.start == NULL && call->arguments != NULL && call->block != NULL) {
14460+
pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
14461+
break;
14462+
}
14463+
}
1444614464
} else {
1444714465
// If there is no comma at the end of the argument list then we're
1444814466
// done parsing arguments and can break out of this loop.
@@ -14594,6 +14612,18 @@ update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_ord
1459414612
return true;
1459514613
}
1459614614

14615+
/**
14616+
* Ensures that after parsing a parameter, the next token is not `=`.
14617+
* Some parameters like `def(* = 1)` cannot become optional. When no parens
14618+
* are present like in `def * = 1`, this creates ambiguity with endless method definitions.
14619+
*/
14620+
static inline void
14621+
refute_optional_parameter(pm_parser_t *parser) {
14622+
if (match1(parser, PM_TOKEN_EQUAL)) {
14623+
pm_parser_err_previous(parser, PM_ERR_DEF_ENDLESS_PARAMETERS);
14624+
}
14625+
}
14626+
1459714627
/**
1459814628
* Parse a list of parameters on a method definition.
1459914629
*/
@@ -14646,6 +14676,10 @@ parse_parameters(
1464614676
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_BLOCK;
1464714677
}
1464814678

14679+
if (!uses_parentheses) {
14680+
refute_optional_parameter(parser);
14681+
}
14682+
1464914683
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
1465014684
if (repeated) {
1465114685
pm_node_flag_set_repeated_parameter((pm_node_t *)param);
@@ -14667,6 +14701,10 @@ parse_parameters(
1466714701
bool succeeded = update_parameter_state(parser, &parser->current, &order);
1466814702
parser_lex(parser);
1466914703

14704+
if (!uses_parentheses) {
14705+
refute_optional_parameter(parser);
14706+
}
14707+
1467014708
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL;
1467114709
pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous);
1467214710

@@ -14848,6 +14886,10 @@ parse_parameters(
1484814886
context_pop(parser);
1484914887
pm_parameters_node_keywords_append(params, param);
1485014888

14889+
if (!uses_parentheses) {
14890+
refute_optional_parameter(parser);
14891+
}
14892+
1485114893
// If parsing the value of the parameter resulted in error recovery,
1485214894
// then we can put a missing node in its place and stop parsing the
1485314895
// parameters entirely now.
@@ -14879,6 +14921,10 @@ parse_parameters(
1487914921
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS;
1488014922
}
1488114923

14924+
if (!uses_parentheses) {
14925+
refute_optional_parameter(parser);
14926+
}
14927+
1488214928
pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
1488314929
if (repeated) {
1488414930
pm_node_flag_set_repeated_parameter(param);
@@ -14927,6 +14973,10 @@ parse_parameters(
1492714973
}
1492814974
}
1492914975

14976+
if (!uses_parentheses) {
14977+
refute_optional_parameter(parser);
14978+
}
14979+
1493014980
if (params->keyword_rest == NULL) {
1493114981
pm_parameters_node_keyword_rest_set(params, param);
1493214982
} else {
@@ -18491,20 +18541,28 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
1849118541
return (pm_node_t *) node;
1849218542
}
1849318543
case PM_TOKEN_CHARACTER_LITERAL: {
18494-
parser_lex(parser);
18495-
18496-
pm_token_t opening = parser->previous;
18497-
opening.type = PM_TOKEN_STRING_BEGIN;
18498-
opening.end = opening.start + 1;
18499-
18500-
pm_token_t content = parser->previous;
18501-
content.type = PM_TOKEN_STRING_CONTENT;
18502-
content.start = content.start + 1;
18503-
1850418544
pm_token_t closing = not_provided(parser);
18505-
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &content, &closing);
18545+
pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(
18546+
parser,
18547+
&(pm_token_t) {
18548+
.type = PM_TOKEN_STRING_BEGIN,
18549+
.start = parser->current.start,
18550+
.end = parser->current.start + 1
18551+
},
18552+
&(pm_token_t) {
18553+
.type = PM_TOKEN_STRING_CONTENT,
18554+
.start = parser->current.start + 1,
18555+
.end = parser->current.end
18556+
},
18557+
&closing
18558+
);
18559+
1850618560
pm_node_flag_set(node, parse_unescaped_encoding(parser));
1850718561

18562+
// Skip past the character literal here, since now we have handled
18563+
// parser->explicit_encoding correctly.
18564+
parser_lex(parser);
18565+
1850818566
// Characters can be followed by strings in which case they are
1850918567
// automatically concatenated.
1851018568
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
@@ -20901,7 +20959,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
2090120959
bool permitted = true;
2090220960
if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false;
2090320961

20904-
pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id, (uint16_t) (depth + 1));
20962+
pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MODIFIER, diag_id, (uint16_t) (depth + 1));
2090520963
if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE);
2090620964

2090720965
parse_assignment_value_local(parser, value);
@@ -22498,9 +22556,10 @@ parse_program(pm_parser_t *parser) {
2249822556
statements = wrap_statements(parser, statements);
2249922557
} else {
2250022558
flush_block_exits(parser, previous_block_exits);
22501-
pm_node_list_free(&current_block_exits);
2250222559
}
2250322560

22561+
pm_node_list_free(&current_block_exits);
22562+
2250422563
// If this is an empty file, then we're still going to parse all of the
2250522564
// statements in order to gather up all of the comments and such. Here we'll
2250622565
// correct the location information.

prism/templates/include/prism/ast.h.erb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,8 @@ typedef enum pm_<%= flag.human %> {
212212
/** <%= value.comment %> */
213213
PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << (index + Prism::Template::COMMON_FLAGS_COUNT) %>,
214214
<%- end -%>
215+
216+
PM_<%= flag.human.upcase %>_LAST,
215217
} pm_<%= flag.human %>_t;
216218
<%- end -%>
217219

prism/templates/lib/prism/serialize.rb.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ module Prism
1414

1515
# The patch version of prism that we are expecting to find in the serialized
1616
# strings.
17-
PATCH_VERSION = 1
17+
PATCH_VERSION = 2
1818

1919
# Deserialize the dumped output from a request to parse or parse_file.
2020
#

prism/templates/src/diagnostic.c.erb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
144144
[PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_LEVEL_SYNTAX },
145145
[PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_LEVEL_SYNTAX },
146146
[PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX },
147+
[PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX },
147148
[PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
148149
[PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX },
149150
[PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX },

0 commit comments

Comments
 (0)