prism 1.8.0 → 1.8.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2344922b08aa30076aab32c5a92e0d7f21a05f03bb85d089cc69e228a71e3b20
4
- data.tar.gz: 7a44533dd2827ec9f6c31fc69c533c9f90b88520aef71219a348aa61fa460fbd
3
+ metadata.gz: cc702a11a2b52196e74eee050fefa294ac3c2aef3dcd7d4ab2f347e075707286
4
+ data.tar.gz: 32666fef05c64edc7a55ab517d6b582931f9b5b11ff22b5d9dfc5c7d00ee00b2
5
5
  SHA512:
6
- metadata.gz: c278e7b881b89f51150850df09062d9a9bd5e5076746e4b86ab199729a588f8aa346e12b6ba9b95dc0cf53592866bf216977bbb7da10cef6bd8a018681e9f45f
7
- data.tar.gz: '009dee7695d1f7d58adb68d3829f97ecff445cc0eb8509526979f938932e553abdc2ba601049df67b8b29a75b7d542a9fb06d4c1984131d6f60e2ac9e3cf83c2'
6
+ metadata.gz: 2507880056ab51a2aafb14b6927a5d009ff8f3be4eb9917705a56ac59ac6c21c4a687f984652f2f4abe813e24f239077ee5aa0cd7308b6f3240fa864b1b06b28
7
+ data.tar.gz: 921a61d5bd263f70975250aca097c6ed36b747762098b2bc90d113d88f8c8f802e931bf7c2f78c365bce9390190b53bc1c243c1dfa5d3ea2a9c89a12b45659fb
data/CHANGELOG.md CHANGED
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [1.8.1] - 2026-03-16
10
+
11
+ ### Changed
12
+
13
+ - Fix `not` binding power in endless methods.
14
+ - Correctly handle `and?` and similar on Ruby 4.0.
15
+ - Fix error message for block/lambda with `...` argument.
16
+ - Fix `in` handling.
17
+
7
18
  ## [1.8.0] - 2026-01-12
8
19
 
9
20
  ### Added
@@ -19,8 +30,6 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
19
30
  - Decouple ripper translator from ripper library.
20
31
  - Sync Prism::Translation::ParserCurrent with Ruby 4.0.
21
32
 
22
- ## [Unreleased]
23
-
24
33
  ## [1.7.0] - 2025-12-18
25
34
 
26
35
  ### Added
@@ -731,7 +740,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
731
740
 
732
741
  - 🎉 Initial release! 🎉
733
742
 
734
- [unreleased]: https://github.com/ruby/prism/compare/v1.8.0...HEAD
743
+ [unreleased]: https://github.com/ruby/prism/compare/v1.8.1...HEAD
744
+ [1.8.1]: https://github.com/ruby/prism/compare/v1.8.0...v1.8.1
735
745
  [1.8.0]: https://github.com/ruby/prism/compare/v1.7.0...v1.8.0
736
746
  [1.7.0]: https://github.com/ruby/prism/compare/v1.6.0...v1.7.0
737
747
  [1.6.0]: https://github.com/ruby/prism/compare/v1.5.2...v1.6.0
data/config.yml CHANGED
@@ -17,6 +17,8 @@ errors:
17
17
  - ARGUMENT_FORWARDING_UNBOUND
18
18
  - ARGUMENT_NO_FORWARDING_AMPERSAND
19
19
  - ARGUMENT_NO_FORWARDING_ELLIPSES
20
+ - ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA
21
+ - ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK
20
22
  - ARGUMENT_NO_FORWARDING_STAR
21
23
  - ARGUMENT_NO_FORWARDING_STAR_STAR
22
24
  - ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT
@@ -1,7 +1,7 @@
1
1
  #ifndef PRISM_EXT_NODE_H
2
2
  #define PRISM_EXT_NODE_H
3
3
 
4
- #define EXPECTED_PRISM_VERSION "1.8.0"
4
+ #define EXPECTED_PRISM_VERSION "1.8.1"
5
5
 
6
6
  #include <ruby.h>
7
7
  #include <ruby/encoding.h>
@@ -48,6 +48,8 @@ typedef enum {
48
48
  PM_ERR_ARGUMENT_FORWARDING_UNBOUND,
49
49
  PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND,
50
50
  PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
51
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA,
52
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK,
51
53
  PM_ERR_ARGUMENT_NO_FORWARDING_STAR,
52
54
  PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR,
53
55
  PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT,
@@ -19,11 +19,11 @@
19
19
  /**
20
20
  * The patch version of the Prism library as an int.
21
21
  */
22
- #define PRISM_VERSION_PATCH 0
22
+ #define PRISM_VERSION_PATCH 1
23
23
 
24
24
  /**
25
25
  * The version of the Prism library as a constant string.
26
26
  */
27
- #define PRISM_VERSION "1.8.0"
27
+ #define PRISM_VERSION "1.8.1"
28
28
 
29
29
  #endif
@@ -25,7 +25,7 @@ module Prism
25
25
 
26
26
  # The patch version of prism that we are expecting to find in the serialized
27
27
  # strings.
28
- PATCH_VERSION = 0
28
+ PATCH_VERSION = 1
29
29
 
30
30
  # Deserialize the dumped output from a request to parse or parse_file.
31
31
  #
@@ -354,6 +354,8 @@ module Prism
354
354
  :argument_forwarding_unbound,
355
355
  :argument_no_forwarding_ampersand,
356
356
  :argument_no_forwarding_ellipses,
357
+ :argument_no_forwarding_ellipses_lambda,
358
+ :argument_no_forwarding_ellipses_block,
357
359
  :argument_no_forwarding_star,
358
360
  :argument_no_forwarding_star_star,
359
361
  :argument_splat_after_assoc_splat,
data/prism.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "prism"
5
- spec.version = "1.8.0"
5
+ spec.version = "1.8.1"
6
6
  spec.authors = ["Shopify"]
7
7
  spec.email = ["ruby@shopify.com"]
8
8
 
data/src/diagnostic.c CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  #include "prism/diagnostic.h"
12
12
 
13
- #define PM_DIAGNOSTIC_ID_MAX 324
13
+ #define PM_DIAGNOSTIC_ID_MAX 326
14
14
 
15
15
  /** This struct holds the data for each diagnostic. */
16
16
  typedef struct {
@@ -112,6 +112,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
112
112
  [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX },
113
113
  [PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX },
114
114
  [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX },
115
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA] = { "unexpected ... in lambda argument", PM_ERROR_LEVEL_SYNTAX },
116
+ [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK] = { "unexpected ... in block argument", PM_ERROR_LEVEL_SYNTAX },
115
117
  [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX },
116
118
  [PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX },
117
119
  [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX },
@@ -442,6 +444,8 @@ pm_diagnostic_id_human(pm_diagnostic_id_t diag_id) {
442
444
  case PM_ERR_ARGUMENT_FORWARDING_UNBOUND: return "argument_forwarding_unbound";
443
445
  case PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND: return "argument_no_forwarding_ampersand";
444
446
  case PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES: return "argument_no_forwarding_ellipses";
447
+ case PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA: return "argument_no_forwarding_ellipses_lambda";
448
+ case PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK: return "argument_no_forwarding_ellipses_block";
445
449
  case PM_ERR_ARGUMENT_NO_FORWARDING_STAR: return "argument_no_forwarding_star";
446
450
  case PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR: return "argument_no_forwarding_star_star";
447
451
  case PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT: return "argument_splat_after_assoc_splat";
data/src/prism.c CHANGED
@@ -9979,8 +9979,21 @@ parser_lex(pm_parser_t *parser) {
9979
9979
  following && (
9980
9980
  (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') ||
9981
9981
  (peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') ||
9982
- (peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) ||
9983
- (peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2)))
9982
+ (
9983
+ peek_at(parser, following) == 'a' &&
9984
+ peek_at(parser, following + 1) == 'n' &&
9985
+ peek_at(parser, following + 2) == 'd' &&
9986
+ peek_at(parser, next_content + 3) != '!' &&
9987
+ peek_at(parser, next_content + 3) != '?' &&
9988
+ !char_is_identifier(parser, following + 3, parser->end - (following + 3))
9989
+ ) ||
9990
+ (
9991
+ peek_at(parser, following) == 'o' &&
9992
+ peek_at(parser, following + 1) == 'r' &&
9993
+ peek_at(parser, next_content + 2) != '!' &&
9994
+ peek_at(parser, next_content + 2) != '?' &&
9995
+ !char_is_identifier(parser, following + 2, parser->end - (following + 2))
9996
+ )
9984
9997
  )
9985
9998
  ) {
9986
9999
  if (!lexed_comment) parser_lex_ignored_newline(parser);
@@ -10051,6 +10064,8 @@ parser_lex(pm_parser_t *parser) {
10051
10064
  peek_at(parser, next_content) == 'a' &&
10052
10065
  peek_at(parser, next_content + 1) == 'n' &&
10053
10066
  peek_at(parser, next_content + 2) == 'd' &&
10067
+ peek_at(parser, next_content + 3) != '!' &&
10068
+ peek_at(parser, next_content + 3) != '?' &&
10054
10069
  !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3))
10055
10070
  ) {
10056
10071
  if (!lexed_comment) parser_lex_ignored_newline(parser);
@@ -10067,6 +10082,8 @@ parser_lex(pm_parser_t *parser) {
10067
10082
  if (
10068
10083
  peek_at(parser, next_content) == 'o' &&
10069
10084
  peek_at(parser, next_content + 1) == 'r' &&
10085
+ peek_at(parser, next_content + 2) != '!' &&
10086
+ peek_at(parser, next_content + 2) != '?' &&
10070
10087
  !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2))
10071
10088
  ) {
10072
10089
  if (!lexed_comment) parser_lex_ignored_newline(parser);
@@ -13859,6 +13876,7 @@ parse_parameters(
13859
13876
  bool allows_forwarding_parameters,
13860
13877
  bool accepts_blocks_in_defaults,
13861
13878
  bool in_block,
13879
+ pm_diagnostic_id_t diag_id_forwarding,
13862
13880
  uint16_t depth
13863
13881
  ) {
13864
13882
  pm_do_loop_stack_push(parser, false);
@@ -13914,7 +13932,7 @@ parse_parameters(
13914
13932
  }
13915
13933
  case PM_TOKEN_UDOT_DOT_DOT: {
13916
13934
  if (!allows_forwarding_parameters) {
13917
- pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES);
13935
+ pm_parser_err_current(parser, diag_id_forwarding);
13918
13936
  }
13919
13937
 
13920
13938
  bool succeeded = update_parameter_state(parser, &parser->current, &order);
@@ -14594,6 +14612,7 @@ parse_block_parameters(
14594
14612
  false,
14595
14613
  accepts_blocks_in_defaults,
14596
14614
  true,
14615
+ is_lambda_literal ? PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_LAMBDA : PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES_BLOCK,
14597
14616
  (uint16_t) (depth + 1)
14598
14617
  );
14599
14618
  if (!is_lambda_literal) {
@@ -18836,7 +18855,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
18836
18855
  if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
18837
18856
  params = NULL;
18838
18857
  } else {
18839
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, false, (uint16_t) (depth + 1));
18858
+ params = parse_parameters(
18859
+ parser,
18860
+ PM_BINDING_POWER_DEFINED,
18861
+ true,
18862
+ false,
18863
+ true,
18864
+ true,
18865
+ false,
18866
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
18867
+ (uint16_t) (depth + 1)
18868
+ );
18840
18869
  }
18841
18870
 
18842
18871
  lex_state_set(parser, PM_LEX_STATE_BEG);
@@ -18861,7 +18890,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
18861
18890
 
18862
18891
  lparen = not_provided(parser);
18863
18892
  rparen = not_provided(parser);
18864
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1));
18893
+ params = parse_parameters(
18894
+ parser,
18895
+ PM_BINDING_POWER_DEFINED,
18896
+ false,
18897
+ false,
18898
+ true,
18899
+ true,
18900
+ false,
18901
+ PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES,
18902
+ (uint16_t) (depth + 1)
18903
+ );
18865
18904
 
18866
18905
  // Reject `def * = 1` and similar. We have to specifically check
18867
18906
  // for them because they create ambiguity with optional arguments.
@@ -18917,7 +18956,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
18917
18956
  context_push(parser, PM_CONTEXT_RESCUE_MODIFIER);
18918
18957
 
18919
18958
  pm_token_t rescue_keyword = parser->previous;
18920
- pm_node_t *value = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
18959
+ pm_node_t *value = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
18921
18960
  context_pop(parser);
18922
18961
 
18923
18962
  statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value));
@@ -20214,7 +20253,7 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_
20214
20253
  pm_token_t rescue = parser->current;
20215
20254
  parser_lex(parser);
20216
20255
 
20217
- pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
20256
+ pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
20218
20257
  context_pop(parser);
20219
20258
 
20220
20259
  return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
@@ -20320,7 +20359,7 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
20320
20359
  }
20321
20360
  }
20322
20361
 
20323
- pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
20362
+ pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MATCH + 1, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
20324
20363
  context_pop(parser);
20325
20364
 
20326
20365
  return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
@@ -21639,12 +21678,6 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
21639
21678
  ) {
21640
21679
  node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
21641
21680
 
21642
- if (context_terminator(parser->current_context->context, &parser->current)) {
21643
- // If this token terminates the current context, then we need to
21644
- // stop parsing the expression, as it has become a statement.
21645
- return node;
21646
- }
21647
-
21648
21681
  switch (PM_NODE_TYPE(node)) {
21649
21682
  case PM_MULTI_WRITE_NODE:
21650
21683
  // Multi-write nodes are statements, and cannot be followed by
@@ -21757,6 +21790,17 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
21757
21790
  break;
21758
21791
  }
21759
21792
  }
21793
+
21794
+ if (context_terminator(parser->current_context->context, &parser->current)) {
21795
+ pm_binding_powers_t next_binding_powers = pm_binding_powers[parser->current.type];
21796
+ if (
21797
+ !next_binding_powers.binary ||
21798
+ binding_power > next_binding_powers.left ||
21799
+ (PM_NODE_TYPE_P(node, PM_CALL_NODE) && pm_call_node_command_p((pm_call_node_t *) node))
21800
+ ) {
21801
+ return node;
21802
+ }
21803
+ }
21760
21804
  }
21761
21805
 
21762
21806
  return node;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prism
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify