From 1df1edc080031b8f18b41a5a8d308a667ea89fc1 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Mon, 6 May 2024 10:28:36 -0400 Subject: [PATCH 001/151] YJIT: Fix comment and counter in rb_yjit_invalidate_ep_is_bp() (#10722) `mem::take` substitutes an empty instance which makes `jit.ep_is_bp()` return false. --- yjit/src/invariants.rs | 5 ++--- yjit/src/stats.rs | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/yjit/src/invariants.rs b/yjit/src/invariants.rs index 695a37878f285b..6639fd677b3344 100644 --- a/yjit/src/invariants.rs +++ b/yjit/src/invariants.rs @@ -584,11 +584,10 @@ pub extern "C" fn rb_yjit_invalidate_ep_is_bp(iseq: IseqPtr) { let no_ep_escape_iseqs = &mut Invariants::get_instance().no_ep_escape_iseqs; match no_ep_escape_iseqs.get_mut(&iseq) { Some(blocks) => { - // Invalidate existing blocks and let jit.ep_is_bp() - // return true when they are compiled again + // Invalidate existing blocks and make jit.ep_is_bp() return false for block in mem::take(blocks) { invalidate_block_version(&block); - incr_counter!(invalidate_no_singleton_class); + incr_counter!(invalidate_ep_escape); } } None => { diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 0a63fab8b049ae..6ffe28f12adcac 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -268,7 +268,7 @@ macro_rules! make_counters { /// The list of counters that are available without --yjit-stats. /// They are incremented only by `incr_counter!` and don't use `gen_counter_incr`. -pub const DEFAULT_COUNTERS: [Counter; 16] = [ +pub const DEFAULT_COUNTERS: [Counter; 17] = [ Counter::code_gc_count, Counter::compiled_iseq_entry, Counter::cold_iseq_entry, @@ -286,6 +286,7 @@ pub const DEFAULT_COUNTERS: [Counter; 16] = [ Counter::invalidate_constant_state_bump, Counter::invalidate_constant_ic_fill, Counter::invalidate_no_singleton_class, + Counter::invalidate_ep_escape, ]; /// Macro to increase a counter by name and count @@ -568,6 +569,7 @@ make_counters! { invalidate_constant_state_bump, invalidate_constant_ic_fill, invalidate_no_singleton_class, + invalidate_ep_escape, // Currently, it's out of the ordinary (might be impossible) for YJIT to leave gaps in // executable memory, so this should be 0. From 88d74a4848998435e4a6d1bf2d70dde3d8996532 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Mon, 6 May 2024 16:15:24 +0200 Subject: [PATCH 002/151] [DOC] Fix typos in WeakMap docs --- weakmap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/weakmap.c b/weakmap.c index 86920952f3d657..8939056811ef74 100644 --- a/weakmap.c +++ b/weakmap.c @@ -985,7 +985,7 @@ wkmap_inspect(VALUE self) * * Keys in the map are compared by identity. * - * m = ObjectSpace::WeekMap.new + * m = ObjectSpace::WeakMap.new * key1 = "foo" * val1 = Object.new * m[key1] = val1 @@ -1041,13 +1041,13 @@ wkmap_inspect(VALUE self) * * val = nil * GC.start - * # There is no more references to `val`, yet the pair isn't + * # There are no more references to `val`, yet the pair isn't * # garbage-collected. * map["name"] #=> 2023-12-07 00:00:00 +0200 * * key = nil * GC.start - * # There is no more references to `key`, key and value are + * # There are no more references to `key`, key and value are * # garbage-collected. * map["name"] #=> nil * From 5909186d02f2b50eea23a8661543744ef7c9342b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:09:15 -0400 Subject: [PATCH 003/151] [ruby/prism] Fix up error message for unexpected { https://github.com/ruby/prism/commit/80dbe035ba --- prism/templates/src/diagnostic.c.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 86e7c3b6d1ac7a..d9a199964514e1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -106,7 +106,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT] = { "unexpected `*` splat argument after a `**` keyword splat argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_SPLAT_AFTER_SPLAT] = { "unexpected `*` splat argument after a `*` splat argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_TERM_PAREN] = { "unexpected %s; expected a `)` to close the arguments", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected `{` after a method call without parenthesis", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_UNEXPECTED_BLOCK] = { "unexpected '{' after a method call without parenthesis", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_ELEMENT] = { "expected an element for the array", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_LEVEL_SYNTAX }, From 14d400829d7bc6cdc8111ba534fb9e6aad2e96b5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:12:30 -0400 Subject: [PATCH 004/151] [PRISM] Enable passing test_brace_after_literal_argument test --- test/.excludes-prism/TestSyntax.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index 72b0e2bac2fd41..47fd0456e6fd89 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -4,7 +4,6 @@ exclude(:test_anonymous_rest_forwarding, "unknown") exclude(:test_argument_forwarding_with_super, "unknown") exclude(:test_argument_forwarding, "unknown") -exclude(:test_brace_after_literal_argument, "unknown") exclude(:test_dedented_heredoc_concatenation, "unknown") exclude(:test_dedented_heredoc_continued_line, "unknown") exclude(:test_duplicated_when, "unknown") From f92d82ef06f5478bd942a22ca987f787fa92cedc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:01:50 -0400 Subject: [PATCH 005/151] [ruby/prism] More specific error for conflicting forwarding parameters https://github.com/ruby/prism/commit/1c3b48fedb --- prism/config.yml | 5 +- prism/prism.c | 89 ++++++++++++++++++++++------ prism/templates/src/diagnostic.c.erb | 5 +- 3 files changed, 80 insertions(+), 19 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 4fc4aa8e6aa91a..5e6ee82ca490d4 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -7,13 +7,16 @@ errors: - ARGUMENT_BARE_HASH - ARGUMENT_BLOCK_FORWARDING - ARGUMENT_BLOCK_MULTI + - ARGUMENT_CONFLICT_AMPERSAND + - ARGUMENT_CONFLICT_STAR + - ARGUMENT_CONFLICT_STAR_STAR - ARGUMENT_FORMAL_CLASS - ARGUMENT_FORMAL_CONSTANT - ARGUMENT_FORMAL_GLOBAL - ARGUMENT_FORMAL_IVAR - ARGUMENT_FORWARDING_UNBOUND - ARGUMENT_IN - - ARGUMENT_NO_FORWARDING_AMP + - ARGUMENT_NO_FORWARDING_AMPERSAND - ARGUMENT_NO_FORWARDING_ELLIPSES - ARGUMENT_NO_FORWARDING_STAR - ARGUMENT_NO_FORWARDING_STAR_STAR diff --git a/prism/prism.c b/prism/prism.c index d4926c25e45cf5..4f55dad954ff79 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -749,42 +749,97 @@ pm_parser_scope_find(pm_parser_t *parser, uint32_t depth) { return scope; } -static void -pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const pm_token_t * token, const uint8_t mask, pm_diagnostic_id_t diag) { +typedef enum { + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS, + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT, + PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL +} pm_scope_forwarding_param_check_result_t; + +static pm_scope_forwarding_param_check_result_t +pm_parser_scope_forwarding_param_check(pm_parser_t *parser, const uint8_t mask) { pm_scope_t *scope = parser->current_scope; - while (scope) { + bool conflict = false; + + while (scope != NULL) { if (scope->parameters & mask) { - if (!scope->closed) { - pm_parser_err_token(parser, token, diag); - return; + if (scope->closed) { + if (conflict) { + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT; + } else { + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS; + } } - return; + + conflict = true; } + if (scope->closed) break; scope = scope->previous; } - pm_parser_err_token(parser, token, diag); + return PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL; } -static inline void +static void pm_parser_scope_forwarding_block_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK, PM_ERR_ARGUMENT_NO_FORWARDING_AMP); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_BLOCK)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_AMPERSAND); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND); + break; + } } -static inline void +static void pm_parser_scope_forwarding_positionals_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_STAR); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_STAR); + break; + } } -static inline void -pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_ALL, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); +static void +pm_parser_scope_forwarding_all_check(pm_parser_t *parser, const pm_token_t *token) { + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_ALL)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + // This shouldn't happen, because ... is not allowed in the + // declaration of blocks. If we get here, we assume we already have + // an error for this. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); + break; + } } -static inline void +static void pm_parser_scope_forwarding_keywords_check(pm_parser_t *parser, const pm_token_t * token) { - pm_parser_scope_forwarding_param_check(parser, token, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR); + switch (pm_parser_scope_forwarding_param_check(parser, PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS)) { + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_PASS: + // Pass. + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_CONFLICT: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_CONFLICT_STAR_STAR); + break; + case PM_SCOPE_FORWARDING_PARAM_CHECK_RESULT_FAIL: + pm_parser_err_token(parser, token, PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR); + break; + } } /** diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index d9a199964514e1..ed3c61ec79ab1b 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -93,13 +93,16 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "both block arg and actual block given; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_AMPERSAND] = { "unexpected `&`; anonymous block parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_STAR] = { "unexpected `*`; anonymous rest parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_CONFLICT_STAR_STAR] = { "unexpected `**`; anonymous keyword rest parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_CLASS] = { "invalid formal argument; formal argument cannot be a class variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_CONSTANT] = { "invalid formal argument; formal argument cannot be a constant", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_NO_FORWARDING_AMP] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_NO_FORWARDING_STAR_STAR] = { "unexpected `**`; no anonymous keyword rest parameter", PM_ERROR_LEVEL_SYNTAX }, From 5e6bb0857aac9ee16d47b5a7a547fc5ba329f088 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:05:49 -0400 Subject: [PATCH 006/151] [PRISM] Enable passing forwarding parameter tests --- test/.excludes-prism/TestSyntax.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index 47fd0456e6fd89..257db7f328ecc0 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -1,7 +1,4 @@ exclude(:test__END___cr, "unknown") -exclude(:test_anonymous_block_forwarding, "unknown") -exclude(:test_anonymous_keyword_rest_forwarding, "unknown") -exclude(:test_anonymous_rest_forwarding, "unknown") exclude(:test_argument_forwarding_with_super, "unknown") exclude(:test_argument_forwarding, "unknown") exclude(:test_dedented_heredoc_concatenation, "unknown") From d4fdc459537abf5d4a76bef2e1cc62a02f3dc2b0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:21:28 -0400 Subject: [PATCH 007/151] [ruby/prism] Unexpected fractional component error messages https://github.com/ruby/prism/commit/e893bc2230 --- prism/config.yml | 1 + prism/prism.c | 10 ++++++++++ prism/templates/src/diagnostic.c.erb | 1 + 3 files changed, 12 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 5e6ee82ca490d4..4e85a6f34df6cb 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -145,6 +145,7 @@ errors: - INVALID_MULTIBYTE_ESCAPE - INVALID_NUMBER_BINARY - INVALID_NUMBER_DECIMAL + - INVALID_NUMBER_FRACTION - INVALID_NUMBER_HEXADECIMAL - INVALID_NUMBER_OCTAL - INVALID_NUMBER_UNDERSCORE_INNER diff --git a/prism/prism.c b/prism/prism.c index 4f55dad954ff79..44b4dc5ae53138 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8851,6 +8851,16 @@ lex_numeric_prefix(pm_parser_t *parser, bool* seen_e) { type = lex_optional_float_suffix(parser, seen_e); } + // At this point we have a completed number, but we want to provide the user + // with a good experience if they put an additional .xxx fractional + // component on the end, so we'll check for that here. + if (peek_offset(parser, 0) == '.' && pm_char_is_decimal_digit(peek_offset(parser, 1))) { + const uint8_t *fraction_start = parser->current.end; + const uint8_t *fraction_end = parser->current.end + 2; + fraction_end += pm_strspn_decimal_digit(fraction_end, parser->end - fraction_end); + pm_parser_err(parser, fraction_start, fraction_end, PM_ERR_INVALID_NUMBER_FRACTION); + } + return type; } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index ed3c61ec79ab1b..04b8af858b1a64 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -224,6 +224,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_LOCAL_VARIABLE_WRITE] = { "identifier %.*s is not valid to set", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_BINARY] = { "invalid binary number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_DECIMAL] = { "invalid decimal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_NUMBER_FRACTION] = { "unexpected fraction part after numeric literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_HEXADECIMAL] = { "invalid hexadecimal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_UNDERSCORE_INNER] = { "invalid underscore placement in number", PM_ERROR_LEVEL_SYNTAX }, From e276929511dd690128de08da5f379ea7df539a0c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 11:23:16 -0400 Subject: [PATCH 008/151] [PRISM] Enable test_unexpected_fraction --- test/.excludes-prism/TestSyntax.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index 257db7f328ecc0..9402546e68103e 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -14,7 +14,6 @@ exclude(:test_numbered_parameter, "unknown") exclude(:test_optional_self_reference, "unknown") exclude(:test_syntax_error_at_newline, "unknown") -exclude(:test_unexpected_fraction, "unknown") exclude(:test_unterminated_heredoc_cr, "unknown") exclude(:test_warn_balanced, "unknown") exclude(:test_warn_unreachable, "unknown") From 5c018cddcca52c9d00c16cfad252a74750d0852e Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 14:53:52 +0200 Subject: [PATCH 009/151] [rubygems/rubygems] Remove unnecessary compatibility code https://github.com/rubygems/rubygems/commit/160a515412 --- lib/rubygems/ext/cargo_builder.rb | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb index 86a0e73f28d120..09ad1407c25966 100644 --- a/lib/rubygems/ext/cargo_builder.rb +++ b/lib/rubygems/ext/cargo_builder.rb @@ -184,6 +184,7 @@ def ruby_static? end def cargo_dylib_path(dest_path, crate_name) + so_ext = RbConfig::CONFIG["SOEXT"] prefix = so_ext == "dll" ? "" : "lib" path_parts = [dest_path] path_parts << ENV["CARGO_BUILD_TARGET"] if ENV["CARGO_BUILD_TARGET"] @@ -312,22 +313,6 @@ def write_deffile(dest_dir, crate_name) deffile_path end - # We have to basically reimplement RbConfig::CONFIG['SOEXT'] here to support - # Ruby < 2.5 - # - # @see https://github.com/ruby/ruby/blob/c87c027f18c005460746a74c07cd80ee355b16e4/configure.ac#L3185 - def so_ext - return RbConfig::CONFIG["SOEXT"] if RbConfig::CONFIG.key?("SOEXT") - - if win_target? - "dll" - elsif darwin_target? - "dylib" - else - "so" - end - end - # Corresponds to $(LIBPATH) in mkmf def mkmf_libpath ["-L", "native=#{makefile_config("libdir")}"] From 00b1553dc6d7424682bd97bb92542dbefd9ddeb2 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 17:23:36 +0200 Subject: [PATCH 010/151] [rubygems/rubygems] Remove more unnecessary compatibility code https://github.com/rubygems/rubygems/commit/00d91f141b --- test/rubygems/helper.rb | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index f97306717d1b47..b90b7f28ebaa3c 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -453,7 +453,7 @@ def teardown FileUtils.rm_rf @tempdir - restore_env + ENV.replace(@orig_env) Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE, @@ -1526,23 +1526,6 @@ def self.key_path(key_name) PUBLIC_KEY = nil PUBLIC_CERT = nil end if Gem::HAVE_OPENSSL - - private - - def restore_env - unless Gem.win_platform? - ENV.replace(@orig_env) - return - end - - # Fallback logic for Windows below to workaround - # https://bugs.ruby-lang.org/issues/16798. Can be dropped once all - # supported rubies include the fix for that. - - ENV.clear - - @orig_env.each {|k, v| ENV[k] = v } - end end # https://github.com/seattlerb/minitest/blob/13c48a03d84a2a87855a4de0c959f96800100357/lib/minitest/mock.rb#L192 From eeba1581099ea881f7102d18569432748b0ef08f Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 12:33:12 -0400 Subject: [PATCH 011/151] [PRISM] Support for compiling ractor constant writes --- prism_compile.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 4 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index f784e9d0eed138..99ebc7cf8199aa 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -301,10 +301,10 @@ parse_static_literal_string(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, { rb_encoding *encoding; - if (node->flags & PM_ENCODING_FLAGS_FORCED_BINARY_ENCODING) { + if (node->flags & PM_STRING_FLAGS_FORCED_BINARY_ENCODING) { encoding = rb_ascii8bit_encoding(); } - else if (node->flags & PM_ENCODING_FLAGS_FORCED_UTF8_ENCODING) { + else if (node->flags & PM_STRING_FLAGS_FORCED_UTF8_ENCODING) { encoding = rb_utf8_encoding(); } else { @@ -4563,7 +4563,182 @@ pm_compile_case_node_dispatch(rb_iseq_t *iseq, VALUE dispatch, const pm_node_t * return dispatch; } -/* +/** + * Return the object that will be pushed onto the stack for the given node. + */ +static VALUE +pm_compile_shareable_constant_literal(rb_iseq_t *iseq, const pm_node_t *node, const pm_scope_node_t *scope_node) +{ + switch (PM_NODE_TYPE(node)) { + case PM_TRUE_NODE: + case PM_FALSE_NODE: + case PM_NIL_NODE: + case PM_SYMBOL_NODE: + case PM_REGULAR_EXPRESSION_NODE: + case PM_SOURCE_LINE_NODE: + case PM_INTEGER_NODE: + case PM_FLOAT_NODE: + case PM_RATIONAL_NODE: + case PM_IMAGINARY_NODE: + case PM_SOURCE_ENCODING_NODE: + return pm_static_literal_value(iseq, node, scope_node); + case PM_STRING_NODE: + return parse_static_literal_string(iseq, scope_node, node, &((const pm_string_node_t *) node)->unescaped); + case PM_SOURCE_FILE_NODE: + return pm_source_file_value((const pm_source_file_node_t *) node, scope_node); + case PM_ARRAY_NODE: { + const pm_array_node_t *cast = (const pm_array_node_t *) node; + VALUE result = rb_ary_new_capa(cast->elements.size); + + for (size_t index = 0; index < cast->elements.size; index++) { + VALUE element = pm_compile_shareable_constant_literal(iseq, cast->elements.nodes[index], scope_node); + if (element == Qundef) return Qundef; + + rb_ary_push(result, element); + } + + return rb_ractor_make_shareable(result); + } + case PM_HASH_NODE: { + const pm_hash_node_t *cast = (const pm_hash_node_t *) node; + VALUE result = rb_hash_new_capa(cast->elements.size); + + for (size_t index = 0; index < cast->elements.size; index++) { + const pm_node_t *element = cast->elements.nodes[index]; + if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) return Qundef; + + const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element; + + VALUE key = pm_compile_shareable_constant_literal(iseq, assoc->key, scope_node); + if (key == Qundef) return Qundef; + + VALUE value = pm_compile_shareable_constant_literal(iseq, assoc->value, scope_node); + if (value == Qundef) return Qundef; + + rb_hash_aset(result, key, value); + } + + return rb_ractor_make_shareable(result); + } + default: + return Qundef; + } +} + +/** + * Compile the instructions for pushing the value that will be written to a + * shared constant. + */ +static void +pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_node_flags_t shareability, VALUE path, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node) +{ + VALUE literal = pm_compile_shareable_constant_literal(iseq, node, scope_node); + if (literal != Qundef) { + const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node); + PUSH_INSN1(ret, location, putobject, literal); + return; + } + + const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node); + switch (PM_NODE_TYPE(node)) { + case PM_ARRAY_NODE: { + const pm_array_node_t *cast = (const pm_array_node_t *) node; + + ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + + for (size_t index = 0; index < cast->elements.size; index++) { + pm_compile_shareable_constant_value(iseq, cast->elements.nodes[index], shareability, path, ret, scope_node); + } + + PUSH_INSN1(ret, location, newarray, INT2FIX(cast->elements.size)); + PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + return; + } + case PM_HASH_NODE: { + const pm_hash_node_t *cast = (const pm_hash_node_t *) node; + + ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + + for (size_t index = 0; index < cast->elements.size; index++) { + const pm_node_t *element = cast->elements.nodes[index]; + + if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) { + COMPILE_ERROR(ERROR_ARGS "Ractor constant writes do not support **"); + } + + const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element; + pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node); + pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node); + } + + PUSH_INSN1(ret, location, newhash, INT2FIX(cast->elements.size * 2)); + PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + return; + } + default: { + DECL_ANCHOR(value_seq); + INIT_ANCHOR(value_seq); + + pm_compile_node(iseq, node, value_seq, false, scope_node); + if (PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) { + PUSH_SEND_WITH_FLAG(value_seq, location, idUMinus, INT2FIX(0), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + + if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL) { + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PUSH_SEQ(ret, value_seq); + PUSH_INSN1(ret, location, putobject, path); + PUSH_SEND_WITH_FLAG(ret, location, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + else if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) { + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PUSH_SEQ(ret, value_seq); + PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + else if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING) { + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + PUSH_SEQ(ret, value_seq); + PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + + break; + } + } +} + +/** + * Compile a shareable constant node, which is a write to a constant within the + * context of a ractor pragma. + */ +static void +pm_compile_shareable_constant_node(rb_iseq_t *iseq, const pm_shareable_constant_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node); + + switch (PM_NODE_TYPE(node->write)) { + case PM_CONSTANT_WRITE_NODE: { + const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node->write; + ID name_id = pm_constant_id_lookup(scope_node, cast->name); + + VALUE name = ID2SYM(name_id); + VALUE path = rb_id2str(name_id); + + pm_compile_shareable_constant_value(iseq, cast->value, node->base.flags, path, ret, scope_node); + if (!popped) PUSH_INSN(ret, location, dup); + + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + PUSH_INSN1(ret, location, setconstant, name); + return; + } + default: + rb_bug("Unexpected node type for shareable constant write: %s", pm_node_type_to_str(PM_NODE_TYPE(node->write))); + return; + } +} + +/** * Compiles a prism node into instruction sequences. * * iseq - The current instruction sequence object (used for locals) @@ -8453,7 +8628,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_SHAREABLE_CONSTANT_NODE: { // A value that is being written to a constant that is being marked as // shared depending on the current lexical context. - PM_COMPILE(((const pm_shareable_constant_node_t *) node)->write); + pm_compile_shareable_constant_node(iseq, (const pm_shareable_constant_node_t *) node, ret, popped, scope_node); return; } case PM_SINGLETON_CLASS_NODE: { From 481e16d58bb278752bab009b3c25af9144364433 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 6 May 2024 13:55:16 -0400 Subject: [PATCH 012/151] [PRISM] Support for compiling ractor constant path writes --- prism_compile.c | 602 +++++++++++++++++++----------- test/.excludes-prism/TestParse.rb | 7 +- 2 files changed, 388 insertions(+), 221 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 99ebc7cf8199aa..6d7d35fd19ab6d 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -4630,7 +4630,7 @@ pm_compile_shareable_constant_literal(rb_iseq_t *iseq, const pm_node_t *node, co * shared constant. */ static void -pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_node_flags_t shareability, VALUE path, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node) +pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_flags_t shareability, VALUE path, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, bool top) { VALUE literal = pm_compile_shareable_constant_literal(iseq, node, scope_node); if (literal != Qundef) { @@ -4644,22 +4644,29 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_n case PM_ARRAY_NODE: { const pm_array_node_t *cast = (const pm_array_node_t *) node; - ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (top) { + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + } for (size_t index = 0; index < cast->elements.size; index++) { - pm_compile_shareable_constant_value(iseq, cast->elements.nodes[index], shareability, path, ret, scope_node); + pm_compile_shareable_constant_value(iseq, cast->elements.nodes[index], shareability, path, ret, scope_node, false); } PUSH_INSN1(ret, location, newarray, INT2FIX(cast->elements.size)); - PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + + if (top) { + ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); + PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + return; } case PM_HASH_NODE: { const pm_hash_node_t *cast = (const pm_hash_node_t *) node; - ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (top) { + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + } for (size_t index = 0; index < cast->elements.size; index++) { const pm_node_t *element = cast->elements.nodes[index]; @@ -4669,12 +4676,17 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_n } const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element; - pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node); - pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node); + pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node, false); + pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node, false); } PUSH_INSN1(ret, location, newhash, INT2FIX(cast->elements.size * 2)); - PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + + if (top) { + ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable"); + PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + return; } default: { @@ -4693,14 +4705,14 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_n PUSH_SEND_WITH_FLAG(ret, location, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE)); } else if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) { - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (top) PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); PUSH_SEQ(ret, value_seq); - PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + if (top) PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); } else if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING) { - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (top) PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); PUSH_SEQ(ret, value_seq); - PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + if (top) PUSH_SEND_WITH_FLAG(ret, location, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); } break; @@ -4709,33 +4721,335 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, pm_n } /** - * Compile a shareable constant node, which is a write to a constant within the - * context of a ractor pragma. + * Compile a constant write node, either in the context of a ractor pragma or + * not. */ static void -pm_compile_shareable_constant_node(rb_iseq_t *iseq, const pm_shareable_constant_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +pm_compile_constant_write_node(rb_iseq_t *iseq, const pm_constant_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) { - const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node); + const pm_line_column_t location = *node_location; + ID name_id = pm_constant_id_lookup(scope_node, node->name); - switch (PM_NODE_TYPE(node->write)) { - case PM_CONSTANT_WRITE_NODE: { - const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node->write; - ID name_id = pm_constant_id_lookup(scope_node, cast->name); + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, rb_id2str(name_id), ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } - VALUE name = ID2SYM(name_id); - VALUE path = rb_id2str(name_id); + if (!popped) PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + PUSH_INSN1(ret, location, setconstant, ID2SYM(name_id)); +} - pm_compile_shareable_constant_value(iseq, cast->value, node->base.flags, path, ret, scope_node); - if (!popped) PUSH_INSN(ret, location, dup); +/** + * Compile a constant and write node, either in the context of a ractor pragma + * or not. + */ +static void +pm_compile_constant_and_write_node(rb_iseq_t *iseq, const pm_constant_and_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - PUSH_INSN1(ret, location, setconstant, name); - return; - } - default: - rb_bug("Unexpected node type for shareable constant write: %s", pm_node_type_to_str(PM_NODE_TYPE(node->write))); - return; + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name)); + LABEL *end_label = NEW_LABEL(location.line); + + pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node); + if (!popped) PUSH_INSN(ret, location, dup); + + PUSH_INSNL(ret, location, branchunless, end_label); + if (!popped) PUSH_INSN(ret, location, pop); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, name, ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + if (!popped) PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + PUSH_INSN1(ret, location, setconstant, name); + PUSH_LABEL(ret, end_label); +} + +/** + * Compile a constant or write node, either in the context of a ractor pragma or + * not. + */ +static void +pm_compile_constant_or_write_node(rb_iseq_t *iseq, const pm_constant_or_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name)); + + LABEL *set_label = NEW_LABEL(location.line); + LABEL *end_label = NEW_LABEL(location.line); + + PUSH_INSN(ret, location, putnil); + PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST), name, Qtrue); + PUSH_INSNL(ret, location, branchunless, set_label); + + pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node); + if (!popped) PUSH_INSN(ret, location, dup); + + PUSH_INSNL(ret, location, branchif, end_label); + if (!popped) PUSH_INSN(ret, location, pop); + PUSH_LABEL(ret, set_label); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, name, ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + if (!popped) PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + PUSH_INSN1(ret, location, setconstant, name); + PUSH_LABEL(ret, end_label); +} + +/** + * Compile a constant operator write node, either in the context of a ractor + * pragma or not. + */ +static void +pm_compile_constant_operator_write_node(rb_iseq_t *iseq, const pm_constant_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name)); + ID method_id = pm_constant_id_lookup(scope_node, node->operator); + + pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, name, ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + if (!popped) PUSH_INSN(ret, location, dup); + + PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); + PUSH_INSN1(ret, location, setconstant, name); +} + +/** + * Creates a string that is used in ractor error messages to describe the + * constant path being written. + */ +static VALUE +pm_constant_path_path(const pm_constant_path_node_t *node, const pm_scope_node_t *scope_node) +{ + VALUE parts = rb_ary_new(); + rb_ary_push(parts, rb_id2str(pm_constant_id_lookup(scope_node, node->name))); + + const pm_node_t *current = node->parent; + while (current != NULL && PM_NODE_TYPE_P(current, PM_CONSTANT_PATH_NODE)) { + const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) current; + rb_ary_unshift(parts, rb_id2str(pm_constant_id_lookup(scope_node, cast->name))); + current = cast->parent; + } + + if (current == NULL) { + rb_ary_unshift(parts, rb_id2str(idNULL)); + } + else if (PM_NODE_TYPE_P(current, PM_CONSTANT_READ_NODE)) { + rb_ary_unshift(parts, rb_id2str(pm_constant_id_lookup(scope_node, ((const pm_constant_read_node_t *) current)->name))); + } + else { + rb_ary_unshift(parts, rb_str_new_cstr("...")); + } + + return rb_ary_join(parts, rb_str_new_cstr("::")); +} + +/** + * Compile a constant path write node, either in the context of a ractor pragma + * or not. + */ +static void +pm_compile_constant_path_write_node(rb_iseq_t *iseq, const pm_constant_path_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + const pm_constant_path_node_t *target = node->target; + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); + + if (target->parent) { + PM_COMPILE_NOT_POPPED((const pm_node_t *) target->parent); + } + else { + PUSH_INSN1(ret, location, putobject, rb_cObject); + } + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, pm_constant_path_path(node->target, scope_node), ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + if (!popped) { + PUSH_INSN(ret, location, swap); + PUSH_INSN1(ret, location, topn, INT2FIX(1)); + } + + PUSH_INSN(ret, location, swap); + PUSH_INSN1(ret, location, setconstant, name); +} + +/** + * Compile a constant path and write node, either in the context of a ractor + * pragma or not. + */ +static void +pm_compile_constant_path_and_write_node(rb_iseq_t *iseq, const pm_constant_path_and_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + const pm_constant_path_node_t *target = node->target; + + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); + LABEL *lfin = NEW_LABEL(location.line); + + if (target->parent) { + PM_COMPILE_NOT_POPPED(target->parent); + } + else { + PUSH_INSN1(ret, location, putobject, rb_cObject); + } + + PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putobject, Qtrue); + PUSH_INSN1(ret, location, getconstant, name); + + if (!popped) PUSH_INSN(ret, location, dup); + PUSH_INSNL(ret, location, branchunless, lfin); + + if (!popped) PUSH_INSN(ret, location, pop); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, pm_constant_path_path(node->target, scope_node), ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + if (popped) { + PUSH_INSN1(ret, location, topn, INT2FIX(1)); + } + else { + PUSH_INSN1(ret, location, dupn, INT2FIX(2)); + PUSH_INSN(ret, location, swap); + } + + PUSH_INSN1(ret, location, setconstant, name); + PUSH_LABEL(ret, lfin); + + if (!popped) PUSH_INSN(ret, location, swap); + PUSH_INSN(ret, location, pop); +} + +/** + * Compile a constant path or write node, either in the context of a ractor + * pragma or not. + */ +static void +pm_compile_constant_path_or_write_node(rb_iseq_t *iseq, const pm_constant_path_or_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + const pm_constant_path_node_t *target = node->target; + + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); + LABEL *lassign = NEW_LABEL(location.line); + LABEL *lfin = NEW_LABEL(location.line); + + if (target->parent) { + PM_COMPILE_NOT_POPPED(target->parent); + } + else { + PUSH_INSN1(ret, location, putobject, rb_cObject); + } + + PUSH_INSN(ret, location, dup); + PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST_FROM), name, Qtrue); + PUSH_INSNL(ret, location, branchunless, lassign); + + PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putobject, Qtrue); + PUSH_INSN1(ret, location, getconstant, name); + + if (!popped) PUSH_INSN(ret, location, dup); + PUSH_INSNL(ret, location, branchif, lfin); + + if (!popped) PUSH_INSN(ret, location, pop); + PUSH_LABEL(ret, lassign); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, pm_constant_path_path(node->target, scope_node), ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + if (popped) { + PUSH_INSN1(ret, location, topn, INT2FIX(1)); + } + else { + PUSH_INSN1(ret, location, dupn, INT2FIX(2)); + PUSH_INSN(ret, location, swap); + } + + PUSH_INSN1(ret, location, setconstant, name); + PUSH_LABEL(ret, lfin); + + if (!popped) PUSH_INSN(ret, location, swap); + PUSH_INSN(ret, location, pop); +} + +/** + * Compile a constant path operator write node, either in the context of a + * ractor pragma or not. + */ +static void +pm_compile_constant_path_operator_write_node(rb_iseq_t *iseq, const pm_constant_path_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node) +{ + const pm_line_column_t location = *node_location; + const pm_constant_path_node_t *target = node->target; + + ID method_id = pm_constant_id_lookup(scope_node, node->operator); + VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); + + if (target->parent) { + PM_COMPILE_NOT_POPPED(target->parent); + } + else { + PUSH_INSN1(ret, location, putobject, rb_cObject); + } + + PUSH_INSN(ret, location, dup); + PUSH_INSN1(ret, location, putobject, Qtrue); + PUSH_INSN1(ret, location, getconstant, name); + + if (shareability != 0) { + pm_compile_shareable_constant_value(iseq, node->value, shareability, pm_constant_path_path(node->target, scope_node), ret, scope_node, true); + } + else { + PM_COMPILE_NOT_POPPED(node->value); + } + + PUSH_CALL(ret, location, method_id, INT2FIX(1)); + PUSH_INSN(ret, location, swap); + + if (!popped) { + PUSH_INSN1(ret, location, topn, INT2FIX(1)); + PUSH_INSN(ret, location, swap); } + + PUSH_INSN1(ret, location, setconstant, name); } /** @@ -5826,147 +6140,28 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // Foo::Bar &&= baz // ^^^^^^^^^^^^^^^^ const pm_constant_path_and_write_node_t *cast = (const pm_constant_path_and_write_node_t *) node; - const pm_constant_path_node_t *target = cast->target; - - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); - LABEL *lfin = NEW_LABEL(location.line); - - if (target->parent) { - PM_COMPILE_NOT_POPPED(target->parent); - } - else { - PUSH_INSN1(ret, location, putobject, rb_cObject); - } - - PUSH_INSN(ret, location, dup); - PUSH_INSN1(ret, location, putobject, Qtrue); - PUSH_INSN1(ret, location, getconstant, name); - - if (!popped) PUSH_INSN(ret, location, dup); - PUSH_INSNL(ret, location, branchunless, lfin); - - if (!popped) PUSH_INSN(ret, location, pop); - PM_COMPILE_NOT_POPPED(cast->value); - - if (popped) { - PUSH_INSN1(ret, location, topn, INT2FIX(1)); - } - else { - PUSH_INSN1(ret, location, dupn, INT2FIX(2)); - PUSH_INSN(ret, location, swap); - } - - PUSH_INSN1(ret, location, setconstant, name); - PUSH_LABEL(ret, lfin); - - if (!popped) PUSH_INSN(ret, location, swap); - PUSH_INSN(ret, location, pop); - + pm_compile_constant_path_and_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_PATH_OR_WRITE_NODE: { // Foo::Bar ||= baz // ^^^^^^^^^^^^^^^^ const pm_constant_path_or_write_node_t *cast = (const pm_constant_path_or_write_node_t *) node; - const pm_constant_path_node_t *target = cast->target; - - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); - LABEL *lassign = NEW_LABEL(location.line); - LABEL *lfin = NEW_LABEL(location.line); - - if (target->parent) { - PM_COMPILE_NOT_POPPED(target->parent); - } - else { - PUSH_INSN1(ret, location, putobject, rb_cObject); - } - - PUSH_INSN(ret, location, dup); - PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST_FROM), name, Qtrue); - PUSH_INSNL(ret, location, branchunless, lassign); - - PUSH_INSN(ret, location, dup); - PUSH_INSN1(ret, location, putobject, Qtrue); - PUSH_INSN1(ret, location, getconstant, name); - - if (!popped) PUSH_INSN(ret, location, dup); - PUSH_INSNL(ret, location, branchif, lfin); - - if (!popped) PUSH_INSN(ret, location, pop); - PUSH_LABEL(ret, lassign); - PM_COMPILE_NOT_POPPED(cast->value); - - if (popped) { - PUSH_INSN1(ret, location, topn, INT2FIX(1)); - } - else { - PUSH_INSN1(ret, location, dupn, INT2FIX(2)); - PUSH_INSN(ret, location, swap); - } - - PUSH_INSN1(ret, location, setconstant, name); - PUSH_LABEL(ret, lfin); - - if (!popped) PUSH_INSN(ret, location, swap); - PUSH_INSN(ret, location, pop); - + pm_compile_constant_path_or_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: { // Foo::Bar += baz // ^^^^^^^^^^^^^^^ const pm_constant_path_operator_write_node_t *cast = (const pm_constant_path_operator_write_node_t *) node; - const pm_constant_path_node_t *target = cast->target; - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); - - if (target->parent) { - PM_COMPILE_NOT_POPPED(target->parent); - } - else { - PUSH_INSN1(ret, location, putobject, rb_cObject); - } - - PUSH_INSN(ret, location, dup); - PUSH_INSN1(ret, location, putobject, Qtrue); - PUSH_INSN1(ret, location, getconstant, name); - - PM_COMPILE_NOT_POPPED(cast->value); - PUSH_CALL(ret, location, method_id, INT2FIX(1)); - PUSH_INSN(ret, location, swap); - - if (!popped) { - PUSH_INSN1(ret, location, topn, INT2FIX(1)); - PUSH_INSN(ret, location, swap); - } - - PUSH_INSN1(ret, location, setconstant, name); + pm_compile_constant_path_operator_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_PATH_WRITE_NODE: { // Foo::Bar = 1 // ^^^^^^^^^^^^ const pm_constant_path_write_node_t *cast = (const pm_constant_path_write_node_t *) node; - const pm_constant_path_node_t *target = cast->target; - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); - - if (target->parent) { - PM_COMPILE_NOT_POPPED((const pm_node_t *) target->parent); - } - else { - PUSH_INSN1(ret, location, putobject, rb_cObject); - } - - PM_COMPILE_NOT_POPPED(cast->value); - - if (!popped) { - PUSH_INSN(ret, location, swap); - PUSH_INSN1(ret, location, topn, INT2FIX(1)); - } - - PUSH_INSN(ret, location, swap); - PUSH_INSN1(ret, location, setconstant, name); - + pm_compile_constant_path_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_READ_NODE: { @@ -5984,82 +6179,28 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, // Foo &&= bar // ^^^^^^^^^^^ const pm_constant_and_write_node_t *cast = (const pm_constant_and_write_node_t *) node; - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name)); - LABEL *end_label = NEW_LABEL(location.line); - - pm_compile_constant_read(iseq, name, &cast->name_loc, ret, scope_node); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSNL(ret, location, branchunless, end_label); - if (!popped) PUSH_INSN(ret, location, pop); - - PM_COMPILE_NOT_POPPED(cast->value); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - PUSH_INSN1(ret, location, setconstant, name); - PUSH_LABEL(ret, end_label); - + pm_compile_constant_and_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_OR_WRITE_NODE: { // Foo ||= bar // ^^^^^^^^^^^ const pm_constant_or_write_node_t *cast = (const pm_constant_or_write_node_t *) node; - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name)); - LABEL *set_label = NEW_LABEL(location.line); - LABEL *end_label = NEW_LABEL(location.line); - - PUSH_INSN(ret, location, putnil); - PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST), name, Qtrue); - PUSH_INSNL(ret, location, branchunless, set_label); - - pm_compile_constant_read(iseq, name, &cast->name_loc, ret, scope_node); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSNL(ret, location, branchif, end_label); - if (!popped) PUSH_INSN(ret, location, pop); - - PUSH_LABEL(ret, set_label); - PM_COMPILE_NOT_POPPED(cast->value); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - PUSH_INSN1(ret, location, setconstant, name); - PUSH_LABEL(ret, end_label); - + pm_compile_constant_or_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_OPERATOR_WRITE_NODE: { // Foo += bar // ^^^^^^^^^^ const pm_constant_operator_write_node_t *cast = (const pm_constant_operator_write_node_t *) node; - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name)); - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); - - pm_compile_constant_read(iseq, name, &cast->name_loc, ret, scope_node); - PM_COMPILE_NOT_POPPED(cast->value); - - PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - PUSH_INSN1(ret, location, setconstant, name); - + pm_compile_constant_operator_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_CONSTANT_WRITE_NODE: { // Foo = 1 // ^^^^^^^ const pm_constant_write_node_t *cast = (const pm_constant_write_node_t *) node; - VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name)); - - PM_COMPILE_NOT_POPPED(cast->value); - if (!popped) PUSH_INSN(ret, location, dup); - - PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - PUSH_INSN1(ret, location, setconstant, name); - + pm_compile_constant_write_node(iseq, cast, 0, &location, ret, popped, scope_node); return; } case PM_DEF_NODE: { @@ -8628,7 +8769,38 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, case PM_SHAREABLE_CONSTANT_NODE: { // A value that is being written to a constant that is being marked as // shared depending on the current lexical context. - pm_compile_shareable_constant_node(iseq, (const pm_shareable_constant_node_t *) node, ret, popped, scope_node); + const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node; + + switch (PM_NODE_TYPE(cast->write)) { + case PM_CONSTANT_WRITE_NODE: + pm_compile_constant_write_node(iseq, (const pm_constant_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_AND_WRITE_NODE: + pm_compile_constant_and_write_node(iseq, (const pm_constant_and_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_OR_WRITE_NODE: + pm_compile_constant_or_write_node(iseq, (const pm_constant_or_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_OPERATOR_WRITE_NODE: + pm_compile_constant_operator_write_node(iseq, (const pm_constant_operator_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_PATH_WRITE_NODE: + pm_compile_constant_path_write_node(iseq, (const pm_constant_path_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_PATH_AND_WRITE_NODE: + pm_compile_constant_path_and_write_node(iseq, (const pm_constant_path_and_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_PATH_OR_WRITE_NODE: + pm_compile_constant_path_or_write_node(iseq, (const pm_constant_path_or_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE: + pm_compile_constant_path_operator_write_node(iseq, (const pm_constant_path_operator_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node); + break; + default: + rb_bug("Unexpected node type for shareable constant write: %s", pm_node_type_to_str(PM_NODE_TYPE(cast->write))); + break; + } + return; } case PM_SINGLETON_CLASS_NODE: { diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 4428e5a0e6aff7..5b2fe15a6108f9 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -4,12 +4,7 @@ exclude(:test_location_of_invalid_token, "unknown") exclude(:test_percent, "unknown") exclude(:test_question, "unknown") -exclude(:test_shareable_constant_value_ignored, "unknown") -exclude(:test_shareable_constant_value_nested, "ractor support") -exclude(:test_shareable_constant_value_nonliteral, "ractor support") -exclude(:test_shareable_constant_value_simple, "ractor support") -exclude(:test_shareable_constant_value_unfrozen, "ractor support") -exclude(:test_shareable_constant_value_unshareable_literal, "ractor support") +exclude(:test_shareable_constant_value_ignored, "comment-only line warning") exclude(:test_string, "unknown") exclude(:test_truncated_source_line, "unknown") exclude(:test_unexpected_eof, "unknown") From e9356bec96deac9fbf83d45c332570b7f84381d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 02:19:14 +0000 Subject: [PATCH 013/151] Bump actions/checkout in /.github/actions/setup/directories Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/0ad4b8fadaa221de15dcec353f45205ec38ea70b...44c2b7a8a4ea60a981eaca3cf939b5f4305c123b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index a59f575c991a76..db1ae87fffefc5 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -88,7 +88,7 @@ runs: git config --global init.defaultBranch garbage - if: inputs.checkout - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: path: ${{ inputs.srcdir }} fetch-depth: ${{ inputs.fetch-depth }} From 7c8903d014e12bd80a35804affa029028c9f48cc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 03:01:56 +0000 Subject: [PATCH 014/151] Bump actions/checkout from 4.1.4 to 4.1.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/0ad4b8fadaa221de15dcec353f45205ec38ea70b...44c2b7a8a4ea60a981eaca3cf939b5f4305c123b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/annocheck.yml | 2 +- .github/workflows/baseruby.yml | 2 +- .github/workflows/bundled_gems.yml | 2 +- .github/workflows/check_dependencies.yml | 2 +- .github/workflows/check_misc.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/compilers.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/prism.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/rjit.yml | 2 +- .github/workflows/scorecards.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- .github/workflows/wasm.yml | 2 +- .github/workflows/windows.yml | 2 +- .github/workflows/yjit-macos.yml | 4 ++-- .github/workflows/yjit-ubuntu.yml | 6 +++--- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index 35e74d64d8599c..c6b5ff1c0433bb 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -63,7 +63,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 12f98d4a1ee84f..7aaf6b8f447ff7 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -56,7 +56,7 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler: none - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: ./.github/actions/setup/ubuntu diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index fcc005239be6a0..c509967c351845 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index fd7e2f58e5a373..4bbcb73cb51e10 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -45,7 +45,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index 48434a47a942a2..c9a182c57b163d 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index c7d0def7aeaf22..8b8a4565da121f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - name: Install libraries if: ${{ contains(matrix.os, 'macos') }} diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 5e5eb69b6f1c2f..5f6cd59481c075 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -233,7 +233,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 54e30129e427fa..71c314021fc6c3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -52,7 +52,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index ad393410599af2..df6b2bd312da1c 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -97,7 +97,7 @@ jobs: $result working-directory: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml index 600bc8fc55dd51..7d4cdcb47ac147 100644 --- a/.github/workflows/prism.yml +++ b/.github/workflows/prism.yml @@ -55,7 +55,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index 1657721a65369d..168794ddbbddc9 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -51,7 +51,7 @@ jobs: with: ruby-version: '3.1' - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/rjit.yml b/.github/workflows/rjit.yml index 7a5e6cf7c0f71b..f1cd70afa4210f 100644 --- a/.github/workflows/rjit.yml +++ b/.github/workflows/rjit.yml @@ -55,7 +55,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 00a0638e967cf5..7f3a24b05fad28 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -32,7 +32,7 @@ jobs: steps: - name: 'Checkout code' - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: persist-credentials: false diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index bb48435c7ff530..2dc4a7b39a6392 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -45,7 +45,7 @@ jobs: - ruby-3.3 steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0 with: diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index bd1a7056bb2fd3..70ee4a2e6171ce 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -58,7 +58,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 0bd96bf9df306c..b77f4a152a5b47 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -61,7 +61,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d5b486355aeab7..8fe00aca1c6fda 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -123,7 +123,7 @@ jobs: Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH shell: pwsh - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index 45a6a0578f2f4a..e04306e46aa30a 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -37,7 +37,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - run: RUST_BACKTRACE=1 cargo test working-directory: yjit @@ -81,7 +81,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 146027bcf16148..b040f6d78b103e 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -36,7 +36,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 # For now we can't run cargo test --offline because it complains about the # capstone dependency, even though the dependency is optional @@ -68,7 +68,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 # Check that we don't have linting errors in release mode, too - run: cargo clippy --all-targets --all-features @@ -127,7 +127,7 @@ jobs: )}} steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 with: sparse-checkout-cone-mode: false sparse-checkout: /.github From 80adf6a18c653e25a0448110e6978a9d0764eba7 Mon Sep 17 00:00:00 2001 From: Yuta Saito Date: Sat, 4 May 2024 20:41:16 +0000 Subject: [PATCH 015/151] [rubygems/rubygems] Accept WASI as an OS name in Gem::Platform https://github.com/rubygems/rubygems/commit/1209d3c6b0 --- lib/rubygems/platform.rb | 1 + test/rubygems/test_gem_platform.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb index 48b7344aee5d77..d54ad12880d20d 100644 --- a/lib/rubygems/platform.rb +++ b/lib/rubygems/platform.rb @@ -134,6 +134,7 @@ def initialize(arch) when /netbsdelf/ then ["netbsdelf", nil] when /openbsd(\d+\.\d+)?/ then ["openbsd", $1] when /solaris(\d+\.\d+)?/ then ["solaris", $1] + when /wasi/ then ["wasi", nil] # test when /^(\w+_platform)(\d+)?/ then [$1, $2] else ["unknown", nil] diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb index e4bf882317db35..00e48498c603d4 100644 --- a/test/rubygems/test_gem_platform.rb +++ b/test/rubygems/test_gem_platform.rb @@ -145,6 +145,9 @@ def test_initialize "x86_64-openbsd3.9" => ["x86_64", "openbsd", "3.9"], "x86_64-openbsd4.0" => ["x86_64", "openbsd", "4.0"], "x86_64-openbsd" => ["x86_64", "openbsd", nil], + "wasm32-wasi" => ["wasm32", "wasi", nil], + "wasm32-wasip1" => ["wasm32", "wasi", nil], + "wasm32-wasip2" => ["wasm32", "wasi", nil], } test_cases.each do |arch, expected| From e1e6b4972fa33feb260bf93ba087d47034082867 Mon Sep 17 00:00:00 2001 From: git Date: Tue, 7 May 2024 06:59:36 +0000 Subject: [PATCH 016/151] Update bundled gems list as of 2024-05-07 --- NEWS.md | 2 +- gems/bundled_gems | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8f3c050235fd6f..fdbd1fdb48add3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -73,7 +73,7 @@ The following bundled gems are promoted from default gems. * mutex_m 0.2.0 * getoptlong 0.2.1 * base64 0.2.0 -* bigdecimal 3.1.7 +* bigdecimal 3.1.8 * observer 0.1.2 * abbrev 0.1.2 * resolv-replace 0.1.1 diff --git a/gems/bundled_gems b/gems/bundled_gems index ad979c1c5c4b1e..4e7e23bacefe8e 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -25,7 +25,7 @@ racc 1.7.3 https://github.com/ruby/racc mutex_m 0.2.0 https://github.com/ruby/mutex_m getoptlong 0.2.1 https://github.com/ruby/getoptlong base64 0.2.0 https://github.com/ruby/base64 -bigdecimal 3.1.7 https://github.com/ruby/bigdecimal +bigdecimal 3.1.8 https://github.com/ruby/bigdecimal observer 0.1.2 https://github.com/ruby/observer abbrev 0.1.2 https://github.com/ruby/abbrev resolv-replace 0.1.1 https://github.com/ruby/resolv-replace From eb8efa42f0904281345a6622fff8209a464d39e9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 09:53:17 -0400 Subject: [PATCH 017/151] [ruby/prism] shareable_constant_value line warnings https://github.com/ruby/prism/commit/8c984b6922 --- prism/config.yml | 1 + prism/prism.c | 7 ++++++- prism/templates/src/diagnostic.c.erb | 1 + test/prism/warnings_test.rb | 9 +++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/prism/config.yml b/prism/config.yml index 4e85a6f34df6cb..9268effce7c397 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -290,6 +290,7 @@ warnings: - KEYWORD_EOL - LITERAL_IN_CONDITION_DEFAULT - LITERAL_IN_CONDITION_VERBOSE + - SHAREABLE_CONSTANT_VALUE_LINE - SHEBANG_CARRIAGE_RETURN - UNEXPECTED_CARRIAGE_RETURN - UNREACHABLE_STATEMENT diff --git a/prism/prism.c b/prism/prism.c index 44b4dc5ae53138..12bbf1b59787cd 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8394,7 +8394,12 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) { // If we have hit a ractor pragma, attempt to lex that. uint32_t value_length = (uint32_t) (value_end - value_start); if (key_length == 24 && pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) { - if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) { + const uint8_t *cursor = parser->current.start; + while ((cursor > parser->start) && ((cursor[-1] == ' ') || (cursor[-1] == '\t'))) cursor--; + + if (!((cursor == parser->start) || (cursor[-1] == '\n'))) { + pm_parser_warn_token(parser, &parser->current, PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE); + } else if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) { pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE); } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) { pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL); diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 04b8af858b1a64..ba17cf830667b1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -373,6 +373,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_WARN_KEYWORD_EOL] = { "`%.*s` at the end of line without an expression", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_LITERAL_IN_CONDITION_DEFAULT] = { "%sliteral in %s", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_LITERAL_IN_CONDITION_VERBOSE] = { "%sliteral in %s", PM_WARNING_LEVEL_VERBOSE }, + [PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE] = { "'shareable_constant_value' is ignored unless in comment-only line", PM_WARNING_LEVEL_VERBOSE }, [PM_WARN_SHEBANG_CARRIAGE_RETURN] = { "shebang line ending with \\r may cause problems", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_UNEXPECTED_CARRIAGE_RETURN] = { "encountered \\r in middle of line, treated as a mere space", PM_WARNING_LEVEL_DEFAULT }, [PM_WARN_UNREACHABLE_STATEMENT] = { "statement not reached", PM_WARNING_LEVEL_VERBOSE }, diff --git a/test/prism/warnings_test.rb b/test/prism/warnings_test.rb index d01db01a0e0381..b138a3cb431921 100644 --- a/test/prism/warnings_test.rb +++ b/test/prism/warnings_test.rb @@ -64,6 +64,15 @@ def test_keyword_eol assert_warning("if true\nelsif\nfalse; end", "end of line") end + def test_shareable_constant_value + assert_warning("foo # shareable_constant_value: none", "ignored") + assert_warning("\v # shareable_constant_value: none", "ignored") + + refute_warning("# shareable_constant_value: none") + refute_warning(" # shareable_constant_value: none") + refute_warning("\t\t# shareable_constant_value: none") + end + def test_string_in_predicate assert_warning("if 'foo'; end", "string") assert_warning("if \"\#{foo}\"; end", "string") From 8cc733dff7b831555f9250153a477bdff3354eae Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 12:08:33 -0400 Subject: [PATCH 018/151] [ruby/prism] Add error for invalid implicit local writes https://github.com/ruby/prism/commit/ab21882561 --- prism/prism.c | 78 +++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 12bbf1b59787cd..f5aa51ea01c0df 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -1758,7 +1758,7 @@ char_is_identifier_utf8(const uint8_t *b, const uint8_t *end) { * it's important that it be as fast as possible. */ static inline size_t -char_is_identifier(pm_parser_t *parser, const uint8_t *b) { +char_is_identifier(const pm_parser_t *parser, const uint8_t *b) { if (parser->encoding_changed) { size_t width; if ((width = parser->encoding->alnum_char(b, parser->end - b)) != 0) { @@ -16125,6 +16125,33 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) return (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator); } +/** + * Check that the slice of the source given by the bounds parameters constitutes + * a valid local variable name. + */ +static bool +pm_slice_is_valid_local(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end) { + ptrdiff_t length = end - start; + if (length == 0) return false; + + // First ensure that it starts with a valid identifier starting character. + size_t width = char_is_identifier_start(parser, start); + if (width == 0) return false; + + // Next, ensure that it's not an uppercase character. + if (parser->encoding_changed) { + if (parser->encoding->isupper_char(start, length)) return false; + } else { + if (pm_encoding_utf_8_isupper_char(start, length)) return false; + } + + // Next, iterate through all of the bytes of the string to ensure that they + // are all valid identifier characters. + const uint8_t *cursor = start + width; + while ((cursor < end) && (width = char_is_identifier(parser, cursor))) cursor += width; + return cursor == end; +} + /** * Create an implicit node for the value of a hash pattern that has omitted the * value. This will use an implicit local variable target. @@ -16132,14 +16159,18 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) static pm_node_t * parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_symbol_node_t *key) { const pm_location_t *value_loc = &((pm_symbol_node_t *) key)->value_loc; - pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, value_loc->start, value_loc->end); + pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, value_loc->start, value_loc->end); int depth = -1; - if (value_loc->end[-1] == '!' || value_loc->end[-1] == '?') { - pm_parser_err(parser, key->base.location.start, key->base.location.end, PM_ERR_PATTERN_HASH_KEY_LOCALS); - PM_PARSER_ERR_LOCATION_FORMAT(parser, value_loc, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE, (int) (value_loc->end - value_loc->start), (const char *) value_loc->start); - } else { + + if (pm_slice_is_valid_local(parser, value_loc->start, value_loc->end)) { depth = pm_parser_local_depth_constant_id(parser, constant_id); + } else { + pm_parser_err(parser, key->base.location.start, key->base.location.end, PM_ERR_PATTERN_HASH_KEY_LOCALS); + + if ((value_loc->end > value_loc->start) && ((value_loc->end[-1] == '!') || (value_loc->end[-1] == '?'))) { + PM_PARSER_ERR_LOCATION_FORMAT(parser, value_loc, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE, (int) (value_loc->end - value_loc->start), (const char *) value_loc->start); + } } if (depth == -1) { @@ -19770,39 +19801,6 @@ parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const } } -/** - * Returns true if the name of the capture group is a valid local variable that - * can be written to. - */ -static bool -parse_regular_expression_named_capture(pm_parser_t *parser, const uint8_t *source, size_t length) { - if (length == 0) { - return false; - } - - // First ensure that it starts with a valid identifier starting character. - size_t width = char_is_identifier_start(parser, source); - if (!width) { - return false; - } - - // Next, ensure that it's not an uppercase character. - if (parser->encoding_changed) { - if (parser->encoding->isupper_char(source, (ptrdiff_t) length)) return false; - } else { - if (pm_encoding_utf_8_isupper_char(source, (ptrdiff_t) length)) return false; - } - - // Next, iterate through all of the bytes of the string to ensure that they - // are all valid identifier characters. - const uint8_t *cursor = source + width; - while (cursor < source + length && (width = char_is_identifier(parser, cursor))) { - cursor += width; - } - - return cursor == source + length; -} - /** * Potentially change a =~ with a regular expression with named captures into a * match write node. @@ -19829,7 +19827,7 @@ parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t * // If the name of the capture group isn't a valid identifier, we do // not add it to the local table. - if (!parse_regular_expression_named_capture(parser, source, length)) continue; + if (!pm_slice_is_valid_local(parser, source, source + length)) continue; if (content->type == PM_STRING_SHARED) { // If the unescaped string is a slice of the source, then we can From 8ec1c416f75ff20ccf71c08c51f91bdd42f226a8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 12:15:44 -0400 Subject: [PATCH 019/151] [ruby/prism] Specific error message for symbol literal with interpolation in hash patterns https://github.com/ruby/prism/commit/31f0201bae --- prism/config.yml | 1 + prism/prism.c | 3 ++- prism/templates/src/diagnostic.c.erb | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 9268effce7c397..1325fc79903a8f 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -215,6 +215,7 @@ errors: - PATTERN_EXPRESSION_AFTER_REST - PATTERN_HASH_KEY - PATTERN_HASH_KEY_DUPLICATE + - PATTERN_HASH_KEY_INTERPOLATED - PATTERN_HASH_KEY_LABEL - PATTERN_HASH_KEY_LOCALS - PATTERN_IDENT_AFTER_HROCKET diff --git a/prism/prism.c b/prism/prism.c index f5aa51ea01c0df..7d863aadaf2467 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -16240,7 +16240,8 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node // If we get anything else, then this is an error. For this we'll // create a missing node for the value and create an assoc node for // the first node in the list. - pm_parser_err_node(parser, first_node, PM_ERR_PATTERN_HASH_KEY_LABEL); + pm_diagnostic_id_t diag_id = PM_NODE_TYPE_P(first_node, PM_INTERPOLATED_SYMBOL_NODE) ? PM_ERR_PATTERN_HASH_KEY_INTERPOLATED : PM_ERR_PATTERN_HASH_KEY_LABEL; + pm_parser_err_node(parser, first_node, diag_id); pm_token_t operator = not_provided(parser); pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, first_node->location.start, first_node->location.end); diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index ba17cf830667b1..fcebdc5c382ee1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -298,7 +298,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, // TODO // THIS // AND // ABOVE // IS WEIRD + [PM_ERR_PATTERN_HASH_KEY_INTERPOLATED] = { "symbol literal with interpolation is not allowed", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_LOCALS] = { "key must be valid as local variables", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_IDENT_AFTER_HROCKET] = { "expected an identifier after the `=>` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_LABEL_AFTER_COMMA] = { "expected a label after the `,` in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, From ef3803ed4028810f9088019f0db1a366370ab53a Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sun, 21 Apr 2024 18:51:25 -0700 Subject: [PATCH 020/151] Ignore the result of pthread_kill in ubf_wakeup_thread After an upgrade to Ruby 3.3.0, I experienced reproducible production crashes of the form: [BUG] pthread_kill: No such process (ESRCH) This is the only pthread_kill call in Ruby. The result of pthread_kill was previously ignored in Ruby 3.2 and below. Checking the result was added in be1bbd5b7d40ad863ab35097765d3754726bbd54 (MaNy). I have not yet been able to create a minimal self-contained example, but it should be safe to remove the checks. --- thread_pthread.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/thread_pthread.c b/thread_pthread.c index 82b5e362ccc0eb..b9421559f2ee83 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -2569,10 +2569,7 @@ ubf_wakeup_thread(rb_thread_t *th) { RUBY_DEBUG_LOG("th:%u thread_id:%p", rb_th_serial(th), (void *)th->nt->thread_id); - int r = pthread_kill(th->nt->thread_id, SIGVTALRM); - if (r != 0) { - rb_bug_errno("pthread_kill", r); - } + pthread_kill(th->nt->thread_id, SIGVTALRM); } static void From 5d44846815f874279672e05d7bf7037e939e471c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 13:02:25 -0400 Subject: [PATCH 021/151] [ruby/prism] Disallow implicit hash in array pattern https://github.com/ruby/prism/commit/bdd509c6ac --- prism/config.yml | 2 ++ prism/prism.c | 52 +++++++++++++++++++--------- prism/templates/src/diagnostic.c.erb | 2 ++ 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index 1325fc79903a8f..025777305154a3 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -98,6 +98,7 @@ errors: - EXPECT_EXPRESSION_AFTER_SPLAT_HASH - EXPECT_EXPRESSION_AFTER_STAR - EXPECT_IDENT_REQ_PARAMETER + - EXPECT_IN_DELIMITER - EXPECT_LPAREN_REQ_PARAMETER - EXPECT_MESSAGE - EXPECT_RBRACKET @@ -213,6 +214,7 @@ errors: - PATTERN_EXPRESSION_AFTER_PIPE - PATTERN_EXPRESSION_AFTER_RANGE - PATTERN_EXPRESSION_AFTER_REST + - PATTERN_HASH_IMPLICIT - PATTERN_HASH_KEY - PATTERN_HASH_KEY_DUPLICATE - PATTERN_HASH_KEY_INTERPOLATED diff --git a/prism/prism.c b/prism/prism.c index 7d863aadaf2467..21e04da7bece10 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -15916,8 +15916,12 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w nodes->size = write_index; } +#define PM_PARSE_PATTERN_SINGLE 0 +#define PM_PARSE_PATTERN_TOP 1 +#define PM_PARSE_PATTERN_MULTI 2 + static pm_node_t * -parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pattern, pm_diagnostic_id_t diag_id); +parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id); /** * Add the newly created local to the list of captures for this pattern matching @@ -15965,7 +15969,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures accept1(parser, PM_TOKEN_NEWLINE); if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) { - inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); + inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET); } @@ -15977,7 +15981,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures accept1(parser, PM_TOKEN_NEWLINE); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { - inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); + inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); } @@ -16225,7 +16229,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node } else { // Here we have a value for the first assoc in the list, so // we will parse it now. - value = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); } pm_token_t operator = not_provided(parser); @@ -16278,7 +16282,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key); } else { - value = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); + value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY); } pm_token_t operator = not_provided(parser); @@ -16335,7 +16339,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm // Otherwise, we'll parse the inner pattern, then deal with it depending // on the type it returns. - pm_node_t *inner = parse_pattern(parser, captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); + pm_node_t *inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET); @@ -16608,7 +16612,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p pm_token_t opening = parser->current; parser_lex(parser); - pm_node_t *body = parse_pattern(parser, captures, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); + pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN); accept1(parser, PM_TOKEN_NEWLINE); expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN); pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous); @@ -16667,7 +16671,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p * Parse a pattern matching expression. */ static pm_node_t * -parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pattern, pm_diagnostic_id_t diag_id) { +parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id) { pm_node_t *node = NULL; bool leading_rest = false; @@ -16677,14 +16681,26 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pat case PM_TOKEN_LABEL: { parser_lex(parser); pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous); - return (pm_node_t *) parse_pattern_hash(parser, captures, key); + node = (pm_node_t *) parse_pattern_hash(parser, captures, key); + + if (!(flags & PM_PARSE_PATTERN_TOP)) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT); + } + + return node; } case PM_TOKEN_USTAR_STAR: { node = parse_pattern_keyword_rest(parser, captures); - return (pm_node_t *) parse_pattern_hash(parser, captures, node); + node = (pm_node_t *) parse_pattern_hash(parser, captures, node); + + if (!(flags & PM_PARSE_PATTERN_TOP)) { + pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT); + } + + return node; } case PM_TOKEN_USTAR: { - if (top_pattern) { + if (flags & (PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI)) { parser_lex(parser); node = (pm_node_t *) parse_pattern_rest(parser, captures); leading_rest = true; @@ -16703,7 +16719,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, bool top_pat return (pm_node_t *) parse_pattern_hash(parser, captures, node); } - if (top_pattern && match1(parser, PM_TOKEN_COMMA)) { + if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) { // If we have a comma, then we are now parsing either an array pattern or a // find pattern. We need to parse all of the patterns, put them into a big // list, and then determine which type of node we have. @@ -17989,7 +18005,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b pm_token_t in_keyword = parser->previous; pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -18018,7 +18034,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b then_keyword = not_provided(parser); } } else { - expect1(parser, PM_TOKEN_KEYWORD_THEN, PM_ERR_EXPECT_WHEN_DELIMITER); + expect1(parser, PM_TOKEN_KEYWORD_THEN, PM_ERR_EXPECT_IN_DELIMITER); then_keyword = parser->previous; } @@ -20668,7 +20684,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -20685,7 +20701,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t parser_lex(parser); pm_constant_id_list_t captures = { 0 }; - pm_node_t *pattern = parse_pattern(parser, &captures, true, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET); + pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET); parser->pattern_matching_newlines = previous_pattern_matching_newlines; pm_constant_id_list_free(&captures); @@ -20698,6 +20714,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t } } +#undef PM_PARSE_PATTERN_SINGLE +#undef PM_PARSE_PATTERN_TOP +#undef PM_PARSE_PATTERN_MULTI + /** * Parse an expression at the given point of the parser using the given binding * power to parse subsequent chains. If this function finds a syntax error, it diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index fcebdc5c382ee1..32b4e32a3e5592 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -182,6 +182,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_IN_DELIMITER] = { "expected a delimiter after the patterns of an `in` clause", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_MESSAGE] = { "unexpected %s; expecting a message to send to the receiver", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_SYNTAX }, @@ -296,6 +297,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_INTERPOLATED] = { "symbol literal with interpolation is not allowed", PM_ERROR_LEVEL_SYNTAX }, From dcbe0edb836aa3be62b7b64f3c7f27e7ef6885fb Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 13:15:01 -0400 Subject: [PATCH 022/151] [ruby/prism] Better error message for contents of hash pattern https://github.com/ruby/prism/commit/60dbf60f48 --- prism/prism.c | 4 ++-- prism/templates/src/diagnostic.c.erb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 21e04da7bece10..4c685822ba88bf 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -16406,11 +16406,11 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm first_node = parse_pattern_keyword_rest(parser, captures); break; case PM_TOKEN_STRING_BEGIN: - first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY); + first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY_LABEL); break; default: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type)); parser_lex(parser); - pm_parser_err_previous(parser, PM_ERR_PATTERN_HASH_KEY); first_node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end); break; diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 32b4e32a3e5592..5536b7b922e1fd 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -298,7 +298,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_PATTERN_HASH_KEY] = { "expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_INTERPOLATED] = { "symbol literal with interpolation is not allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PATTERN_HASH_KEY_LABEL] = { "expected a label as the key in the hash pattern", PM_ERROR_LEVEL_SYNTAX }, From 21b94ae0d16d2d78035a081f0bcae06402e2c622 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 14:02:56 -0400 Subject: [PATCH 023/151] [ruby/prism] Extend error message for unterminated HEREDOC https://github.com/ruby/prism/commit/c1b07ec11b --- prism/templates/src/diagnostic.c.erb | 2 +- test/prism/errors_test.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 5536b7b922e1fd..9406436c2b238b 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -212,7 +212,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HEREDOC_IDENTIFIER] = { "unterminated here document identifier", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_HEREDOC_TERM] = { "unterminated heredoc; can't find string \"%.*s\"", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_HEREDOC_TERM] = { "unterminated heredoc; can't find string \"%.*s\" anywhere before EOF", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3] = { "`%.*s' is not allowed as a class variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_VARIABLE_CLASS] = { "'%.*s' is not allowed as a class variable name", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 280bf63a24b123..db4d2af5e1c15b 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -1241,7 +1241,7 @@ def test_content_after_unterminated_heredoc expected = CallNode(0, receiver, Location(), :foo, Location(), nil, nil, nil, nil) assert_errors expected, "<<~FOO.foo\n", [ - ["unterminated heredoc; can't find string \"FOO\"", 3..6] + ["unterminated heredoc; can't find string \"FOO\" anywhere before EOF", 3..6] ] end From 2bfc48755e7fc39e1ee33181a4bd6b72aa27de48 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 13:25:32 -0400 Subject: [PATCH 024/151] [PRISM] Enable more passing tests --- test/.excludes-prism/TestParse.rb | 1 - test/.excludes-prism/TestPatternMatching.rb | 2 -- test/.excludes-prism/TestRubyLiteral.rb | 2 -- 3 files changed, 5 deletions(-) delete mode 100644 test/.excludes-prism/TestPatternMatching.rb diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 5b2fe15a6108f9..0afe3c13129d3d 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -4,7 +4,6 @@ exclude(:test_location_of_invalid_token, "unknown") exclude(:test_percent, "unknown") exclude(:test_question, "unknown") -exclude(:test_shareable_constant_value_ignored, "comment-only line warning") exclude(:test_string, "unknown") exclude(:test_truncated_source_line, "unknown") exclude(:test_unexpected_eof, "unknown") diff --git a/test/.excludes-prism/TestPatternMatching.rb b/test/.excludes-prism/TestPatternMatching.rb deleted file mode 100644 index cfd0c6bed97058..00000000000000 --- a/test/.excludes-prism/TestPatternMatching.rb +++ /dev/null @@ -1,2 +0,0 @@ -exclude(:test_hash_pattern, "useless literal warning missing") -exclude(:test_invalid_syntax, "[a:] is disallowed") diff --git a/test/.excludes-prism/TestRubyLiteral.rb b/test/.excludes-prism/TestRubyLiteral.rb index 926f0c5a5e6d6c..0305bc211773d0 100644 --- a/test/.excludes-prism/TestRubyLiteral.rb +++ b/test/.excludes-prism/TestRubyLiteral.rb @@ -1,5 +1,3 @@ -exclude(:test_debug_frozen_string_in_array_literal, "unknown") -exclude(:test_debug_frozen_string, "unknown") exclude(:test_dregexp, "https://github.com/ruby/prism/issues/2664") exclude(:test_hash_value_omission, "unknown") exclude(:test_string, "https://github.com/ruby/prism/issues/2331") From b4b39a619984bbb3c96406a1eb4dfb477168a1cd Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 13:31:51 -0400 Subject: [PATCH 025/151] [PRISM] Enable test_methoddef_endless_command --- test/ruby/test_syntax.rb | 4 ++-- tool/lib/test/unit/assertions.rb | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 44162f06cbdfee..8bdac2ebd1cb08 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1755,8 +1755,8 @@ def test_methoddef_endless_command assert_equal("instance ok", k.new.rescued("ok")) # Current technical limitation: cannot prepend "private" or something for command endless def - error = /syntax error, unexpected string literal/ - error2 = /syntax error, unexpected local variable or method/ + error = /(syntax error,|\^~*) unexpected string literal/ + error2 = /(syntax error,|\^~*) unexpected local variable or method/ assert_syntax_error('private def foo = puts "Hello"', error) assert_syntax_error('private def foo() = puts "Hello"', error) assert_syntax_error('private def foo(x) = puts x', error2) diff --git a/tool/lib/test/unit/assertions.rb b/tool/lib/test/unit/assertions.rb index b4f1dbc1765f79..aad422f7e7aa33 100644 --- a/tool/lib/test/unit/assertions.rb +++ b/tool/lib/test/unit/assertions.rb @@ -768,7 +768,14 @@ def assert_syntax_error(code, error, *args, **opt) e = assert_raise(SyntaxError, mesg) do syntax_check(src, fname, line) end - assert_match(error, e.message, mesg) + + # Prism adds ANSI escape sequences to syntax error messages to + # colorize and format them. We strip them out here to make them easier + # to match against in tests. + message = e.message + message.gsub!(/\e\[.*?m/, "") + + assert_match(error, message, mesg) e end end From aabe718e6483eb572566878320a0d83f430d1cbc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 8 May 2024 17:24:36 +0900 Subject: [PATCH 026/151] Show the caller location of assertion methods Not only defined in `Test::Unit` or `CoreAssertions`, also show the caller location of assertion methods defined in the current class or ancestors. --- tool/lib/test/unit.rb | 30 +++++++++++++++++++--------- tool/test/testunit/test_assertion.rb | 13 ++++++++++++ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/tool/lib/test/unit.rb b/tool/lib/test/unit.rb index d758b5fb026fa1..2b0856b8227ebe 100644 --- a/tool/lib/test/unit.rb +++ b/tool/lib/test/unit.rb @@ -37,6 +37,26 @@ class AssertionFailedError < Exception; end class PendedError < AssertionFailedError; end + class << self + ## + # Extract the location where the last assertion method was + # called. Returns "" if _e_ does not have backtrace, or + # an empty string if no assertion method location was found. + + def location e + last_before_assertion = nil + + return '' unless e&.backtrace # SystemStackError can return nil. + + e.backtrace.reverse_each do |s| + break if s =~ /:in \W(?:.*\#)?(?:assert|refute|flunk|pass|fail|raise|must|wont)/ + last_before_assertion = s + end + return "" unless last_before_assertion + /:in / =~ last_before_assertion ? $` : last_before_assertion + end + end + module Order class NoSort def initialize(seed) @@ -1778,15 +1798,7 @@ def record suite, method, assertions, time, error, source_location = nil end def location e # :nodoc: - last_before_assertion = "" - - return '' unless e&.backtrace # SystemStackError can return nil. - - e.backtrace.reverse_each do |s| - break if s =~ /in .(?:Test::Unit::(?:Core)?Assertions#)?(assert|refute|flunk|pass|fail|raise|must|wont)/ - last_before_assertion = s - end - last_before_assertion.sub(/:in .*$/, '') + Test::Unit.location e end ## diff --git a/tool/test/testunit/test_assertion.rb b/tool/test/testunit/test_assertion.rb index 709b4955729643..1e19c102b8ef90 100644 --- a/tool/test/testunit/test_assertion.rb +++ b/tool/test/testunit/test_assertion.rb @@ -50,4 +50,17 @@ def assert_not_pattern_list(pattern_list, actual, message=nil) assert_pattern_list(pattern_list, actual, message) end end + + def test_caller_bactrace_location + begin + line = __LINE__; assert_fail_for_backtrace_location + rescue Test::Unit::AssertionFailedError => e + end + location = Test::Unit::Runner.new.location(e) + assert_equal "#{__FILE__}:#{line}", location + end + + def assert_fail_for_backtrace_location + assert false + end end From 841b45a4421a7f103b0312f84c14ece522833617 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 5 May 2024 00:22:30 -0700 Subject: [PATCH 027/151] [ruby/openssl] Add to_text for PKCS7 and Timestamp::Response https://github.com/ruby/openssl/commit/71cd1e3f5c --- ext/openssl/ossl_pkcs7.c | 20 +++++++++++++ ext/openssl/ossl_ts.c | 60 ++++++++++++++++++++++++++++++++++++++ test/openssl/test_pkcs7.rb | 6 ++++ test/openssl/test_ts.rb | 2 ++ 4 files changed, 88 insertions(+) diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index aeeb4bf5f40657..446df4c075d6d9 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -847,6 +847,25 @@ ossl_pkcs7_to_der(VALUE self) return str; } +static VALUE +ossl_pkcs7_to_text(VALUE self) +{ + PKCS7 *pkcs7; + BIO *out; + VALUE str; + + GetPKCS7(self, pkcs7); + if(!(out = BIO_new(BIO_s_mem()))) + ossl_raise(ePKCS7Error, NULL); + if(!PKCS7_print_ctx(out, pkcs7, 0, NULL)) { + BIO_free(out); + ossl_raise(ePKCS7Error, NULL); + } + str = ossl_membio2str(out); + + return str; +} + static VALUE ossl_pkcs7_to_pem(VALUE self) { @@ -1056,6 +1075,7 @@ Init_ossl_pkcs7(void) rb_define_method(cPKCS7, "to_pem", ossl_pkcs7_to_pem, 0); rb_define_alias(cPKCS7, "to_s", "to_pem"); rb_define_method(cPKCS7, "to_der", ossl_pkcs7_to_der, 0); + rb_define_method(cPKCS7, "to_text", ossl_pkcs7_to_text, 0); cPKCS7Signer = rb_define_class_under(cPKCS7, "SignerInfo", rb_cObject); rb_define_const(cPKCS7, "Signer", cPKCS7Signer); diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c index f698bdc7ffb048..b18a86aad9a0fc 100644 --- a/ext/openssl/ossl_ts.c +++ b/ext/openssl/ossl_ts.c @@ -503,6 +503,25 @@ ossl_ts_req_to_der(VALUE self) return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ); } +static VALUE +ossl_ts_req_to_text(VALUE self) +{ + TS_REQ *req; + BIO *out; + + GetTSRequest(self, req); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_REQ_print_bio(out, req)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + static VALUE ossl_ts_resp_alloc(VALUE klass) { @@ -757,6 +776,25 @@ ossl_ts_resp_to_der(VALUE self) return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); } +static VALUE +ossl_ts_resp_to_text(VALUE self) +{ + TS_RESP *resp; + BIO *out; + + GetTSResponse(self, resp); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_RESP_print_bio(out, resp)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + /* * Verifies a timestamp token by checking the signature, validating the * certificate chain implied by tsa_certificate and by checking conformance to @@ -1073,6 +1111,25 @@ ossl_ts_token_info_to_der(VALUE self) return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO); } +static VALUE +ossl_ts_token_info_to_text(VALUE self) +{ + TS_TST_INFO *info; + BIO *out; + + GetTSTokenInfo(self, info); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_TST_INFO_print_bio(out, info)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + static ASN1_INTEGER * ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data) { @@ -1356,6 +1413,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0); rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0); rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0); + rb_define_method(cTimestampResponse, "to_text", ossl_ts_resp_to_text, 0); rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1); /* Document-class: OpenSSL::Timestamp::TokenInfo @@ -1374,6 +1432,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0); rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0); rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0); + rb_define_method(cTimestampTokenInfo, "to_text", ossl_ts_token_info_to_text, 0); /* Document-class: OpenSSL::Timestamp::Request * Allows to create timestamp requests or parse existing ones. A Request is @@ -1399,6 +1458,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1); rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0); rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0); + rb_define_method(cTimestampRequest, "to_text", ossl_ts_req_to_text, 0); /* * Indicates a successful response. Equal to +0+. diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb index 96f3f1f6becfe5..c049ed444afa28 100644 --- a/test/openssl/test_pkcs7.rb +++ b/test/openssl/test_pkcs7.rb @@ -227,6 +227,12 @@ def test_smime assert_equal(p7.to_der, OpenSSL::PKCS7.read_smime(smime).to_der) end + def test_to_text + p7 = OpenSSL::PKCS7.new + p7.type = "signed" + assert_match(/signed/, p7.to_text) + end + def test_degenerate_pkcs7 ca_cert_pem = < Date: Wed, 8 May 2024 19:25:37 +0900 Subject: [PATCH 028/151] [Bug #20474] Keep spaces in leading blank line --- parse.y | 4 ++++ test/ruby/test_syntax.rb | 12 +++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 5dec8e01f930cd..5ff8394c2781e1 100644 --- a/parse.y +++ b/parse.y @@ -8578,6 +8578,10 @@ parser_update_heredoc_indent(struct parser_params *p, int c) } p->heredoc_line_indent = -1; } + else { + /* Whitespace only line has no indentation */ + p->heredoc_line_indent = 0; + } } return FALSE; } diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 8bdac2ebd1cb08..7b894eee79ec27 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -889,6 +889,16 @@ def test_dedented_heredoc_with_blank_more_indented_line assert_dedented_heredoc(expect, result) end + def test_dedented_heredoc_with_leading_blank_line + # the blank line has six leading spaces + result = " \n" \ + " b\n" + expect = " \n" \ + "b\n" + assert_dedented_heredoc(expect, result) + end + + def test_dedented_heredoc_with_blank_more_indented_line_escaped result = " a\n" \ "\\ \\ \\ \\ \\ \\ \n" \ @@ -996,7 +1006,7 @@ def test_dedented_heredoc_invalid_identifer end def test_dedented_heredoc_concatenation - assert_equal("\n0\n1", eval("<<~0 '1'\n \n0\#{}\n0")) + assert_equal(" \n0\n1", eval("<<~0 '1'\n \n0\#{}\n0")) end def test_heredoc_mixed_encoding From ba062a623147559ff891d6b52c86b31a1f3f4987 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Tue, 7 May 2024 15:23:10 -0400 Subject: [PATCH 029/151] [PRISM] Use correct warning encoding --- error.c | 31 ++++++++++++++++++++++++++----- prism_compile.c | 13 ++++++++----- test/.excludes-prism/TestParse.rb | 1 - 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/error.c b/error.c index dc032df6512cef..5f8111df57f470 100644 --- a/error.c +++ b/error.c @@ -386,18 +386,28 @@ warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_ return rb_str_cat2(str, "\n"); } -#define with_warn_vsprintf(file, line, fmt) \ +#define with_warn_vsprintf(enc, file, line, fmt) \ VALUE str; \ va_list args; \ va_start(args, fmt); \ - str = warn_vsprintf(NULL, file, line, fmt, args); \ + str = warn_vsprintf(enc, file, line, fmt, args); \ va_end(args); void rb_compile_warn(const char *file, int line, const char *fmt, ...) { if (!NIL_P(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { + rb_write_warning_str(str); + } + } +} + +void +rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...) +{ + if (!NIL_P(ruby_verbose)) { + with_warn_vsprintf(enc, file, line, fmt) { rb_write_warning_str(str); } } @@ -408,7 +418,18 @@ void rb_compile_warning(const char *file, int line, const char *fmt, ...) { if (RTEST(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { + rb_write_warning_str(str); + } + } +} + +/* rb_enc_compile_warning() reports only in verbose mode */ +void +rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...) +{ + if (RTEST(ruby_verbose)) { + with_warn_vsprintf(enc, file, line, fmt) { rb_write_warning_str(str); } } @@ -418,7 +439,7 @@ void rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...) { if (!NIL_P(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { rb_warn_category(str, rb_warning_category_to_name(category)); } } diff --git a/prism_compile.c b/prism_compile.c index 6d7d35fd19ab6d..4ea263d45c1877 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -9280,6 +9280,9 @@ pm_parse_process_error(const pm_parse_result_t *result) return error; } +void rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...); +void rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...); + /** * Parse the parse result and raise a Ruby error if there are any syntax errors. * It returns an error if one should be raised. It is assumed that the parse @@ -9298,6 +9301,9 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node) pm_scope_node_init(node, scope_node, NULL); scope_node->filepath_encoding = filepath_encoding; + scope_node->encoding = rb_enc_find(parser->encoding->name); + if (!scope_node->encoding) rb_bug("Encoding not found %s!", parser->encoding->name); + // Emit all of the various warnings from the parse. const pm_diagnostic_t *warning; const char *warning_filepath = (const char *) pm_string_source(&parser->filepath); @@ -9306,10 +9312,10 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node) int line = pm_location_line_number(parser, &warning->location); if (warning->level == PM_WARNING_LEVEL_VERBOSE) { - rb_compile_warning(warning_filepath, line, "%s", warning->message); + rb_enc_compile_warning(scope_node->encoding, warning_filepath, line, "%s", warning->message); } else { - rb_compile_warn(warning_filepath, line, "%s", warning->message); + rb_enc_compile_warn(scope_node->encoding, warning_filepath, line, "%s", warning->message); } } @@ -9324,9 +9330,6 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node) // Now set up the constant pool and intern all of the various constants into // their corresponding IDs. - scope_node->encoding = rb_enc_find(parser->encoding->name); - if (!scope_node->encoding) rb_bug("Encoding not found %s!", parser->encoding->name); - scope_node->parser = parser; scope_node->constants = calloc(parser->constant_pool.size, sizeof(ID)); diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 0afe3c13129d3d..b24c2df815ccd3 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -8,5 +8,4 @@ exclude(:test_truncated_source_line, "unknown") exclude(:test_unexpected_eof, "unknown") exclude(:test_unexpected_token_after_numeric, "unknown") -exclude(:test_unused_variable, "missing warning") exclude(:test_void_value_in_rhs, "unknown") From 5a332940ed2f809cb17af7e4d068089b6e1fa6ca Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 8 May 2024 21:39:32 +0900 Subject: [PATCH 030/151] Update revision.h if branch unmatch not only revision [ci skip] --- defs/gmake.mk | 15 ++++++++++----- tool/lib/vcs.rb | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/defs/gmake.mk b/defs/gmake.mk index c914b39690d50f..0d05adc5d3fe59 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -429,14 +429,19 @@ endif ifeq ($(HAVE_GIT),yes) REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null) +BRANCH_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) symbolic-ref --short HEAD 2>/dev/null) else REVISION_LATEST := update +BRANCH_LATEST := endif -REVISION_IN_HEADER := $(shell sed '/^\#define RUBY_FULL_REVISION "\(.*\)"/!d;s//\1/;q' $(wildcard $(srcdir)/revision.h revision.h) /dev/null 2>/dev/null) -ifeq ($(REVISION_IN_HEADER),) -REVISION_IN_HEADER := none -endif -ifneq ($(REVISION_IN_HEADER),$(REVISION_LATEST)) +revision.h := $(wildcard $(srcdir)/revision.h revision.h) +REVISION_IN_HEADER := $(if $(revision.h),\ + $(shell sed '/^\#define RUBY_FULL_REVISION "\(.*\)"/!d;s//\1/;q' $(revision.h))) +BRANCH_IN_HEADER := $(if $(revision.h),\ + $(shell sed '/^\#define RUBY_BRANCH_NAME \(".*"\)/!d;s//\1/;s,.* // ,,;s/"//g;q' $(revision.h))) +REVISION_IN_HEADER := $(if $(REVISION_IN_HEADER),$(REVISION_IN_HEADER),none) +BRANCH_IN_HEADER := $(if $(BRANCH_IN_HEADER),$(BRANCH_IN_HEADER),...) +ifneq ($(REVISION_IN_HEADER):$(BRANCH_IN_HEADER),$(REVISION_LATEST):$(BRANCH_LATEST)) $(REVISION_H): PHONY endif diff --git a/tool/lib/vcs.rb b/tool/lib/vcs.rb index 3894f9c8e8d5c1..563382c927d606 100644 --- a/tool/lib/vcs.rb +++ b/tool/lib/vcs.rb @@ -256,8 +256,9 @@ def revision_header(last, release_date, release_datetime = nil, branch = nil, ti if branch e = '..' name = branch.sub(/\A(.{#{limit-e.size}}).{#{e.size+1},}/o) {$1+e} - name = name.dump.sub(/\\#/, '#') - code << "#define RUBY_BRANCH_NAME #{name}" + (name = name.dump).gsub!(/\\#/, '#') + comment = " // #{branch}" unless name == %["#{branch}"] + code << "#define RUBY_BRANCH_NAME #{name}#{comment}" end if title title = title.dump.sub(/\\#/, '#') From 74d948a617caac55ef66119a4aebe4ee6c034d98 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 08:43:27 -0400 Subject: [PATCH 031/151] [ruby/prism] Better error message on missing hash value https://github.com/ruby/prism/commit/b20e37e82e --- prism/prism.c | 4 ++++ prism/templates/src/diagnostic.c.erb | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 4c685822ba88bf..1d2bf69bb25072 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -17030,6 +17030,10 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, pm_token_type_human(parser->previous.type)); break; } + case PM_ERR_HASH_VALUE: { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type)); + break; + } case PM_ERR_UNARY_RECEIVER: { const char *human = (parser->current.type == PM_TOKEN_EOF ? "end-of-input" : pm_token_type_human(parser->current.type)); PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]); diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 9406436c2b238b..0c3b267adfdfc4 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -210,7 +210,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_HASH_KEY] = { "unexpected %s, expecting '}' or a key in the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HASH_ROCKET] = { "expected a `=>` between the hash key and value", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HASH_TERM] = { "expected a `}` to close the hash literal", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_HASH_VALUE] = { "expected a value in the hash literal", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_HASH_VALUE] = { "unexpected %s; expected a value in the hash literal", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HEREDOC_IDENTIFIER] = { "unterminated here document identifier", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_HEREDOC_TERM] = { "unterminated heredoc; can't find string \"%.*s\" anywhere before EOF", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INCOMPLETE_QUESTION_MARK] = { "incomplete expression at `?`", PM_ERROR_LEVEL_SYNTAX }, From 06a1df3ef9559bbdac31c444e154ebf86e09d0a2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 09:19:19 -0400 Subject: [PATCH 032/151] [PRISM] Enable more passing tests --- test/.excludes-prism/TestRubyLiteral.rb | 1 - test/.excludes-prism/TestSyntax.rb | 4 ---- 2 files changed, 5 deletions(-) diff --git a/test/.excludes-prism/TestRubyLiteral.rb b/test/.excludes-prism/TestRubyLiteral.rb index 0305bc211773d0..9c6a8fd0fec856 100644 --- a/test/.excludes-prism/TestRubyLiteral.rb +++ b/test/.excludes-prism/TestRubyLiteral.rb @@ -1,3 +1,2 @@ exclude(:test_dregexp, "https://github.com/ruby/prism/issues/2664") -exclude(:test_hash_value_omission, "unknown") exclude(:test_string, "https://github.com/ruby/prism/issues/2331") diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index 9402546e68103e..f79839984300ea 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -1,16 +1,12 @@ exclude(:test__END___cr, "unknown") exclude(:test_argument_forwarding_with_super, "unknown") exclude(:test_argument_forwarding, "unknown") -exclude(:test_dedented_heredoc_concatenation, "unknown") exclude(:test_dedented_heredoc_continued_line, "unknown") exclude(:test_duplicated_when, "unknown") exclude(:test_error_message_encoding, "unknown") -exclude(:test_heredoc_cr, "unknown") -exclude(:test_heredoc_no_terminator, "unknown") exclude(:test_it, "https://github.com/ruby/prism/issues/2323") exclude(:test_keyword_invalid_name, "unknown") exclude(:test_keyword_self_reference, "unknown") -exclude(:test_methoddef_endless_command, "unknown") exclude(:test_numbered_parameter, "unknown") exclude(:test_optional_self_reference, "unknown") exclude(:test_syntax_error_at_newline, "unknown") From 548a72e537e4a189817f7e6ca28ad80013b1cb0c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 10:20:46 -0400 Subject: [PATCH 033/151] [PRISM] Sync prism version bump --- lib/prism/prism.gemspec | 2 +- prism/extension.h | 2 +- prism/templates/lib/prism/serialize.rb.erb | 2 +- prism/version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 8a3efe826d3317..d23b6a65cb2a4c 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "prism" - spec.version = "0.27.0" + spec.version = "0.28.0" spec.authors = ["Shopify"] spec.email = ["ruby@shopify.com"] diff --git a/prism/extension.h b/prism/extension.h index 9134959783c73d..93ad58fdc8f5b2 100644 --- a/prism/extension.h +++ b/prism/extension.h @@ -1,7 +1,7 @@ #ifndef PRISM_EXT_NODE_H #define PRISM_EXT_NODE_H -#define EXPECTED_PRISM_VERSION "0.27.0" +#define EXPECTED_PRISM_VERSION "0.28.0" #include #include diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 578e7d2e70f9e0..370b6297997689 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -10,7 +10,7 @@ module Prism # The minor version of prism that we are expecting to find in the serialized # strings. - MINOR_VERSION = 27 + MINOR_VERSION = 28 # The patch version of prism that we are expecting to find in the serialized # strings. diff --git a/prism/version.h b/prism/version.h index 0d25b2883c0707..195d1dab0a03be 100644 --- a/prism/version.h +++ b/prism/version.h @@ -14,7 +14,7 @@ /** * The minor version of the Prism library as an int. */ -#define PRISM_VERSION_MINOR 27 +#define PRISM_VERSION_MINOR 28 /** * The patch version of the Prism library as an int. @@ -24,6 +24,6 @@ /** * The version of the Prism library as a constant string. */ -#define PRISM_VERSION "0.27.0" +#define PRISM_VERSION "0.28.0" #endif From ad9c89fab8c532b4e5d926962c5d9d5ae5b01de4 Mon Sep 17 00:00:00 2001 From: git Date: Wed, 8 May 2024 14:22:18 +0000 Subject: [PATCH 034/151] Update default gems list at 548a72e537e4a189817f7e6ca28ad8 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index fdbd1fdb48add3..014a995c2a2fd5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -49,7 +49,7 @@ The following default gems are updated. * json 2.7.2 * net-http 0.4.1 * optparse 0.5.0 -* prism 0.27.0 +* prism 0.28.0 * rdoc 6.6.3.1 * reline 0.5.5 * resolv 0.4.0 From 26446cccc9e8c4dfb7655ae686106a1ee200f2ec Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Thu, 9 May 2024 01:00:26 +0900 Subject: [PATCH 035/151] [ruby/reline] Implement bracketed paste insert (https://github.com/ruby/reline/pull/655) https://github.com/ruby/reline/commit/e92dcbf514 --- lib/reline.rb | 19 +++++--- lib/reline/ansi.rb | 53 +++++++++------------ lib/reline/config.rb | 1 + lib/reline/line_editor.rb | 12 ++++- lib/reline/unicode.rb | 10 ++-- test/reline/yamatanooroti/test_rendering.rb | 9 +--- 6 files changed, 55 insertions(+), 49 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index d5bf2e363b0b6a..fb00b96531457e 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -312,6 +312,10 @@ def readline(prompt = '', add_hist = false) $stderr.sync = true $stderr.puts "Reline is used by #{Process.pid}" end + unless config.test_mode or config.loaded? + config.read + io_gate.set_default_key_bindings(config) + end otio = io_gate.prep may_req_ambiguous_char_width @@ -338,11 +342,6 @@ def readline(prompt = '', add_hist = false) end end - unless config.test_mode or config.loaded? - config.read - io_gate.set_default_key_bindings(config) - end - line_editor.print_nomultiline_prompt(prompt) line_editor.update_dialogs line_editor.rerender @@ -352,7 +351,15 @@ def readline(prompt = '', add_hist = false) loop do read_io(config.keyseq_timeout) { |inputs| line_editor.set_pasting_state(io_gate.in_pasting?) - inputs.each { |key| line_editor.update(key) } + inputs.each do |key| + if key.char == :bracketed_paste_start + text = io_gate.read_bracketed_paste + line_editor.insert_pasted_text(text) + line_editor.scroll_into_view + else + line_editor.update(key) + end + end } if line_editor.finished? line_editor.render_finished diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index 5e1f7249e3356d..45a475a787a582 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -45,6 +45,7 @@ def self.win? end def self.set_default_key_bindings(config, allow_terminfo: true) + set_bracketed_paste_key_bindings(config) set_default_key_bindings_ansi_cursor(config) if allow_terminfo && Reline::Terminfo.enabled? set_default_key_bindings_terminfo(config) @@ -66,6 +67,12 @@ def self.set_default_key_bindings(config, allow_terminfo: true) end end + def self.set_bracketed_paste_key_bindings(config) + [:emacs, :vi_insert, :vi_command].each do |keymap| + config.add_default_key_binding_by_keymap(keymap, START_BRACKETED_PASTE.bytes, :bracketed_paste_start) + end + end + def self.set_default_key_bindings_ansi_cursor(config) ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)| bindings = [["\e[#{char}", default_func]] # CSI + char @@ -178,46 +185,26 @@ def self.inner_getc(timeout_second) nil end - @@in_bracketed_paste_mode = false - START_BRACKETED_PASTE = String.new("\e[200~,", encoding: Encoding::ASCII_8BIT) - END_BRACKETED_PASTE = String.new("\e[200~.", encoding: Encoding::ASCII_8BIT) - def self.getc_with_bracketed_paste(timeout_second) + START_BRACKETED_PASTE = String.new("\e[200~", encoding: Encoding::ASCII_8BIT) + END_BRACKETED_PASTE = String.new("\e[201~", encoding: Encoding::ASCII_8BIT) + def self.read_bracketed_paste buffer = String.new(encoding: Encoding::ASCII_8BIT) - buffer << inner_getc(timeout_second) - while START_BRACKETED_PASTE.start_with?(buffer) or END_BRACKETED_PASTE.start_with?(buffer) do - if START_BRACKETED_PASTE == buffer - @@in_bracketed_paste_mode = true - return inner_getc(timeout_second) - elsif END_BRACKETED_PASTE == buffer - @@in_bracketed_paste_mode = false - ungetc(-1) - return inner_getc(timeout_second) - end - succ_c = inner_getc(Reline.core.config.keyseq_timeout) - - if succ_c - buffer << succ_c - else - break - end + until buffer.end_with?(END_BRACKETED_PASTE) + c = inner_getc(Float::INFINITY) + break unless c + buffer << c end - buffer.bytes.reverse_each do |ch| - ungetc ch - end - inner_getc(timeout_second) + string = buffer.delete_suffix(END_BRACKETED_PASTE).force_encoding(encoding) + string.valid_encoding? ? string : '' end # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second def self.getc(timeout_second) - if Reline.core.config.enable_bracketed_paste - getc_with_bracketed_paste(timeout_second) - else - inner_getc(timeout_second) - end + inner_getc(timeout_second) end def self.in_pasting? - @@in_bracketed_paste_mode or (not empty_buffer?) + not empty_buffer? end def self.empty_buffer? @@ -361,11 +348,15 @@ def self.set_winch_handler(&handler) end def self.prep + # Enable bracketed paste + @@output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste retrieve_keybuffer nil end def self.deprep(otio) + # Disable bracketed paste + @@output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste Signal.trap('WINCH', @@old_winch_handler) if @@old_winch_handler end end diff --git a/lib/reline/config.rb b/lib/reline/config.rb index e06b4d16e5f989..d44c2675abace0 100644 --- a/lib/reline/config.rb +++ b/lib/reline/config.rb @@ -51,6 +51,7 @@ def initialize @autocompletion = false @convert_meta = true if seven_bit_encoding?(Reline::IOGate.encoding) @loaded = false + @enable_bracketed_paste = true end def reset diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 57a3ab2f975840..9e221f4c9ce6d6 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -283,7 +283,7 @@ def multiline_off indent1 = @auto_indent_proc.(@buffer_of_lines.take(@line_index - 1).push(''), @line_index - 1, 0, true) indent2 = @auto_indent_proc.(@buffer_of_lines.take(@line_index), @line_index - 1, @buffer_of_lines[@line_index - 1].bytesize, false) indent = indent2 || indent1 - @buffer_of_lines[@line_index - 1] = ' ' * indent + @buffer_of_lines[@line_index - 1].gsub(/\A */, '') + @buffer_of_lines[@line_index - 1] = ' ' * indent + @buffer_of_lines[@line_index - 1].gsub(/\A\s*/, '') ) process_auto_indent @line_index, add_newline: true else @@ -1305,6 +1305,16 @@ def confirm_multiline_termination @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n") end + def insert_pasted_text(text) + pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer) + post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..) + lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1) + lines << '' if lines.empty? + @buffer_of_lines[@line_index, 1] = lines + @line_index += lines.size - 1 + @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize + end + def insert_text(text) if @buffer_of_lines[@line_index].bytesize == @byte_pointer @buffer_of_lines[@line_index] += text diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb index 82c9ec427ce7c2..d7460d6d4aec3f 100644 --- a/lib/reline/unicode.rb +++ b/lib/reline/unicode.rb @@ -43,11 +43,13 @@ class Reline::Unicode def self.escape_for_print(str) str.chars.map! { |gr| - escaped = EscapedPairs[gr.ord] - if escaped && gr != -"\n" && gr != -"\t" - escaped - else + case gr + when -"\n" gr + when -"\t" + -' ' + else + EscapedPairs[gr.ord] || gr end }.join end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 74798c338f32a5..9e8d7da78fdfe6 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -543,15 +543,10 @@ def test_no_escape_sequence_passed_to_dynamic_prompt EOC end - def test_enable_bracketed_paste + def test_bracketed_paste omit if Reline.core.io_gate.win? - write_inputrc <<~LINES - set enable-bracketed-paste on - LINES start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') - write("\e[200~,") - write("def hoge\n 3\nend") - write("\e[200~.") + write("\e[200~def hoge\r\t3\rend\e[201~") close assert_screen(<<~EOC) Multiline REPL. From e9378788837f7d053df4339ac0a0ea1d683502a4 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 9 May 2024 01:02:59 +0900 Subject: [PATCH 036/151] Revert "Update revision.h if branch unmatch not only revision" This reverts commit 5a332940ed2f809cb17af7e4d068089b6e1fa6ca. Something does not work well on Github Actions. --- defs/gmake.mk | 15 +++++---------- tool/lib/vcs.rb | 5 ++--- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/defs/gmake.mk b/defs/gmake.mk index 0d05adc5d3fe59..c914b39690d50f 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -429,19 +429,14 @@ endif ifeq ($(HAVE_GIT),yes) REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null) -BRANCH_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) symbolic-ref --short HEAD 2>/dev/null) else REVISION_LATEST := update -BRANCH_LATEST := endif -revision.h := $(wildcard $(srcdir)/revision.h revision.h) -REVISION_IN_HEADER := $(if $(revision.h),\ - $(shell sed '/^\#define RUBY_FULL_REVISION "\(.*\)"/!d;s//\1/;q' $(revision.h))) -BRANCH_IN_HEADER := $(if $(revision.h),\ - $(shell sed '/^\#define RUBY_BRANCH_NAME \(".*"\)/!d;s//\1/;s,.* // ,,;s/"//g;q' $(revision.h))) -REVISION_IN_HEADER := $(if $(REVISION_IN_HEADER),$(REVISION_IN_HEADER),none) -BRANCH_IN_HEADER := $(if $(BRANCH_IN_HEADER),$(BRANCH_IN_HEADER),...) -ifneq ($(REVISION_IN_HEADER):$(BRANCH_IN_HEADER),$(REVISION_LATEST):$(BRANCH_LATEST)) +REVISION_IN_HEADER := $(shell sed '/^\#define RUBY_FULL_REVISION "\(.*\)"/!d;s//\1/;q' $(wildcard $(srcdir)/revision.h revision.h) /dev/null 2>/dev/null) +ifeq ($(REVISION_IN_HEADER),) +REVISION_IN_HEADER := none +endif +ifneq ($(REVISION_IN_HEADER),$(REVISION_LATEST)) $(REVISION_H): PHONY endif diff --git a/tool/lib/vcs.rb b/tool/lib/vcs.rb index 563382c927d606..3894f9c8e8d5c1 100644 --- a/tool/lib/vcs.rb +++ b/tool/lib/vcs.rb @@ -256,9 +256,8 @@ def revision_header(last, release_date, release_datetime = nil, branch = nil, ti if branch e = '..' name = branch.sub(/\A(.{#{limit-e.size}}).{#{e.size+1},}/o) {$1+e} - (name = name.dump).gsub!(/\\#/, '#') - comment = " // #{branch}" unless name == %["#{branch}"] - code << "#define RUBY_BRANCH_NAME #{name}#{comment}" + name = name.dump.sub(/\\#/, '#') + code << "#define RUBY_BRANCH_NAME #{name}" end if title title = title.dump.sub(/\\#/, '#') From 7c1e11fe02f4d3db46a4f037a7ef0b715183f881 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 12:19:23 -0400 Subject: [PATCH 037/151] [ruby/prism] Validate Unicode escape sequences are not surrogates https://github.com/ruby/prism/commit/64d2ce2622 --- prism/prism.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 1d2bf69bb25072..3e9bc5c9aca098 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9367,12 +9367,20 @@ escape_hexadecimal_digit(const uint8_t value) { * validated. */ static inline uint32_t -escape_unicode(const uint8_t *string, size_t length) { +escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) { uint32_t value = 0; for (size_t index = 0; index < length; index++) { if (index != 0) value <<= 4; value |= escape_hexadecimal_digit(string[index]); } + + // Here we're going to verify that the value is actually a valid Unicode + // codepoint and not a surrogate pair. + if (value >= 0xD800 && value <= 0xDFFF) { + pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE); + return 0xFFFD; + } + return value; } @@ -9660,7 +9668,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre extra_codepoints_start = unicode_start; } - uint32_t value = escape_unicode(unicode_start, hexadecimal_length); + uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length); escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value); parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end); @@ -9685,7 +9693,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre size_t length = pm_strspn_hexadecimal_digit(parser->current.end, MIN(parser->end - parser->current.end, 4)); if (length == 4) { - uint32_t value = escape_unicode(parser->current.end, 4); + uint32_t value = escape_unicode(parser, parser->current.end, 4); if (flags & PM_ESCAPE_FLAG_REGEXP) { pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start)); From 84ba35e8c2b7f089ac9cbc601a8fe68432023c44 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 12:27:47 -0400 Subject: [PATCH 038/151] [ruby/prism] Invalid escape character syntax for nested unicode escapes https://github.com/ruby/prism/commit/623a0bb995 --- prism/config.yml | 1 + prism/prism.c | 4 ++++ prism/templates/src/diagnostic.c.erb | 1 + 3 files changed, 6 insertions(+) diff --git a/prism/config.yml b/prism/config.yml index 025777305154a3..8b4ffad065ce42 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -138,6 +138,7 @@ errors: - INVALID_BLOCK_EXIT - INVALID_CHARACTER - INVALID_ENCODING_MAGIC_COMMENT + - INVALID_ESCAPE_CHARACTER - INVALID_FLOAT_EXPONENT - INVALID_LOCAL_VARIABLE_READ - INVALID_LOCAL_VARIABLE_WRITE diff --git a/prism/prism.c b/prism/prism.c index 3e9bc5c9aca098..97fa30e4bd5293 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9707,6 +9707,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } } + if (flags & (PM_ESCAPE_FLAG_CONTROL | PM_ESCAPE_FLAG_META)) { + pm_parser_err(parser, start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); + } + return; } case 'c': { diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 0c3b267adfdfc4..cffaf0853d318f 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -220,6 +220,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "'%.*s' is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INSTANCE_VARIABLE_BARE] = { "'@' without identifiers is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_BLOCK_EXIT] = { "Invalid %s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_ESCAPE_CHARACTER] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_LOCAL_VARIABLE_READ] = { "identifier %.*s is not valid to get", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_LOCAL_VARIABLE_WRITE] = { "identifier %.*s is not valid to set", PM_ERROR_LEVEL_SYNTAX }, From 61829eec657e8271f05a74f2067b4203ba0a51a2 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 12:38:42 -0400 Subject: [PATCH 039/151] [ruby/prism] Ensure keyword parameters do not end in ! or ? https://github.com/ruby/prism/commit/57d86a8545 --- prism/prism.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/prism/prism.c b/prism/prism.c index 97fa30e4bd5293..6ae32825eb4065 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14326,6 +14326,10 @@ parse_parameters( pm_token_t local = name; local.end -= 1; + if (local.end[-1] == '!' || local.end[-1] == '?') { + PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE); + } + bool repeated = pm_parser_parameter_name_check(parser, &local); pm_parser_local_add_token(parser, &local, 1); From 2d631cf428a4bc76c0d75b5af841efd61d92aeee Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 13:04:33 -0400 Subject: [PATCH 040/151] [ruby/prism] Fix line number of unreachable statement warning https://github.com/ruby/prism/commit/62f6b1f2e2 --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 6ae32825eb4065..05123ac57036dc 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -6946,7 +6946,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, case PM_REDO_NODE: case PM_RETRY_NODE: case PM_RETURN_NODE: - pm_parser_warn_node(parser, previous, PM_WARN_UNREACHABLE_STATEMENT); + pm_parser_warn_node(parser, statement, PM_WARN_UNREACHABLE_STATEMENT); break; default: break; From 128c9a92dde2ad1319a2f5afc2e35b1b23841fd9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 13:58:39 -0400 Subject: [PATCH 041/151] [ruby/prism] Enhance def params term error message https://github.com/ruby/prism/commit/3af1acd5da --- prism/prism.c | 7 ++++++- prism/templates/src/diagnostic.c.erb | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 05123ac57036dc..09f25fa8a9c40b 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -18508,7 +18508,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b lex_state_set(parser, PM_LEX_STATE_BEG); parser->command_start = true; - expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_DEF_PARAMS_TERM_PAREN); + if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_type_human(parser->current.type)); + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + } + rparen = parser->previous; break; } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index cffaf0853d318f..75a00958fc8cec 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -149,7 +149,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_DEF_PARAMS_TERM_PAREN] = { "unexpected %s; expected a `)` to close the parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_RECEIVER] = { "expected a receiver for the method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_RECEIVER_TERM] = { "expected a `.` or `::` after the receiver in a method definition", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_DEF_TERM] = { "expected an `end` to close the `def` statement", PM_ERROR_LEVEL_SYNTAX }, From 442e398e62d32d042884f0cad76b5294d3110bfe Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 14:56:07 -0400 Subject: [PATCH 042/151] [ruby/prism] Ensure keyword parameters are not constants https://github.com/ruby/prism/commit/fd210115c1 --- prism/prism.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 09f25fa8a9c40b..f24f122420e0db 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14326,7 +14326,9 @@ parse_parameters( pm_token_t local = name; local.end -= 1; - if (local.end[-1] == '!' || local.end[-1] == '?') { + if (parser->encoding_changed ? parser->encoding->isupper_char(local.start, local.end - local.start) : pm_encoding_utf_8_isupper_char(local.start, local.end - local.start)) { + pm_parser_err(parser, local.start, local.end, PM_ERR_ARGUMENT_FORMAL_CONSTANT); + } else if (local.end[-1] == '!' || local.end[-1] == '?') { PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_INVALID_LOCAL_VARIABLE_WRITE); } From 8bd6ae4c40615c99458cc7ea0ba1897957502b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20=C5=A0im=C3=A1nek?= Date: Wed, 8 May 2024 23:46:42 +0200 Subject: [PATCH 043/151] [rubygems/rubygems] Monthly man update for May 2024. https://github.com/rubygems/rubygems/commit/9ee7069841 --- lib/bundler/man/bundle-add.1 | 2 +- lib/bundler/man/bundle-binstubs.1 | 2 +- lib/bundler/man/bundle-cache.1 | 2 +- lib/bundler/man/bundle-check.1 | 2 +- lib/bundler/man/bundle-clean.1 | 2 +- lib/bundler/man/bundle-config.1 | 2 +- lib/bundler/man/bundle-console.1 | 2 +- lib/bundler/man/bundle-doctor.1 | 2 +- lib/bundler/man/bundle-exec.1 | 2 +- lib/bundler/man/bundle-gem.1 | 2 +- lib/bundler/man/bundle-help.1 | 2 +- lib/bundler/man/bundle-info.1 | 2 +- lib/bundler/man/bundle-init.1 | 2 +- lib/bundler/man/bundle-inject.1 | 2 +- lib/bundler/man/bundle-install.1 | 2 +- lib/bundler/man/bundle-list.1 | 2 +- lib/bundler/man/bundle-lock.1 | 2 +- lib/bundler/man/bundle-open.1 | 2 +- lib/bundler/man/bundle-outdated.1 | 2 +- lib/bundler/man/bundle-platform.1 | 2 +- lib/bundler/man/bundle-plugin.1 | 2 +- lib/bundler/man/bundle-pristine.1 | 2 +- lib/bundler/man/bundle-remove.1 | 2 +- lib/bundler/man/bundle-show.1 | 2 +- lib/bundler/man/bundle-update.1 | 2 +- lib/bundler/man/bundle-version.1 | 2 +- lib/bundler/man/bundle-viz.1 | 2 +- lib/bundler/man/bundle.1 | 2 +- lib/bundler/man/gemfile.5 | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1 index 0b09480f88237f..56a3b6f85c9e24 100644 --- a/lib/bundler/man/bundle-add.1 +++ b/lib/bundler/man/bundle-add.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-ADD" "1" "April 2024" "" +.TH "BUNDLE\-ADD" "1" "May 2024" "" .SH "NAME" \fBbundle\-add\fR \- Add gem to the Gemfile and run bundle install .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1 index fdb86bfd2969a0..4ec301951fd1df 100644 --- a/lib/bundler/man/bundle-binstubs.1 +++ b/lib/bundler/man/bundle-binstubs.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-BINSTUBS" "1" "April 2024" "" +.TH "BUNDLE\-BINSTUBS" "1" "May 2024" "" .SH "NAME" \fBbundle\-binstubs\fR \- Install the binstubs of the listed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1 index c5899ace1af94f..e2da1269e6ddd6 100644 --- a/lib/bundler/man/bundle-cache.1 +++ b/lib/bundler/man/bundle-cache.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CACHE" "1" "April 2024" "" +.TH "BUNDLE\-CACHE" "1" "May 2024" "" .SH "NAME" \fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1 index e1a971edaef5ef..dee1af1326739c 100644 --- a/lib/bundler/man/bundle-check.1 +++ b/lib/bundler/man/bundle-check.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CHECK" "1" "April 2024" "" +.TH "BUNDLE\-CHECK" "1" "May 2024" "" .SH "NAME" \fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1 index ca2fb65f59153f..7c7f9b5c775856 100644 --- a/lib/bundler/man/bundle-clean.1 +++ b/lib/bundler/man/bundle-clean.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CLEAN" "1" "April 2024" "" +.TH "BUNDLE\-CLEAN" "1" "May 2024" "" .SH "NAME" \fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1 index a78c6b0a18e144..a207dbbcaa3a9e 100644 --- a/lib/bundler/man/bundle-config.1 +++ b/lib/bundler/man/bundle-config.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CONFIG" "1" "April 2024" "" +.TH "BUNDLE\-CONFIG" "1" "May 2024" "" .SH "NAME" \fBbundle\-config\fR \- Set bundler configuration options .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1 index 86be5e41858e0f..dca18ec43df498 100644 --- a/lib/bundler/man/bundle-console.1 +++ b/lib/bundler/man/bundle-console.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-CONSOLE" "1" "April 2024" "" +.TH "BUNDLE\-CONSOLE" "1" "May 2024" "" .SH "NAME" \fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1 index 94cbff4cbddbd9..6489cc07f7ed8b 100644 --- a/lib/bundler/man/bundle-doctor.1 +++ b/lib/bundler/man/bundle-doctor.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-DOCTOR" "1" "April 2024" "" +.TH "BUNDLE\-DOCTOR" "1" "May 2024" "" .SH "NAME" \fBbundle\-doctor\fR \- Checks the bundle for common problems .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1 index 7aa49e0096c713..1548d29670fa1c 100644 --- a/lib/bundler/man/bundle-exec.1 +++ b/lib/bundler/man/bundle-exec.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-EXEC" "1" "April 2024" "" +.TH "BUNDLE\-EXEC" "1" "May 2024" "" .SH "NAME" \fBbundle\-exec\fR \- Execute a command in the context of the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1 index 89eb9f1980f6d7..5df7b0ef2f9ba7 100644 --- a/lib/bundler/man/bundle-gem.1 +++ b/lib/bundler/man/bundle-gem.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-GEM" "1" "April 2024" "" +.TH "BUNDLE\-GEM" "1" "May 2024" "" .SH "NAME" \fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1 index 441ec12735b97b..a3e7c7770d0371 100644 --- a/lib/bundler/man/bundle-help.1 +++ b/lib/bundler/man/bundle-help.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-HELP" "1" "April 2024" "" +.TH "BUNDLE\-HELP" "1" "May 2024" "" .SH "NAME" \fBbundle\-help\fR \- Displays detailed help for each subcommand .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1 index 287965c06a78c8..a3d7ff0988a442 100644 --- a/lib/bundler/man/bundle-info.1 +++ b/lib/bundler/man/bundle-info.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INFO" "1" "April 2024" "" +.TH "BUNDLE\-INFO" "1" "May 2024" "" .SH "NAME" \fBbundle\-info\fR \- Show information for the given gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1 index d13f8ddc3be7d3..a0edaaa18fbe56 100644 --- a/lib/bundler/man/bundle-init.1 +++ b/lib/bundler/man/bundle-init.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INIT" "1" "April 2024" "" +.TH "BUNDLE\-INIT" "1" "May 2024" "" .SH "NAME" \fBbundle\-init\fR \- Generates a Gemfile into the current working directory .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1 index 086fc88156fc91..7a1038206e16fd 100644 --- a/lib/bundler/man/bundle-inject.1 +++ b/lib/bundler/man/bundle-inject.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INJECT" "1" "April 2024" "" +.TH "BUNDLE\-INJECT" "1" "May 2024" "" .SH "NAME" \fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1 index 762c99e7c0e021..cc46a03b7fc98e 100644 --- a/lib/bundler/man/bundle-install.1 +++ b/lib/bundler/man/bundle-install.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-INSTALL" "1" "April 2024" "" +.TH "BUNDLE\-INSTALL" "1" "May 2024" "" .SH "NAME" \fBbundle\-install\fR \- Install the dependencies specified in your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1 index 93db700091617b..21723608cc3622 100644 --- a/lib/bundler/man/bundle-list.1 +++ b/lib/bundler/man/bundle-list.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-LIST" "1" "April 2024" "" +.TH "BUNDLE\-LIST" "1" "May 2024" "" .SH "NAME" \fBbundle\-list\fR \- List all the gems in the bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1 index c0190f91dee7cc..8b81b7732f705d 100644 --- a/lib/bundler/man/bundle-lock.1 +++ b/lib/bundler/man/bundle-lock.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-LOCK" "1" "April 2024" "" +.TH "BUNDLE\-LOCK" "1" "May 2024" "" .SH "NAME" \fBbundle\-lock\fR \- Creates / Updates a lockfile without installing .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1 index 38bacb67dc3749..41a8804a0936c4 100644 --- a/lib/bundler/man/bundle-open.1 +++ b/lib/bundler/man/bundle-open.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-OPEN" "1" "April 2024" "" +.TH "BUNDLE\-OPEN" "1" "May 2024" "" .SH "NAME" \fBbundle\-open\fR \- Opens the source directory for a gem in your bundle .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1 index cee9d63155acab..838fce45cd8fb6 100644 --- a/lib/bundler/man/bundle-outdated.1 +++ b/lib/bundler/man/bundle-outdated.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-OUTDATED" "1" "April 2024" "" +.TH "BUNDLE\-OUTDATED" "1" "May 2024" "" .SH "NAME" \fBbundle\-outdated\fR \- List installed gems with newer versions available .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1 index 069966f1b2ef26..0dbce7a7a4d834 100644 --- a/lib/bundler/man/bundle-platform.1 +++ b/lib/bundler/man/bundle-platform.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PLATFORM" "1" "April 2024" "" +.TH "BUNDLE\-PLATFORM" "1" "May 2024" "" .SH "NAME" \fBbundle\-platform\fR \- Displays platform compatibility information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1 index f4e043c363830c..1290abb3baa9e1 100644 --- a/lib/bundler/man/bundle-plugin.1 +++ b/lib/bundler/man/bundle-plugin.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PLUGIN" "1" "April 2024" "" +.TH "BUNDLE\-PLUGIN" "1" "May 2024" "" .SH "NAME" \fBbundle\-plugin\fR \- Manage Bundler plugins .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1 index 76a0479bc6f574..bf4a7cd32336ce 100644 --- a/lib/bundler/man/bundle-pristine.1 +++ b/lib/bundler/man/bundle-pristine.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-PRISTINE" "1" "April 2024" "" +.TH "BUNDLE\-PRISTINE" "1" "May 2024" "" .SH "NAME" \fBbundle\-pristine\fR \- Restores installed gems to their pristine condition .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1 index 90a664e33112f6..c3c96b416d3a4a 100644 --- a/lib/bundler/man/bundle-remove.1 +++ b/lib/bundler/man/bundle-remove.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-REMOVE" "1" "April 2024" "" +.TH "BUNDLE\-REMOVE" "1" "May 2024" "" .SH "NAME" \fBbundle\-remove\fR \- Removes gems from the Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1 index f9f1fd1fa38f05..c054875efd84be 100644 --- a/lib/bundler/man/bundle-show.1 +++ b/lib/bundler/man/bundle-show.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-SHOW" "1" "April 2024" "" +.TH "BUNDLE\-SHOW" "1" "May 2024" "" .SH "NAME" \fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1 index 340ebac68779c1..acd80ec75c13f7 100644 --- a/lib/bundler/man/bundle-update.1 +++ b/lib/bundler/man/bundle-update.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-UPDATE" "1" "April 2024" "" +.TH "BUNDLE\-UPDATE" "1" "May 2024" "" .SH "NAME" \fBbundle\-update\fR \- Update your gems to the latest available versions .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1 index 00ff0153cbc404..44eaf92224f6e9 100644 --- a/lib/bundler/man/bundle-version.1 +++ b/lib/bundler/man/bundle-version.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-VERSION" "1" "April 2024" "" +.TH "BUNDLE\-VERSION" "1" "May 2024" "" .SH "NAME" \fBbundle\-version\fR \- Prints Bundler version information .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1 index eba3b7df25b0ac..77b902214c243a 100644 --- a/lib/bundler/man/bundle-viz.1 +++ b/lib/bundler/man/bundle-viz.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE\-VIZ" "1" "April 2024" "" +.TH "BUNDLE\-VIZ" "1" "May 2024" "" .SH "NAME" \fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile .SH "SYNOPSIS" diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1 index 4bd2bcaf6741f0..199d1ce9fd5cec 100644 --- a/lib/bundler/man/bundle.1 +++ b/lib/bundler/man/bundle.1 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "BUNDLE" "1" "April 2024" "" +.TH "BUNDLE" "1" "May 2024" "" .SH "NAME" \fBbundle\fR \- Ruby Dependency Management .SH "SYNOPSIS" diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5 index c9478a953e2691..fa9e31f615a0e5 100644 --- a/lib/bundler/man/gemfile.5 +++ b/lib/bundler/man/gemfile.5 @@ -1,6 +1,6 @@ .\" generated with nRonn/v0.11.1 .\" https://github.com/n-ronn/nronn/tree/0.11.1 -.TH "GEMFILE" "5" "April 2024" "" +.TH "GEMFILE" "5" "May 2024" "" .SH "NAME" \fBGemfile\fR \- A format for describing gem dependencies for Ruby programs .SH "SYNOPSIS" From d224bfdc3252913ac635be0bf28173c659a10687 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Apr 2024 17:13:25 +0900 Subject: [PATCH 044/151] `redblack_cache_ancestors` is enabled only when `mmap` is available --- shape.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shape.c b/shape.c index 68c74034e70d65..0f9e3d54fa7ec7 100644 --- a/shape.c +++ b/shape.c @@ -118,6 +118,7 @@ redblack_value(redblack_node_t * node) return (rb_shape_t *)((uintptr_t)node->value & (((uintptr_t)-1) - 1)); } +#ifdef HAVE_MMAP static redblack_id_t redblack_id_for(redblack_node_t * node) { @@ -292,6 +293,7 @@ redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value) return root; } } +#endif rb_shape_tree_t *rb_shape_tree_ptr = NULL; From d6564615e7aad09348b6bb933f787ee30916971e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Apr 2024 17:14:11 +0900 Subject: [PATCH 045/151] Fix format specifier for `DWORD` --- io_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io_buffer.c b/io_buffer.c index 7715aa0d372dc6..af884f14739a41 100644 --- a/io_buffer.c +++ b/io_buffer.c @@ -260,7 +260,7 @@ io_buffer_free(struct rb_io_buffer *buffer) if (buffer->mapping) { if (RB_IO_BUFFER_DEBUG) fprintf(stderr, "io_buffer_free:CloseHandle -> %p\n", buffer->mapping); if (!CloseHandle(buffer->mapping)) { - fprintf(stderr, "io_buffer_free:GetLastError -> %d\n", GetLastError()); + fprintf(stderr, "io_buffer_free:GetLastError -> %lu\n", GetLastError()); } buffer->mapping = NULL; } From 58bde0169d64146ac30976f66412ef1c32b68c58 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 9 May 2024 10:45:45 +0900 Subject: [PATCH 046/151] [DOC] Fix the pattern for man pages --- .github/workflows/annocheck.yml | 4 ++-- .github/workflows/baseruby.yml | 4 ++-- .github/workflows/check_dependencies.yml | 4 ++-- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/compilers.yml | 4 ++-- .github/workflows/macos.yml | 2 +- .github/workflows/mingw.yml | 4 ++-- .github/workflows/rjit-bindgen.yml | 4 ++-- .github/workflows/ubuntu.yml | 2 +- .github/workflows/wasm.yml | 4 ++-- .github/workflows/windows.yml | 4 ++-- .github/workflows/yjit-macos.yml | 2 +- .github/workflows/yjit-ubuntu.yml | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index c6b5ff1c0433bb..0590d8c75e1d7d 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -4,7 +4,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,7 +12,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 7aaf6b8f447ff7..4876251b82b4fd 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -4,7 +4,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,7 +12,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index 4bbcb73cb51e10..fbad01a8f47a4d 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,7 +11,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8b8a4565da121f..4ada9e8446c36f 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,7 +5,7 @@ on: branches: ['master'] paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -13,7 +13,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index 5f6cd59481c075..d4b047b4e93c85 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -4,7 +4,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -12,7 +12,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 71c314021fc6c3..9d0ff5ae373bf1 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index df6b2bd312da1c..f4d399751a6574 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,7 +11,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index 168794ddbbddc9..799be7a847f4df 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,7 +11,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 70ee4a2e6171ce..b808ac5e9e2baa 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index b77f4a152a5b47..09f8e4bbccdff4 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,7 +11,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 8fe00aca1c6fda..d4b9bd644aaf96 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' @@ -11,7 +11,7 @@ on: pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index e04306e46aa30a..c6acd3c614b2d0 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index b040f6d78b103e..2b0c79db28436d 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -3,7 +3,7 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' From d10615c064603a138379019834b13349e563e7bb Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 9 May 2024 11:40:02 +0900 Subject: [PATCH 047/151] [DOC] Update `--dump` option arguments in the ruby man page Related to [Feature #20329]. --- man/ruby.1 | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/man/ruby.1 b/man/ruby.1 index 3cfe605ce9fcb3..bbad8ae2036f62 100644 --- a/man/ruby.1 +++ b/man/ruby.1 @@ -448,18 +448,20 @@ Check syntax (same as .El .Pp Or one of the following, which are intended for debugging the interpreter: -.Bl -hang -offset indent -tag -width "parsetree_with_comment" +.Bl -hang -offset indent -tag -width "+error-tolerant" .It Sy yydebug Enable compiler debug mode (same as .Fl -yydebug). .It Sy parsetree Print a textual representation of the Ruby AST for the program. -.It Sy parsetree_with_comment -Print a textual representation of the Ruby AST for the program, but with each node annotated with the associated Ruby source code. .It Sy insns Print a list of disassembled bytecode instructions. -.It Sy insns_without_opt -Print the list of disassembled bytecode instructions before various optimizations have been applied. +.It Sy -optimize +Disable various optimizations to print a list disassembled bytecode instructions. +.It Sy +error-tolerant +Enable error-tolerant parsing, when yydebug or parsetree. +.It Sy +comment +Annotate a textual representation of the Ruby AST for the program with the associated Ruby source code. .El .Pp .It Fl -verbose From 43b18dac9153df6d325910c1318c456a3dc51395 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 02:52:07 +0000 Subject: [PATCH 048/151] Bump github/codeql-action from 3.25.3 to 3.25.4 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.3 to 3.25.4. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/d39d31e687223d841ef683f52467bd88e9b21c14...ccf74c947955fd1cf117aef6a0e4e66191ef6f61) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/scorecards.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 4ada9e8446c36f..8191d6beb29852 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -80,15 +80,15 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/init@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/autobuild@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/analyze@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 with: category: '/language:${{ matrix.language }}' upload: False @@ -118,7 +118,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v3.25.3 + uses: github/codeql-action/upload-sarif@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 7f3a24b05fad28..be8d99d89d149b 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@d39d31e687223d841ef683f52467bd88e9b21c14 # v2.1.27 + uses: github/codeql-action/upload-sarif@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v2.1.27 with: sarif_file: results.sarif From 9df3f205b1f2982047f9701ce0172d54fa360bdc Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 9 May 2024 12:29:37 +0900 Subject: [PATCH 049/151] test-syntax-suggest is not working with mswin environment --- common.mk | 24 +----------------------- template/Makefile.in | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/common.mk b/common.mk index 1345709a2de2cb..18641efd7ffbbd 100644 --- a/common.mk +++ b/common.mk @@ -1620,30 +1620,8 @@ yes-test-bundled-gems-spec: yes-test-spec-precheck $(PREPARE_BUNDLED_GEMS) $(ACTIONS_ENDGROUP) no-test-bundled-gems-spec: -test-syntax-suggest-precheck: $(TEST_RUNNABLE)-test-syntax-suggest-precheck -no-test-syntax-suggest-precheck: -yes-test-syntax-suggest-precheck: main -test-syntax-suggest-prepare: $(TEST_RUNNABLE)-test-syntax-suggest-prepare -no-test-syntax-suggest-prepare: no-test-syntax-suggest-precheck -yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck - $(ACTIONS_GROUP) - $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ - --install-dir .bundle --conservative "rspec:~> 3" - $(ACTIONS_ENDGROUP) - -RSPECOPTS = -SYNTAX_SUGGEST_SPECS = -PREPARE_SYNTAX_SUGGEST = $(TEST_RUNNABLE)-test-syntax-suggest-prepare -test-syntax-suggest: $(TEST_RUNNABLE)-test-syntax-suggest -yes-test-syntax-suggest: $(PREPARE_SYNTAX_SUGGEST) - $(ACTIONS_GROUP) - $(XRUBY) -C $(srcdir) -Ispec/syntax_suggest:spec/lib .bundle/bin/rspec \ - --require rspec/expectations \ - --require spec_helper --require formatter_overrides --require spec_coverage \ - $(RSPECOPTS) spec/syntax_suggest/$(SYNTAX_SUGGEST_SPECS) - $(ACTIONS_ENDGROUP) -no-test-syntax-suggest: +test-syntax-suggest: check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest diff --git a/template/Makefile.in b/template/Makefile.in index d9a3cbc0650206..813a727cf9f4db 100644 --- a/template/Makefile.in +++ b/template/Makefile.in @@ -663,3 +663,28 @@ yes-test-leaked-globals: yes-test-leaked-globals-precheck PLATFORM=$(hdrdir)/ruby/$(PLATFORM_DIR).h $(srcdir)/configure.ac \ $(COMMONOBJS) $(LIBRUBY_FOR_LEAKED_GLOBALS:yes=$(LIBRUBY_SO)) $(ACTIONS_ENDGROUP) + +test-syntax-suggest-precheck: $(TEST_RUNNABLE)-test-syntax-suggest-precheck +no-test-syntax-suggest-precheck: +yes-test-syntax-suggest-precheck: main + +test-syntax-suggest-prepare: $(TEST_RUNNABLE)-test-syntax-suggest-prepare +no-test-syntax-suggest-prepare: no-test-syntax-suggest-precheck +yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck + $(ACTIONS_GROUP) + $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ + --install-dir .bundle --conservative "rspec:~> 3" + $(ACTIONS_ENDGROUP) + +RSPECOPTS = +SYNTAX_SUGGEST_SPECS = +PREPARE_SYNTAX_SUGGEST = $(TEST_RUNNABLE)-test-syntax-suggest-prepare +test-syntax-suggest: $(TEST_RUNNABLE)-test-syntax-suggest +yes-test-syntax-suggest: $(PREPARE_SYNTAX_SUGGEST) + $(ACTIONS_GROUP) + $(XRUBY) -C $(srcdir) -Ispec/syntax_suggest:spec/lib .bundle/bin/rspec \ + --require rspec/expectations \ + --require spec_helper --require formatter_overrides --require spec_coverage \ + $(RSPECOPTS) spec/syntax_suggest/$(SYNTAX_SUGGEST_SPECS) + $(ACTIONS_ENDGROUP) +no-test-syntax-suggest: From 6bff0707e826b7adf8d473ae269ecdb7dd6f8f34 Mon Sep 17 00:00:00 2001 From: git Date: Thu, 9 May 2024 06:59:48 +0000 Subject: [PATCH 050/151] Update bundled gems list as of 2024-05-08 --- NEWS.md | 2 +- gems/bundled_gems | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 014a995c2a2fd5..2dddf5978c1d26 100644 --- a/NEWS.md +++ b/NEWS.md @@ -62,7 +62,7 @@ The following bundled gems are updated. * rake 13.2.1 * test-unit 3.6.2 * net-ftp 0.3.4 -* net-imap 0.4.10 +* net-imap 0.4.11 * net-smtp 0.5.0 * rbs 3.4.4 * typeprof 0.21.11 diff --git a/gems/bundled_gems b/gems/bundled_gems index 4e7e23bacefe8e..c6bb0f9f545c67 100644 --- a/gems/bundled_gems +++ b/gems/bundled_gems @@ -13,7 +13,7 @@ test-unit 3.6.2 https://github.com/test-unit/test-unit rexml 3.2.6 https://github.com/ruby/rexml rss 0.3.0 https://github.com/ruby/rss net-ftp 0.3.4 https://github.com/ruby/net-ftp -net-imap 0.4.10 https://github.com/ruby/net-imap +net-imap 0.4.11 https://github.com/ruby/net-imap net-pop 0.1.2 https://github.com/ruby/net-pop net-smtp 0.5.0 https://github.com/ruby/net-smtp matrix 0.4.2 https://github.com/ruby/matrix From fb6cfb413d2b2cd3aa6306db7128a7288fd0a131 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 9 May 2024 17:39:57 +0900 Subject: [PATCH 051/151] Mark rdoc as bundled gems at Ruby 3.5 --- lib/bundled_gems.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bundled_gems.rb b/lib/bundled_gems.rb index ed5f940b5744bb..c933ad04717473 100644 --- a/lib/bundled_gems.rb +++ b/lib/bundled_gems.rb @@ -28,6 +28,7 @@ module Gem::BUNDLED_GEMS "syslog" => "3.4.0", "ostruct" => "3.5.0", "pstore" => "3.5.0", + "rdoc" => "3.5.0", }.freeze EXACT = { @@ -45,6 +46,7 @@ module Gem::BUNDLED_GEMS "syslog" => true, "ostruct" => true, "pstore" => true, + "rdoc" => true, }.freeze PREFIXED = { From fba7bdb710de11343fe7acaac8eba3aad0cbc398 Mon Sep 17 00:00:00 2001 From: Mari Imaizumi Date: Thu, 9 May 2024 18:52:25 +0900 Subject: [PATCH 052/151] [ruby/reline] Bump version to 0.5.6 (https://github.com/ruby/reline/pull/700) https://github.com/ruby/reline/commit/1b6c29a2b1 --- lib/reline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reline/version.rb b/lib/reline/version.rb index ab10713f459106..ef7d617a4504fe 100644 --- a/lib/reline/version.rb +++ b/lib/reline/version.rb @@ -1,3 +1,3 @@ module Reline - VERSION = '0.5.5' + VERSION = '0.5.6' end From 8b3280bebd901cd7e42fe1d3f31152443f0e9040 Mon Sep 17 00:00:00 2001 From: git Date: Thu, 9 May 2024 09:53:28 +0000 Subject: [PATCH 053/151] Update default gems list at fba7bdb710de11343fe7acaac8eba3 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 2dddf5978c1d26..c47ff32912d8c3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -51,7 +51,7 @@ The following default gems are updated. * optparse 0.5.0 * prism 0.28.0 * rdoc 6.6.3.1 -* reline 0.5.5 +* reline 0.5.6 * resolv 0.4.0 * stringio 3.1.1 * strscan 3.1.1 From e82138e48a7ff152e358ce37fdae07e989fe5ee3 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 9 May 2024 11:38:07 +0200 Subject: [PATCH 054/151] Stabilize TestObjSpace#test_dump_special_consts The test assumes `:foo` is a static symbol, but that is only true if a literal `:foo` was parsed before `"foo".to_sym` was evaled: ```ruby require 'objspace' foo_sym = "foo".to_sym puts ObjectSpace.dump(eval(":foo")) ``` ``` {"address":"0x100fb46d0", "type":"SYMBOL", "shape_id":10, "slot_size":40, "class":"0x100d3e9c8", "frozen":true, "bytesize":3, "value":"foo", "memsize":40, "flags":{"wb_protected":true, "marking":true, "marked":true}} ``` --- test/objspace/test_objspace.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb index b798b897b44e17..17f73e44336801 100644 --- a/test/objspace/test_objspace.rb +++ b/test/objspace/test_objspace.rb @@ -416,7 +416,7 @@ def test_dump_special_consts assert_equal('true', ObjectSpace.dump(true)) assert_equal('false', ObjectSpace.dump(false)) assert_equal('0', ObjectSpace.dump(0)) - assert_equal('{"type":"SYMBOL", "value":"foo"}', ObjectSpace.dump(:foo)) + assert_equal('{"type":"SYMBOL", "value":"test_dump_special_consts"}', ObjectSpace.dump(:test_dump_special_consts)) end def test_dump_singleton_class From 74c911dfa99e173756e7382982e8eaa0a90a2491 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 9 May 2024 11:56:51 +0200 Subject: [PATCH 055/151] Add a ruby_bug spec for String#index clearing $~ [Bug #20421] The bug was fixed in Ruby 3.3 via 9dcdffb8bf8a3654fd78bf1a58b30c8e13888a7a --- spec/ruby/core/string/index_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/ruby/core/string/index_spec.rb b/spec/ruby/core/string/index_spec.rb index be797080451a41..835263a2cd58c2 100644 --- a/spec/ruby/core/string/index_spec.rb +++ b/spec/ruby/core/string/index_spec.rb @@ -231,6 +231,17 @@ $~.should == nil end + ruby_bug "#20421", ""..."3.3" do + it "always clear $~" do + "a".index(/a/) + $~.should_not == nil + + string = "blablabla" + string.index(/bla/, string.length + 1) + $~.should == nil + end + end + it "starts the search at the given offset" do "blablabla".index(/.{0}/, 5).should == 5 "blablabla".index(/.{1}/, 5).should == 5 From 444030fc6155d32c1f5211ba746bc9c76f70a96d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 8 May 2024 14:20:12 -0400 Subject: [PATCH 056/151] [PRISM] Enable passing tests --- test/.excludes-prism/TestCoverage.rb | 2 +- test/.excludes-prism/TestIRB/RubyLexTest.rb | 2 +- test/.excludes-prism/TestISeq.rb | 7 ++++--- test/.excludes-prism/TestM17N.rb | 4 ++-- .../.excludes-prism/TestMixedUnicodeEscape.rb | 2 +- test/.excludes-prism/TestParse.rb | 21 +++++++++---------- test/.excludes-prism/TestRegexp.rb | 2 +- test/.excludes-prism/TestRequire.rb | 2 +- test/.excludes-prism/TestRubyLiteral.rb | 2 +- test/.excludes-prism/TestSyntax.rb | 7 +++---- test/.excludes-prism/TestUnicodeEscape.rb | 1 - test/ruby/test_parse.rb | 4 ++-- 12 files changed, 27 insertions(+), 29 deletions(-) delete mode 100644 test/.excludes-prism/TestUnicodeEscape.rb diff --git a/test/.excludes-prism/TestCoverage.rb b/test/.excludes-prism/TestCoverage.rb index 20f9972f898616..f122d6edbc768f 100644 --- a/test/.excludes-prism/TestCoverage.rb +++ b/test/.excludes-prism/TestCoverage.rb @@ -1 +1 @@ -exclude(:test_eval, "unknown") +exclude(:test_eval, "respect eval coverage setting") diff --git a/test/.excludes-prism/TestIRB/RubyLexTest.rb b/test/.excludes-prism/TestIRB/RubyLexTest.rb index 2274ae62cfd589..d2635f96117ab2 100644 --- a/test/.excludes-prism/TestIRB/RubyLexTest.rb +++ b/test/.excludes-prism/TestIRB/RubyLexTest.rb @@ -1 +1 @@ -exclude(:test_code_block_open_with_should_continue, "symbol encoding") +exclude(:test_code_block_open_with_should_continue, "https://github.com/ruby/irb/pull/954") diff --git a/test/.excludes-prism/TestISeq.rb b/test/.excludes-prism/TestISeq.rb index 3768d8fc05f12d..ee3d92494e440e 100644 --- a/test/.excludes-prism/TestISeq.rb +++ b/test/.excludes-prism/TestISeq.rb @@ -1,3 +1,4 @@ -exclude(:test_each_child, "https://github.com/ruby/prism/issues/2660") -exclude(:test_syntax_error_message, "Assertion checks against specific error format") -exclude(:test_trace_points, "https://github.com/ruby/prism/issues/2660") +exclude(:test_syntax_error_message, "error message format") + +exclude(:test_each_child, "https://bugs.ruby-lang.org/issues/20479") +exclude(:test_trace_points, "https://bugs.ruby-lang.org/issues/20479") diff --git a/test/.excludes-prism/TestM17N.rb b/test/.excludes-prism/TestM17N.rb index e3c2d43b74f967..f10c9632d96dda 100644 --- a/test/.excludes-prism/TestM17N.rb +++ b/test/.excludes-prism/TestM17N.rb @@ -1,2 +1,2 @@ -exclude(:test_regexp_usascii, "unknown") -exclude(:test_string_mixed_unicode, "unknown") +exclude(:test_regexp_usascii, "x80 should raise syntax error") +exclude(:test_string_mixed_unicode, "should raise mixed encoding error") diff --git a/test/.excludes-prism/TestMixedUnicodeEscape.rb b/test/.excludes-prism/TestMixedUnicodeEscape.rb index 09e3cc168bc32b..753c119d147520 100644 --- a/test/.excludes-prism/TestMixedUnicodeEscape.rb +++ b/test/.excludes-prism/TestMixedUnicodeEscape.rb @@ -1 +1 @@ -exclude(:test_basic, "unknown") +exclude(:test_basic, "should raise mixed encoding error") diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index b24c2df815ccd3..7cf5f97dd26631 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,11 +1,10 @@ -exclude(:test_error_def_in_argument, "unknown") -exclude(:test_global_variable, "unknown") -exclude(:test_invalid_char, "unknown") -exclude(:test_location_of_invalid_token, "unknown") -exclude(:test_percent, "unknown") -exclude(:test_question, "unknown") -exclude(:test_string, "unknown") -exclude(:test_truncated_source_line, "unknown") -exclude(:test_unexpected_eof, "unknown") -exclude(:test_unexpected_token_after_numeric, "unknown") -exclude(:test_void_value_in_rhs, "unknown") +exclude(:test_global_variable, "error message format") +exclude(:test_invalid_char, "error message format") +exclude(:test_location_of_invalid_token, "error message format") +exclude(:test_percent, "error message format") +exclude(:test_question, "error message format") +exclude(:test_string, "error message format") +exclude(:test_truncated_source_line, "truncate error message") +exclude(:test_unexpected_eof, "error message format") +exclude(:test_unexpected_token_after_numeric, "error message format") +exclude(:test_void_value_in_rhs, "missing raising error for some void value expressions") diff --git a/test/.excludes-prism/TestRegexp.rb b/test/.excludes-prism/TestRegexp.rb index 62e704fac5994f..9d514236c73eee 100644 --- a/test/.excludes-prism/TestRegexp.rb +++ b/test/.excludes-prism/TestRegexp.rb @@ -1 +1 @@ -exclude(:test_unescape, "unknown") +exclude(:test_unescape, "unescapes in regexp missing some bytes") diff --git a/test/.excludes-prism/TestRequire.rb b/test/.excludes-prism/TestRequire.rb index a7f66c5d80bc45..cb35d59c6008be 100644 --- a/test/.excludes-prism/TestRequire.rb +++ b/test/.excludes-prism/TestRequire.rb @@ -1 +1 @@ -exclude(:test_require_nonascii_path_shift_jis, "encoding") +exclude(:test_require_nonascii_path_shift_jis, "requiring non-ascii paths") diff --git a/test/.excludes-prism/TestRubyLiteral.rb b/test/.excludes-prism/TestRubyLiteral.rb index 9c6a8fd0fec856..d51295081f6bec 100644 --- a/test/.excludes-prism/TestRubyLiteral.rb +++ b/test/.excludes-prism/TestRubyLiteral.rb @@ -1,2 +1,2 @@ -exclude(:test_dregexp, "https://github.com/ruby/prism/issues/2664") +exclude(:test_dregexp, "x80 should raise syntax error") exclude(:test_string, "https://github.com/ruby/prism/issues/2331") diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index f79839984300ea..fe1e8f0d5c22aa 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -5,11 +5,10 @@ exclude(:test_duplicated_when, "unknown") exclude(:test_error_message_encoding, "unknown") exclude(:test_it, "https://github.com/ruby/prism/issues/2323") -exclude(:test_keyword_invalid_name, "unknown") -exclude(:test_keyword_self_reference, "unknown") exclude(:test_numbered_parameter, "unknown") -exclude(:test_optional_self_reference, "unknown") exclude(:test_syntax_error_at_newline, "unknown") exclude(:test_unterminated_heredoc_cr, "unknown") exclude(:test_warn_balanced, "unknown") -exclude(:test_warn_unreachable, "unknown") + +exclude(:test_optional_self_reference, "https://bugs.ruby-lang.org/issues/20478") +exclude(:test_keyword_self_reference, "https://bugs.ruby-lang.org/issues/20478") diff --git a/test/.excludes-prism/TestUnicodeEscape.rb b/test/.excludes-prism/TestUnicodeEscape.rb deleted file mode 100644 index add4911bc2f0aa..00000000000000 --- a/test/.excludes-prism/TestUnicodeEscape.rb +++ /dev/null @@ -1 +0,0 @@ -exclude(:test_fail, "unknown") diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index b8de2ba952cf02..bd6dabf2c978d4 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1259,8 +1259,8 @@ def test_error_def_in_argument assert_syntax_error("def f r:def d; def f 0end", /unexpected/) end; - assert_syntax_error("def\nf(000)end", /^ \^~~/) - assert_syntax_error("def\nf(&0)end", /^ \^/) + assert_syntax_error("def\nf(000)end", /(^|\| ) \^~~/) + assert_syntax_error("def\nf(&0)end", /(^|\| ) \^/) end def test_method_location_in_rescue From fd2876e6a226e144689a15bc3cbc5fe4ac089533 Mon Sep 17 00:00:00 2001 From: KJ Tsanaktsidis Date: Fri, 10 May 2024 10:11:22 +1000 Subject: [PATCH 057/151] Update ASAN docs to refer to Clang 18's release Clang 18 has the bugfix we need, so we no longer need to tell people to compile Clang from source. --- doc/contributing/building_ruby.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index 96cee40cb4b951..38c78e3cca06d5 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -185,7 +185,7 @@ Using the address sanitizer (ASAN) is a great way to detect memory issues. It ca ``` shell ./autogen.sh mkdir build && cd build -../configure CC=clang cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like +../configure CC=clang-18 cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like make ``` The compiled Ruby will now automatically crash with a report and a backtrace if ASAN detects a memory safety issue. To run Ruby's test suite under ASAN, issue the following command. Note that this will take quite a long time (over two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and `SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't spuriously fail with timeouts when in fact they're just slow. @@ -198,7 +198,7 @@ Please note, however, the following caveats! * ASAN will not work properly on any currently released version of Ruby; the necessary support is currently only present on Ruby's master branch (and the whole test suite passes only as of commit [9d0a5148ae062a0481a4a18fbeb9cfd01dc10428](https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428)) * Due to [this bug](https://bugs.ruby-lang.org/issues/20243), Clang generates code for threadlocal variables which doesn't work with M:N threading. Thus, it's necessary to disable M:N threading support at build time for now (with the `-DUSE_MN_THREADS=0` configure argument). -* Currently, ASAN will only work correctly when using a recent head build of LLVM/Clang - it requires [this bugfix](https://github.com/llvm/llvm-project/pull/75290) related to multithreaded `fork`, which is not yet in any released version. See [here](https://llvm.org/docs/CMake.html) for instructions on how to build LLVM/Clang from source (note you will need at least the `clang` and `compiler-rt` projects enabled). Then, you will need to replace `CC=clang` in the instructions with an explicit path to your built Clang binary. +* ASAN will only work when using Clang version 18 or later - it requires [this bugfix](https://github.com/llvm/llvm-project/pull/75290) related to multithreaded `fork`. * ASAN has only been tested so far with Clang on Linux. It may or may not work with other compilers or on other platforms - please file an issue on [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if you run into problems with such configurations (or, to report that they actually work properly!) * In particular, although I have not yet tried it, I have reason to believe ASAN will _not_ work properly on macOS yet - the fix for the multithreaded fork issue was actually reverted for macOS (see [here](https://github.com/llvm/llvm-project/commit/2a03854e4ce9bb1bcd79a211063bc63c4657f92c)). Please open an issue on [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if this is a problem for you. From f53b46e9df2ce538f1fb73d33493feb7bc0b3439 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 02:40:08 +0000 Subject: [PATCH 058/151] Bump ossf/scorecard-action from 2.3.1 to 2.3.3 Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.1 to 2.3.3. - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/0864cf19026789058feabb7e87baa5f140aac736...dc50aa9510b46c811795eb24b2f1ba02a914e534) --- updated-dependencies: - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/scorecards.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index be8d99d89d149b..602902e6a18082 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -37,7 +37,7 @@ jobs: persist-credentials: false - name: 'Run analysis' - uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 with: results_file: results.sarif results_format: sarif From 346f7bf33e4b1faa82c44b48466ad38ae48fd457 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 9 May 2024 15:36:17 -0400 Subject: [PATCH 059/151] [ruby/prism] Fix escaping control+x https://github.com/ruby/prism/commit/0f0b4c1161 --- prism/prism.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index f24f122420e0db..b217b4694fa4fb 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9629,7 +9629,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start)); } - escape_write_byte_encoded(parser, buffer, value); + escape_write_byte_encoded(parser, buffer, escape_byte(value, flags)); } else { pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_HEXADECIMAL); } From 2f915e729ac8c66f4009f4b28a57773923d7e7d1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 9 May 2024 15:40:43 -0400 Subject: [PATCH 060/151] [PRISM] Enable passing test_string --- test/.excludes-prism/TestRegexp.rb | 1 + test/.excludes-prism/TestRubyLiteral.rb | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/test/.excludes-prism/TestRegexp.rb b/test/.excludes-prism/TestRegexp.rb index 9d514236c73eee..5852d870efed6e 100644 --- a/test/.excludes-prism/TestRegexp.rb +++ b/test/.excludes-prism/TestRegexp.rb @@ -1 +1,2 @@ exclude(:test_unescape, "unescapes in regexp missing some bytes") +exclude(:test_match_control_meta_escape, "unescapes in regexp missing some bytes") diff --git a/test/.excludes-prism/TestRubyLiteral.rb b/test/.excludes-prism/TestRubyLiteral.rb index d51295081f6bec..a25e1c47d91cb5 100644 --- a/test/.excludes-prism/TestRubyLiteral.rb +++ b/test/.excludes-prism/TestRubyLiteral.rb @@ -1,2 +1 @@ exclude(:test_dregexp, "x80 should raise syntax error") -exclude(:test_string, "https://github.com/ruby/prism/issues/2331") From 69d0a3b033cfcb998020d54c0e3cec24b5f07b45 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 05:39:07 -0400 Subject: [PATCH 061/151] [ruby/irb] Simplify regexp to account for prism error messages (https://github.com/ruby/irb/pull/954) https://github.com/ruby/irb/commit/e0c29be074 Co-authored-by: Stan Lo --- lib/irb/ruby-lex.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index cfe36be83f7b31..86e340eb05e568 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -230,7 +230,7 @@ def check_code_syntax(code, local_variables:) # example: # ' return :recoverable_error - when /syntax error, unexpected end-of-input/ + when /unexpected end-of-input/ # "syntax error, unexpected end-of-input, expecting keyword_end" # # example: @@ -240,7 +240,7 @@ def check_code_syntax(code, local_variables:) # fuga # end return :recoverable_error - when /syntax error, unexpected keyword_end/ + when /unexpected keyword_end/ # "syntax error, unexpected keyword_end" # # example: @@ -250,7 +250,7 @@ def check_code_syntax(code, local_variables:) # example: # end return :unrecoverable_error - when /syntax error, unexpected '\.'/ + when /unexpected '\.'/ # "syntax error, unexpected '.'" # # example: From c68bb2408829ffdac2465f38a1d040b7f1e1c6aa Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Fri, 10 May 2024 20:40:54 +0900 Subject: [PATCH 062/151] [ruby/irb] Add a new initialization step to validate IRB.conf's values (https://github.com/ruby/irb/pull/953) Currently, users can only find out that they have set a wrong value for IRB configs when the value is used, with opaque error messages like "comparison of Integer with true failed (TypeError)". This commit adds a new initialization step to validate the values of some IRB configs, so that users can find out about the wrong values during the initialization of IRB. https://github.com/ruby/irb/commit/af8ef2948b --- lib/irb/context.rb | 9 +++-- lib/irb/init.rb | 35 +++++++++++++++++ test/irb/test_init.rb | 91 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/lib/irb/context.rb b/lib/irb/context.rb index 5d2ff973280c58..aafce7aadeebfd 100644 --- a/lib/irb/context.rb +++ b/lib/irb/context.rb @@ -73,11 +73,12 @@ def initialize(irb, workspace = nil, input_method = nil) self.prompt_mode = IRB.conf[:PROMPT_MODE] - if IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager) - @irb_name = IRB.conf[:IRB_NAME] - else - @irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s + @irb_name = IRB.conf[:IRB_NAME] + + unless IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager) + @irb_name = @irb_name + "#" + IRB.JobManager.n_jobs.to_s end + self.irb_path = "(" + @irb_name + ")" case input_method diff --git a/lib/irb/init.rb b/lib/irb/init.rb index 355047519c3252..7dc08912ef92ee 100644 --- a/lib/irb/init.rb +++ b/lib/irb/init.rb @@ -52,6 +52,7 @@ def IRB.setup(ap_path, argv: ::ARGV) IRB.init_error IRB.parse_opts(argv: argv) IRB.run_config + IRB.validate_config IRB.load_modules unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]] @@ -427,6 +428,40 @@ def IRB.irbrc_files @irbrc_files end + def IRB.validate_config + conf[:IRB_NAME] = conf[:IRB_NAME].to_s + + irb_rc = conf[:IRB_RC] + unless irb_rc.nil? || irb_rc.respond_to?(:call) + raise_validation_error "IRB.conf[:IRB_RC] should be a callable object. Got #{irb_rc.inspect}." + end + + back_trace_limit = conf[:BACK_TRACE_LIMIT] + unless back_trace_limit.is_a?(Integer) + raise_validation_error "IRB.conf[:BACK_TRACE_LIMIT] should be an integer. Got #{back_trace_limit.inspect}." + end + + prompt = conf[:PROMPT] + unless prompt.is_a?(Hash) + msg = "IRB.conf[:PROMPT] should be a Hash. Got #{prompt.inspect}." + + if prompt.is_a?(Symbol) + msg += " Did you mean to set `IRB.conf[:PROMPT_MODE]`?" + end + + raise_validation_error msg + end + + eval_history = conf[:EVAL_HISTORY] + unless eval_history.nil? || eval_history.is_a?(Integer) + raise_validation_error "IRB.conf[:EVAL_HISTORY] should be an integer. Got #{eval_history.inspect}." + end + end + + def IRB.raise_validation_error(msg) + raise TypeError, msg, @irbrc_files + end + # loading modules def IRB.load_modules for m in @CONF[:LOAD_MODULES] diff --git a/test/irb/test_init.rb b/test/irb/test_init.rb index f11d7398c826e8..64567870126378 100644 --- a/test/irb/test_init.rb +++ b/test/irb/test_init.rb @@ -268,15 +268,94 @@ def with_argv(argv) end end + class ConfigValidationTest < TestCase + def setup + @original_home = ENV["HOME"] + @original_irbrc = ENV["IRBRC"] + # To prevent the test from using the user's .irbrc file + ENV["HOME"] = Dir.mktmpdir + IRB.instance_variable_set(:@existing_rc_name_generators, nil) + super + end + + def teardown + super + ENV["IRBRC"] = @original_irbrc + ENV["HOME"] = @original_home + File.unlink(@irbrc) + end + + def test_irb_name_converts_non_string_values_to_string + assert_no_irb_validation_error(<<~'RUBY') + IRB.conf[:IRB_NAME] = :foo + RUBY + + assert_equal "foo", IRB.conf[:IRB_NAME] + end + + def test_irb_rc_name_only_takes_callable_objects + assert_irb_validation_error(<<~'RUBY', "IRB.conf[:IRB_RC] should be a callable object. Got :foo.") + IRB.conf[:IRB_RC] = :foo + RUBY + end + + def test_back_trace_limit_only_accepts_integers + assert_irb_validation_error(<<~'RUBY', "IRB.conf[:BACK_TRACE_LIMIT] should be an integer. Got \"foo\".") + IRB.conf[:BACK_TRACE_LIMIT] = "foo" + RUBY + end + + def test_prompt_only_accepts_hash + assert_irb_validation_error(<<~'RUBY', "IRB.conf[:PROMPT] should be a Hash. Got \"foo\".") + IRB.conf[:PROMPT] = "foo" + RUBY + end + + def test_eval_history_only_accepts_integers + assert_irb_validation_error(<<~'RUBY', "IRB.conf[:EVAL_HISTORY] should be an integer. Got \"foo\".") + IRB.conf[:EVAL_HISTORY] = "foo" + RUBY + end + + private + + def assert_irb_validation_error(rc_content, error_message) + write_rc rc_content + + assert_raise_with_message(TypeError, error_message) do + IRB.setup(__FILE__) + end + end + + def assert_no_irb_validation_error(rc_content) + write_rc rc_content + + assert_nothing_raised do + IRB.setup(__FILE__) + end + end + + def write_rc(content) + @irbrc = Tempfile.new('irbrc') + @irbrc.write(content) + @irbrc.close + ENV['IRBRC'] = @irbrc.path + end + end + class InitIntegrationTest < IntegrationTestCase - def test_load_error_in_rc_file_is_warned - write_rc <<~'IRBRC' - require "file_that_does_not_exist" - IRBRC + def setup + super write_ruby <<~'RUBY' binding.irb RUBY + end + + def test_load_error_in_rc_file_is_warned + write_rc <<~'IRBRC' + require "file_that_does_not_exist" + IRBRC output = run_ruby_file do type "'foobar'" @@ -293,10 +372,6 @@ def test_normal_errors_in_rc_file_is_warned raise "I'm an error" IRBRC - write_ruby <<~'RUBY' - binding.irb - RUBY - output = run_ruby_file do type "'foobar'" type "exit" From 3f664c3738fe25227b9d990064e4b5fda2d84c39 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 09:27:59 -0400 Subject: [PATCH 063/151] [ruby/prism] Prism::CallNode#full_message_loc https://github.com/ruby/prism/commit/fa6fe9be84 --- lib/prism/node_ext.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index d4c9b21079e6ee..13830dad3d2aed 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -286,4 +286,19 @@ def signature names end end + + class CallNode < Node + # When a call node has the attribute_write flag set, it means that the call + # is using the attribute write syntax. This is either a method call to []= + # or a method call to a method that ends with =. Either way, the = sign is + # present in the source. + # + # Prism returns the message_loc _without_ the = sign attached, because there + # can be any amount of space between the message and the = sign. However, + # sometimes you want the location of the full message including the inner + # space and the = sign. This method provides that. + def full_message_loc + attribute_write? ? message_loc&.adjoin("=") : message_loc + end + end end From 2bc309e7f31222d626bb0e1acef2c8b2b3f9d32c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 09:45:51 -0400 Subject: [PATCH 064/151] [ruby/prism] Fix RBS outside of prism https://github.com/ruby/prism/commit/ee73ad757f --- lib/prism/prism.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index d23b6a65cb2a4c..73ec01251f0128 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -121,6 +121,7 @@ Gem::Specification.new do |spec| "sig/prism/dot_visitor.rbs", "sig/prism/dsl.rbs", "sig/prism/inspect_visitor.rbs", + "sig/prism/lex_compat.rbs", "sig/prism/mutation_compiler.rbs", "sig/prism/node_ext.rbs", "sig/prism/node.rbs", From 34e0b5b2d419840f4e97cdf8fffcbc3578a5f7a3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 10:29:12 -0400 Subject: [PATCH 065/151] [ruby/prism] Fix tapioca require order https://github.com/ruby/prism/commit/15bf727881 --- lib/prism/parse_result/comments.rb | 2 +- lib/prism/parse_result/newlines.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index f8f74d25032912..3fa0603d74ce71 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Prism - class ParseResult + class ParseResult < Result # When we've parsed the source, we have both the syntax tree and the list of # comments that we found in the source. This class is responsible for # walking the tree and finding the nearest location to attach each comment. diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index 927c17fe2f7064..4a8151cc09a090 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true module Prism - class ParseResult + class ParseResult < Result # The :line tracepoint event gets fired whenever the Ruby VM encounters an # expression on a new line. The types of expressions that can trigger this # event are: From 2e4466454721012b3ba27f262b3e5dd6e3d393b0 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 10:19:11 -0400 Subject: [PATCH 066/151] [ruby/prism] operator rename https://github.com/ruby/prism/commit/b5e47f5c42 --- lib/prism/desugar_compiler.rb | 8 +- lib/prism/node_ext.rb | 155 +++++++++++++-- lib/prism/translation/parser/compiler.rb | 178 +++++++++++++++--- lib/prism/translation/ripper.rb | 32 ++-- lib/prism/translation/ruby_parser.rb | 18 +- prism/config.yml | 32 ++-- prism/prism.c | 32 ++-- test/prism/snapshots/arrays.txt | 20 +- test/prism/snapshots/blocks.txt | 4 +- test/prism/snapshots/boolean_operators.txt | 4 +- test/prism/snapshots/defined.txt | 4 +- .../seattlerb/const_op_asgn_and1.txt | 4 +- .../snapshots/seattlerb/index_0_opasgn.txt | 4 +- .../seattlerb/messy_op_asgn_lineno.txt | 4 +- ..._asgn_primary_colon_const_command_call.txt | 4 +- .../op_asgn_primary_colon_identifier1.txt | 4 +- ..._primary_colon_identifier_command_call.txt | 4 +- .../seattlerb/parse_line_defn_complex.txt | 4 +- .../seattlerb/parse_line_op_asgn.txt | 4 +- .../snapshots/seattlerb/safe_op_asgn.txt | 4 +- .../unparser/corpus/literal/opasgn.txt | 64 +++---- .../unparser/corpus/semantic/opasgn.txt | 4 +- .../snapshots/whitequark/const_op_asgn.txt | 12 +- test/prism/snapshots/whitequark/op_asgn.txt | 12 +- .../snapshots/whitequark/op_asgn_cmd.txt | 16 +- .../snapshots/whitequark/op_asgn_index.txt | 4 +- .../whitequark/op_asgn_index_cmd.txt | 4 +- .../whitequark/rescue_mod_op_assign.txt | 4 +- .../snapshots/whitequark/ruby_bug_12402.txt | 40 ++-- .../snapshots/whitequark/ruby_bug_12669.txt | 16 +- .../snapshots/whitequark/var_op_asgn.txt | 16 +- .../snapshots/whitequark/var_op_asgn_cmd.txt | 4 +- 32 files changed, 488 insertions(+), 231 deletions(-) diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb index 9b62c00df32213..de02445149302c 100644 --- a/lib/prism/desugar_compiler.rb +++ b/lib/prism/desugar_compiler.rb @@ -73,7 +73,7 @@ def initialize(node, source, read_class, write_class, *arguments) # Desugar `x += y` to `x = x + y` def compile - operator_loc = node.operator_loc.chop + binary_operator_loc = node.binary_operator_loc.chop write_class.new( source, @@ -84,15 +84,15 @@ def compile 0, read_class.new(source, *arguments, node.name_loc), nil, - operator_loc.slice.to_sym, - operator_loc, + binary_operator_loc.slice.to_sym, + binary_operator_loc, nil, ArgumentsNode.new(source, 0, [node.value], node.value.location), nil, nil, node.location ), - node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1), + node.binary_operator_loc.copy(start_offset: node.binary_operator_loc.end_offset - 1, length: 1), node.location ) end diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb index 13830dad3d2aed..ceec76b8d6ad50 100644 --- a/lib/prism/node_ext.rb +++ b/lib/prism/node_ext.rb @@ -3,6 +3,17 @@ # Here we are reopening the prism module to provide methods on nodes that aren't # templated and are meant as convenience methods. module Prism + class Node + def deprecated(*replacements) # :nodoc: + suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } + warn(<<~MSG, category: :deprecated) + [deprecation]: #{self.class}##{caller_locations(1, 1)[0].label} is deprecated \ + and will be removed in the next major version. Use #{suggest.join("/")} instead. + #{(caller(1, 3) || []).join("\n")} + MSG + end + end + module RegularExpressionOptions # :nodoc: # Returns a numeric value that represents the flags that were used to create # the regular expression. @@ -168,13 +179,7 @@ def full_name # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. def child - warn(<<~MSG, category: :deprecated) - DEPRECATED: ConstantPathNode#child is deprecated and will be removed \ - in the next major version. Use \ - ConstantPathNode#name/ConstantPathNode#name_loc instead. Called from \ - #{caller(1, 1)&.first}. - MSG - + deprecated("name", "name_loc") name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location) end end @@ -210,13 +215,7 @@ def full_name # constant read or a missing node. To not cause a breaking change, we # continue to supply that API. def child - warn(<<~MSG, category: :deprecated) - DEPRECATED: ConstantPathTargetNode#child is deprecated and will be \ - removed in the next major version. Use \ - ConstantPathTargetNode#name/ConstantPathTargetNode#name_loc instead. \ - Called from #{caller(1, 1)&.first}. - MSG - + deprecated("name", "name_loc") name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location) end end @@ -301,4 +300,132 @@ def full_message_loc attribute_write? ? message_loc&.adjoin("=") : message_loc end end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end end diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb index c3116133889d80..a6c3118efd1a93 100644 --- a/lib/prism/translation/parser/compiler.rb +++ b/lib/prism/translation/parser/compiler.rb @@ -328,18 +328,48 @@ def visit_call_operator_write_node(node) [], nil ), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo.bar &&= baz # ^^^^^^^^^^^^^^^ - alias visit_call_and_write_node visit_call_operator_write_node + def visit_call_and_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo.bar ||= baz # ^^^^^^^^^^^^^^^ - alias visit_call_or_write_node visit_call_operator_write_node + def visit_call_or_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo.bar, = 1 # ^^^^^^^ @@ -419,18 +449,30 @@ def visit_class_variable_write_node(node) def visit_class_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.cvar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # @@foo &&= bar # ^^^^^^^^^^^^^ - alias visit_class_variable_and_write_node visit_class_variable_operator_write_node + def visit_class_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @@foo ||= bar # ^^^^^^^^^^^^^ - alias visit_class_variable_or_write_node visit_class_variable_operator_write_node + def visit_class_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @@foo, = bar # ^^^^^ @@ -458,18 +500,30 @@ def visit_constant_write_node(node) def visit_constant_operator_write_node(node) builder.op_assign( builder.assignable(builder.const([node.name, srange(node.name_loc)])), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # Foo &&= bar # ^^^^^^^^^^^^ - alias visit_constant_and_write_node visit_constant_operator_write_node + def visit_constant_and_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo ||= bar # ^^^^^^^^^^^^ - alias visit_constant_or_write_node visit_constant_operator_write_node + def visit_constant_or_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo, = bar # ^^^ @@ -512,18 +566,30 @@ def visit_constant_path_write_node(node) def visit_constant_path_operator_write_node(node) builder.op_assign( builder.assignable(visit(node.target)), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # Foo::Bar &&= baz # ^^^^^^^^^^^^^^^^ - alias visit_constant_path_and_write_node visit_constant_path_operator_write_node + def visit_constant_path_and_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo::Bar ||= baz # ^^^^^^^^^^^^^^^^ - alias visit_constant_path_or_write_node visit_constant_path_operator_write_node + def visit_constant_path_or_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # Foo::Bar, = baz # ^^^^^^^^ @@ -711,18 +777,30 @@ def visit_global_variable_write_node(node) def visit_global_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.gvar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # $foo &&= bar # ^^^^^^^^^^^^ - alias visit_global_variable_and_write_node visit_global_variable_operator_write_node + def visit_global_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # $foo ||= bar # ^^^^^^^^^^^^ - alias visit_global_variable_or_write_node visit_global_variable_operator_write_node + def visit_global_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # $foo, = bar # ^^^^ @@ -857,18 +935,46 @@ def visit_index_operator_write_node(node) visit_all(arguments), token(node.closing_loc) ), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo[bar] &&= baz # ^^^^^^^^^^^^^^^^ - alias visit_index_and_write_node visit_index_operator_write_node + def visit_index_and_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo[bar] ||= baz # ^^^^^^^^^^^^^^^^ - alias visit_index_or_write_node visit_index_operator_write_node + def visit_index_or_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo[bar], = 1 # ^^^^^^^^ @@ -902,18 +1008,30 @@ def visit_instance_variable_write_node(node) def visit_instance_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.ivar(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # @foo &&= bar # ^^^^^^^^^^^^ - alias visit_instance_variable_and_write_node visit_instance_variable_operator_write_node + def visit_instance_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @foo ||= bar # ^^^^^^^^^^^^ - alias visit_instance_variable_or_write_node visit_instance_variable_operator_write_node + def visit_instance_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # @foo, = bar # ^^^^ @@ -1108,18 +1226,30 @@ def visit_local_variable_write_node(node) def visit_local_variable_operator_write_node(node) builder.op_assign( builder.assignable(builder.ident(token(node.name_loc))), - [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], visit(node.value) ) end # foo &&= bar # ^^^^^^^^^^^ - alias visit_local_variable_and_write_node visit_local_variable_operator_write_node + def visit_local_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo ||= bar # ^^^^^^^^^^^ - alias visit_local_variable_or_write_node visit_local_variable_operator_write_node + def visit_local_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end # foo, = bar # ^^^ diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index d226bb58df73db..68f658565d145d 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -1181,8 +1181,8 @@ def visit_call_operator_write_node(node) bounds(node.location) target = on_field(receiver, call_operator, message) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1339,8 +1339,8 @@ def visit_class_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_cvar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1409,8 +1409,8 @@ def visit_constant_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_const(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1510,8 +1510,8 @@ def visit_constant_path_operator_write_node(node) target = visit_constant_path_write_node_target(node.target) value = visit(node.value) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1802,8 +1802,8 @@ def visit_global_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_gvar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -1983,8 +1983,8 @@ def visit_index_operator_write_node(node) bounds(node.location) target = on_aref_field(receiver, arguments) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -2059,8 +2059,8 @@ def visit_instance_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ivar(node.name.to_s)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) @@ -2337,8 +2337,8 @@ def visit_local_variable_operator_write_node(node) bounds(node.name_loc) target = on_var_field(on_ident(node.name_loc.slice)) - bounds(node.operator_loc) - operator = on_op("#{node.operator}=") + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") value = visit_write_value(node.value) bounds(node.location) diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index c6f741c8e538ca..d01a762a033b24 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -271,9 +271,9 @@ def visit_call_node(node) # ^^^^^^^^^^^^^^^ def visit_call_operator_write_node(node) if op_asgn?(node) - s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.operator) + s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator) else - s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.operator, visit_write_value(node.value)) + s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.binary_operator, visit_write_value(node.value)) end end @@ -372,7 +372,7 @@ def visit_class_variable_write_node(node) # @@foo += bar # ^^^^^^^^^^^^ def visit_class_variable_operator_write_node(node) - s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.operator, visit_write_value(node.value))) + s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value))) end # @@foo &&= bar @@ -417,7 +417,7 @@ def visit_constant_write_node(node) # Foo += bar # ^^^^^^^^^^^ def visit_constant_operator_write_node(node) - s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.operator, visit_write_value(node.value))) + s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value))) end # Foo &&= bar @@ -460,7 +460,7 @@ def visit_constant_path_write_node(node) # Foo::Bar += baz # ^^^^^^^^^^^^^^^ def visit_constant_path_operator_write_node(node) - s(node, :op_asgn, visit(node.target), node.operator, visit_write_value(node.value)) + s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value)) end # Foo::Bar &&= baz @@ -627,7 +627,7 @@ def visit_global_variable_write_node(node) # $foo += bar # ^^^^^^^^^^^ def visit_global_variable_operator_write_node(node) - s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.operator, visit(node.value))) + s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value))) end # $foo &&= bar @@ -719,7 +719,7 @@ def visit_index_operator_write_node(node) arglist << visit(node.block) if !node.block.nil? end - s(node, :op_asgn1, visit(node.receiver), arglist, node.operator, visit_write_value(node.value)) + s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value)) end # foo[bar] &&= baz @@ -775,7 +775,7 @@ def visit_instance_variable_write_node(node) # @foo += bar # ^^^^^^^^^^^ def visit_instance_variable_operator_write_node(node) - s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.operator, visit_write_value(node.value))) + s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value))) end # @foo &&= bar @@ -960,7 +960,7 @@ def visit_local_variable_write_node(node) # foo += bar # ^^^^^^^^^^ def visit_local_variable_operator_write_node(node) - s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.operator, visit_write_value(node.value))) + s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value))) end # foo &&= bar diff --git a/prism/config.yml b/prism/config.yml index 8b4ffad065ce42..eb22d5730110bd 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -1212,9 +1212,9 @@ nodes: type: constant - name: write_name type: constant - - name: operator + - name: binary_operator type: constant - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node @@ -1370,11 +1370,11 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + - name: binary_operator type: constant comment: | Represents assigning to a class variable using an operator that isn't `=`. @@ -1480,11 +1480,11 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + - name: binary_operator type: constant comment: | Represents assigning to a constant using an operator that isn't `=`. @@ -1568,11 +1568,11 @@ nodes: - name: target type: node kind: ConstantPathNode - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + - name: binary_operator type: constant comment: | Represents assigning to a constant path using an operator that isn't `=`. @@ -1939,11 +1939,11 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + - name: binary_operator type: constant comment: | Represents assigning to a global variable using an operator that isn't `=`. @@ -2275,9 +2275,9 @@ nodes: type: location - name: block type: node? - - name: operator + - name: binary_operator type: constant - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node @@ -2363,11 +2363,11 @@ nodes: type: constant - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - - name: operator + - name: binary_operator type: constant comment: | Represents assigning to an instance variable using an operator that isn't `=`. @@ -2643,13 +2643,13 @@ nodes: fields: - name: name_loc type: location - - name: operator_loc + - name: binary_operator_loc type: location - name: value type: node - name: name type: constant - - name: operator + - name: binary_operator type: constant - name: depth type: uint32 diff --git a/prism/prism.c b/prism/prism.c index b217b4694fa4fb..b517aa959e15f5 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -3080,8 +3080,8 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .message_loc = target->message_loc, .read_name = 0, .write_name = target->name, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3119,8 +3119,8 @@ pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, .arguments = target->arguments, .closing_loc = target->closing_loc, .block = target->block, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value }; @@ -3464,9 +3464,9 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -3580,9 +3580,9 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat } }, .target = target, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -3707,9 +3707,9 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -4560,9 +4560,9 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta }, .name = pm_global_variable_write_name(parser, target), .name_loc = target->location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -5068,9 +5068,9 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance }, .name = target->name, .name_loc = target->base.location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1) }; return node; @@ -5664,10 +5664,10 @@ pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *tar } }, .name_loc = target->location, - .operator_loc = PM_LOCATION_TOKEN_VALUE(operator), + .binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator), .value = value, .name = name, - .operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), + .binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1), .depth = depth }; diff --git a/test/prism/snapshots/arrays.txt b/test/prism/snapshots/arrays.txt index e8e53aacb95030..90a4d8f3bbcce4 100644 --- a/test/prism/snapshots/arrays.txt +++ b/test/prism/snapshots/arrays.txt @@ -960,8 +960,8 @@ │ ├── arguments: ∅ │ ├── closing_loc: (84,4)-(84,5) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (84,6)-(84,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (84,6)-(84,8) = "+=" │ └── value: │ @ IntegerNode (location: (84,9)-(84,10)) │ ├── flags: decimal @@ -1040,8 +1040,8 @@ │ ├── arguments: ∅ │ ├── closing_loc: (90,8)-(90,9) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (90,10)-(90,12) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (90,10)-(90,12) = "+=" │ └── value: │ @ IntegerNode (location: (90,13)-(90,14)) │ ├── flags: decimal @@ -1143,8 +1143,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (96,7)-(96,8) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (96,9)-(96,11) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (96,9)-(96,11) = "+=" │ └── value: │ @ IntegerNode (location: (96,12)-(96,13)) │ ├── flags: decimal @@ -1262,8 +1262,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (102,11)-(102,12) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (102,13)-(102,15) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (102,13)-(102,15) = "+=" │ └── value: │ @ IntegerNode (location: (102,16)-(102,17)) │ ├── flags: decimal @@ -1633,8 +1633,8 @@ │ │ │ └── expression: ∅ │ │ ├── closing_loc: (116,13)-(116,14) = "]" │ │ ├── block: ∅ - │ │ ├── operator: :+ - │ │ ├── operator_loc: (116,15)-(116,17) = "+=" + │ │ ├── binary_operator: :+ + │ │ ├── binary_operator_loc: (116,15)-(116,17) = "+=" │ │ └── value: │ │ @ IntegerNode (location: (116,18)-(116,19)) │ │ ├── flags: decimal diff --git a/test/prism/snapshots/blocks.txt b/test/prism/snapshots/blocks.txt index 0b1ec52e38bb1e..1c996ebd09ce07 100644 --- a/test/prism/snapshots/blocks.txt +++ b/test/prism/snapshots/blocks.txt @@ -158,13 +158,13 @@ │ │ └── body: (length: 1) │ │ └── @ LocalVariableOperatorWriteNode (location: (7,24)-(7,33)) │ │ ├── name_loc: (7,24)-(7,28) = "memo" - │ │ ├── operator_loc: (7,29)-(7,31) = "+=" + │ │ ├── binary_operator_loc: (7,29)-(7,31) = "+=" │ │ ├── value: │ │ │ @ LocalVariableReadNode (location: (7,32)-(7,33)) │ │ │ ├── name: :x │ │ │ └── depth: 0 │ │ ├── name: :memo - │ │ ├── operator: :+ + │ │ ├── binary_operator: :+ │ │ └── depth: 0 │ ├── opening_loc: (7,12)-(7,13) = "{" │ └── closing_loc: (7,34)-(7,35) = "}" diff --git a/test/prism/snapshots/boolean_operators.txt b/test/prism/snapshots/boolean_operators.txt index ace8047e18d62a..3bf33430c9b145 100644 --- a/test/prism/snapshots/boolean_operators.txt +++ b/test/prism/snapshots/boolean_operators.txt @@ -21,7 +21,7 @@ │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,6)) │ ├── name_loc: (3,0)-(3,1) = "a" - │ ├── operator_loc: (3,2)-(3,4) = "+=" + │ ├── binary_operator_loc: (3,2)-(3,4) = "+=" │ ├── value: │ │ @ CallNode (location: (3,5)-(3,6)) │ │ ├── flags: variable_call, ignore_visibility @@ -34,7 +34,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 └── @ LocalVariableOrWriteNode (location: (5,0)-(5,7)) ├── name_loc: (5,0)-(5,1) = "a" diff --git a/test/prism/snapshots/defined.txt b/test/prism/snapshots/defined.txt index 53a5081811c42d..c60173ff37146f 100644 --- a/test/prism/snapshots/defined.txt +++ b/test/prism/snapshots/defined.txt @@ -28,13 +28,13 @@ │ ├── value: │ │ @ LocalVariableOperatorWriteNode (location: (3,9)-(3,15)) │ │ ├── name_loc: (3,9)-(3,10) = "x" - │ │ ├── operator_loc: (3,11)-(3,13) = "%=" + │ │ ├── binary_operator_loc: (3,11)-(3,13) = "%=" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,14)-(3,15)) │ │ │ ├── flags: decimal │ │ │ └── value: 2 │ │ ├── name: :x - │ │ ├── operator: :% + │ │ ├── binary_operator: :% │ │ └── depth: 0 │ ├── rparen_loc: (3,15)-(3,16) = ")" │ └── keyword_loc: (3,0)-(3,8) = "defined?" diff --git a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt index b5acfa1d8bc3fb..f9792aebb364fa 100644 --- a/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt +++ b/test/prism/snapshots/seattlerb/const_op_asgn_and1.txt @@ -10,9 +10,9 @@ │ ├── name: :X │ ├── delimiter_loc: (1,0)-(1,2) = "::" │ └── name_loc: (1,2)-(1,3) = "X" - ├── operator_loc: (1,4)-(1,6) = "&=" + ├── binary_operator_loc: (1,4)-(1,6) = "&=" ├── value: │ @ IntegerNode (location: (1,7)-(1,8)) │ ├── flags: decimal │ └── value: 1 - └── operator: :& + └── binary_operator: :& diff --git a/test/prism/snapshots/seattlerb/index_0_opasgn.txt b/test/prism/snapshots/seattlerb/index_0_opasgn.txt index 239a5492535b8a..322eae9907a29b 100644 --- a/test/prism/snapshots/seattlerb/index_0_opasgn.txt +++ b/test/prism/snapshots/seattlerb/index_0_opasgn.txt @@ -21,8 +21,8 @@ ├── arguments: ∅ ├── closing_loc: (1,2)-(1,3) = "]" ├── block: ∅ - ├── operator: :+ - ├── operator_loc: (1,4)-(1,6) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,4)-(1,6) = "+=" └── value: @ CallNode (location: (1,7)-(1,8)) ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt b/test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt index 92373aeeafbbe1..edef23044a6d1c 100644 --- a/test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt +++ b/test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt @@ -27,7 +27,7 @@ │ │ │ ├── name: :C │ │ │ ├── delimiter_loc: (1,4)-(1,6) = "::" │ │ │ └── name_loc: (1,6)-(1,7) = "C" - │ │ ├── operator_loc: (1,8)-(1,10) = "*=" + │ │ ├── binary_operator_loc: (1,8)-(1,10) = "*=" │ │ ├── value: │ │ │ @ CallNode (location: (1,11)-(1,14)) │ │ │ ├── flags: ignore_visibility @@ -52,7 +52,7 @@ │ │ │ │ └── block: ∅ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ - │ │ └── operator: :* + │ │ └── binary_operator: :* │ ├── opening_loc: (1,2)-(1,3) = "(" │ └── closing_loc: (1,14)-(1,15) = ")" ├── closing_loc: ∅ diff --git a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt index e0e8c5b3e39084..523ccde4552c2f 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt @@ -12,7 +12,7 @@ │ ├── name: :B │ ├── delimiter_loc: (1,1)-(1,3) = "::" │ └── name_loc: (1,3)-(1,4) = "B" - ├── operator_loc: (1,5)-(1,7) = "*=" + ├── binary_operator_loc: (1,5)-(1,7) = "*=" ├── value: │ @ CallNode (location: (1,8)-(1,11)) │ ├── flags: ignore_visibility @@ -37,4 +37,4 @@ │ │ └── block: ∅ │ ├── closing_loc: ∅ │ └── block: ∅ - └── operator: :* + └── binary_operator: :* diff --git a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt index 0daadcf6ff6213..b9d00edc30656e 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt @@ -12,8 +12,8 @@ ├── message_loc: (1,3)-(1,4) = "b" ├── read_name: :b ├── write_name: :b= - ├── operator: :+ - ├── operator_loc: (1,5)-(1,7) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,5)-(1,7) = "+=" └── value: @ IntegerNode (location: (1,8)-(1,9)) ├── flags: decimal diff --git a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt index ea8603165b01c1..c12ea3983ce6f0 100644 --- a/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt +++ b/test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt @@ -12,8 +12,8 @@ ├── message_loc: (1,3)-(1,4) = "b" ├── read_name: :b ├── write_name: :b= - ├── operator: :* - ├── operator_loc: (1,5)-(1,7) = "*=" + ├── binary_operator: :* + ├── binary_operator_loc: (1,5)-(1,7) = "*=" └── value: @ CallNode (location: (1,8)-(1,11)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt index 8199eb24490984..84eef70b25b226 100644 --- a/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt +++ b/test/prism/snapshots/seattlerb/parse_line_defn_complex.txt @@ -40,13 +40,13 @@ │ │ └── block: ∅ │ ├── @ LocalVariableOperatorWriteNode (location: (3,2)-(3,8)) │ │ ├── name_loc: (3,2)-(3,3) = "y" - │ │ ├── operator_loc: (3,4)-(3,6) = "*=" + │ │ ├── binary_operator_loc: (3,4)-(3,6) = "*=" │ │ ├── value: │ │ │ @ IntegerNode (location: (3,7)-(3,8)) │ │ │ ├── flags: decimal │ │ │ └── value: 2 │ │ ├── name: :y - │ │ ├── operator: :* + │ │ ├── binary_operator: :* │ │ └── depth: 0 │ └── @ ReturnNode (location: (4,2)-(4,10)) │ ├── flags: redundant diff --git a/test/prism/snapshots/seattlerb/parse_line_op_asgn.txt b/test/prism/snapshots/seattlerb/parse_line_op_asgn.txt index 5c2eb2da3cbe07..d113f2af9d401a 100644 --- a/test/prism/snapshots/seattlerb/parse_line_op_asgn.txt +++ b/test/prism/snapshots/seattlerb/parse_line_op_asgn.txt @@ -5,7 +5,7 @@ └── body: (length: 2) ├── @ LocalVariableOperatorWriteNode (location: (1,6)-(2,11)) │ ├── name_loc: (1,6)-(1,9) = "foo" - │ ├── operator_loc: (1,10)-(1,12) = "+=" + │ ├── binary_operator_loc: (1,10)-(1,12) = "+=" │ ├── value: │ │ @ CallNode (location: (2,8)-(2,11)) │ │ ├── flags: variable_call, ignore_visibility @@ -18,7 +18,7 @@ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ │ ├── name: :foo - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 └── @ CallNode (location: (3,6)-(3,9)) ├── flags: variable_call, ignore_visibility diff --git a/test/prism/snapshots/seattlerb/safe_op_asgn.txt b/test/prism/snapshots/seattlerb/safe_op_asgn.txt index 7a9fd2b7f71206..ebcedd6b5e09a1 100644 --- a/test/prism/snapshots/seattlerb/safe_op_asgn.txt +++ b/test/prism/snapshots/seattlerb/safe_op_asgn.txt @@ -20,8 +20,8 @@ ├── message_loc: (1,3)-(1,4) = "b" ├── read_name: :b ├── write_name: :b= - ├── operator: :+ - ├── operator_loc: (1,5)-(1,7) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,5)-(1,7) = "+=" └── value: @ CallNode (location: (1,8)-(1,11)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt index 8dc084963819b9..0761b47348b692 100644 --- a/test/prism/snapshots/unparser/corpus/literal/opasgn.txt +++ b/test/prism/snapshots/unparser/corpus/literal/opasgn.txt @@ -5,53 +5,53 @@ └── body: (length: 24) ├── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,6)) │ ├── name_loc: (1,0)-(1,1) = "a" - │ ├── operator_loc: (1,2)-(1,4) = "+=" + │ ├── binary_operator_loc: (1,2)-(1,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (1,5)-(1,6)) │ │ ├── flags: decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (2,0)-(2,6)) │ ├── name_loc: (2,0)-(2,1) = "a" - │ ├── operator_loc: (2,2)-(2,4) = "-=" + │ ├── binary_operator_loc: (2,2)-(2,4) = "-=" │ ├── value: │ │ @ IntegerNode (location: (2,5)-(2,6)) │ │ ├── flags: decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :- + │ ├── binary_operator: :- │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,7)) │ ├── name_loc: (3,0)-(3,1) = "a" - │ ├── operator_loc: (3,2)-(3,5) = "**=" + │ ├── binary_operator_loc: (3,2)-(3,5) = "**=" │ ├── value: │ │ @ IntegerNode (location: (3,6)-(3,7)) │ │ ├── flags: decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :** + │ ├── binary_operator: :** │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (4,0)-(4,6)) │ ├── name_loc: (4,0)-(4,1) = "a" - │ ├── operator_loc: (4,2)-(4,4) = "*=" + │ ├── binary_operator_loc: (4,2)-(4,4) = "*=" │ ├── value: │ │ @ IntegerNode (location: (4,5)-(4,6)) │ │ ├── flags: decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :* + │ ├── binary_operator: :* │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (5,0)-(5,6)) │ ├── name_loc: (5,0)-(5,1) = "a" - │ ├── operator_loc: (5,2)-(5,4) = "/=" + │ ├── binary_operator_loc: (5,2)-(5,4) = "/=" │ ├── value: │ │ @ IntegerNode (location: (5,5)-(5,6)) │ │ ├── flags: decimal │ │ └── value: 2 │ ├── name: :a - │ ├── operator: :/ + │ ├── binary_operator: :/ │ └── depth: 0 ├── @ LocalVariableAndWriteNode (location: (6,0)-(6,7)) │ ├── name_loc: (6,0)-(6,1) = "a" @@ -162,8 +162,8 @@ │ ├── message_loc: (10,2)-(10,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :+ - │ ├── operator_loc: (10,4)-(10,6) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (10,4)-(10,6) = "+=" │ └── value: │ @ IntegerNode (location: (10,7)-(10,8)) │ ├── flags: decimal @@ -178,8 +178,8 @@ │ ├── message_loc: (11,2)-(11,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :- - │ ├── operator_loc: (11,4)-(11,6) = "-=" + │ ├── binary_operator: :- + │ ├── binary_operator_loc: (11,4)-(11,6) = "-=" │ └── value: │ @ IntegerNode (location: (11,7)-(11,8)) │ ├── flags: decimal @@ -194,8 +194,8 @@ │ ├── message_loc: (12,2)-(12,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :** - │ ├── operator_loc: (12,4)-(12,7) = "**=" + │ ├── binary_operator: :** + │ ├── binary_operator_loc: (12,4)-(12,7) = "**=" │ └── value: │ @ IntegerNode (location: (12,8)-(12,9)) │ ├── flags: decimal @@ -210,8 +210,8 @@ │ ├── message_loc: (13,2)-(13,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :* - │ ├── operator_loc: (13,4)-(13,6) = "*=" + │ ├── binary_operator: :* + │ ├── binary_operator_loc: (13,4)-(13,6) = "*=" │ └── value: │ @ IntegerNode (location: (13,7)-(13,8)) │ ├── flags: decimal @@ -226,8 +226,8 @@ │ ├── message_loc: (14,2)-(14,3) = "b" │ ├── read_name: :b │ ├── write_name: :b= - │ ├── operator: :/ - │ ├── operator_loc: (14,4)-(14,6) = "/=" + │ ├── binary_operator: :/ + │ ├── binary_operator_loc: (14,4)-(14,6) = "/=" │ └── value: │ @ IntegerNode (location: (14,7)-(14,8)) │ ├── flags: decimal @@ -293,8 +293,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (17,3)-(17,4) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (17,5)-(17,7) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (17,5)-(17,7) = "+=" │ └── value: │ @ IntegerNode (location: (17,8)-(17,9)) │ ├── flags: decimal @@ -323,8 +323,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (18,3)-(18,4) = "]" │ ├── block: ∅ - │ ├── operator: :- - │ ├── operator_loc: (18,5)-(18,7) = "-=" + │ ├── binary_operator: :- + │ ├── binary_operator_loc: (18,5)-(18,7) = "-=" │ └── value: │ @ IntegerNode (location: (18,8)-(18,9)) │ ├── flags: decimal @@ -353,8 +353,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (19,3)-(19,4) = "]" │ ├── block: ∅ - │ ├── operator: :** - │ ├── operator_loc: (19,5)-(19,8) = "**=" + │ ├── binary_operator: :** + │ ├── binary_operator_loc: (19,5)-(19,8) = "**=" │ └── value: │ @ IntegerNode (location: (19,9)-(19,10)) │ ├── flags: decimal @@ -383,8 +383,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (20,3)-(20,4) = "]" │ ├── block: ∅ - │ ├── operator: :* - │ ├── operator_loc: (20,5)-(20,7) = "*=" + │ ├── binary_operator: :* + │ ├── binary_operator_loc: (20,5)-(20,7) = "*=" │ └── value: │ @ IntegerNode (location: (20,8)-(20,9)) │ ├── flags: decimal @@ -413,8 +413,8 @@ │ │ └── block: ∅ │ ├── closing_loc: (21,3)-(21,4) = "]" │ ├── block: ∅ - │ ├── operator: :/ - │ ├── operator_loc: (21,5)-(21,7) = "/=" + │ ├── binary_operator: :/ + │ ├── binary_operator_loc: (21,5)-(21,7) = "/=" │ └── value: │ @ IntegerNode (location: (21,8)-(21,9)) │ ├── flags: decimal @@ -501,8 +501,8 @@ ├── message_loc: (24,4)-(24,5) = "A" ├── read_name: :A ├── write_name: :A= - ├── operator: :+ - ├── operator_loc: (24,6)-(24,8) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (24,6)-(24,8) = "+=" └── value: @ IntegerNode (location: (24,9)-(24,10)) ├── flags: decimal diff --git a/test/prism/snapshots/unparser/corpus/semantic/opasgn.txt b/test/prism/snapshots/unparser/corpus/semantic/opasgn.txt index e100dd8ecb7fe3..7dd26a38dc2acb 100644 --- a/test/prism/snapshots/unparser/corpus/semantic/opasgn.txt +++ b/test/prism/snapshots/unparser/corpus/semantic/opasgn.txt @@ -44,8 +44,8 @@ │ └── closing_loc: (1,10)-(1,11) = "\"" ├── closing_loc: (1,11)-(1,12) = "]" ├── block: ∅ - ├── operator: :+ - ├── operator_loc: (1,13)-(1,15) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,13)-(1,15) = "+=" └── value: @ InterpolatedStringNode (location: (1,16)-(1,25)) ├── flags: ∅ diff --git a/test/prism/snapshots/whitequark/const_op_asgn.txt b/test/prism/snapshots/whitequark/const_op_asgn.txt index 505ce6ef64bdb4..71df6208d25b97 100644 --- a/test/prism/snapshots/whitequark/const_op_asgn.txt +++ b/test/prism/snapshots/whitequark/const_op_asgn.txt @@ -10,21 +10,21 @@ │ │ ├── name: :A │ │ ├── delimiter_loc: (1,0)-(1,2) = "::" │ │ └── name_loc: (1,2)-(1,3) = "A" - │ ├── operator_loc: (1,4)-(1,6) = "+=" + │ ├── binary_operator_loc: (1,4)-(1,6) = "+=" │ ├── value: │ │ @ IntegerNode (location: (1,7)-(1,8)) │ │ ├── flags: decimal │ │ └── value: 1 - │ └── operator: :+ + │ └── binary_operator: :+ ├── @ ConstantOperatorWriteNode (location: (3,0)-(3,6)) │ ├── name: :A │ ├── name_loc: (3,0)-(3,1) = "A" - │ ├── operator_loc: (3,2)-(3,4) = "+=" + │ ├── binary_operator_loc: (3,2)-(3,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (3,5)-(3,6)) │ │ ├── flags: decimal │ │ └── value: 1 - │ └── operator: :+ + │ └── binary_operator: :+ ├── @ ConstantPathOperatorWriteNode (location: (5,0)-(5,9)) │ ├── target: │ │ @ ConstantPathNode (location: (5,0)-(5,4)) @@ -34,12 +34,12 @@ │ │ ├── name: :A │ │ ├── delimiter_loc: (5,1)-(5,3) = "::" │ │ └── name_loc: (5,3)-(5,4) = "A" - │ ├── operator_loc: (5,5)-(5,7) = "+=" + │ ├── binary_operator_loc: (5,5)-(5,7) = "+=" │ ├── value: │ │ @ IntegerNode (location: (5,8)-(5,9)) │ │ ├── flags: decimal │ │ └── value: 1 - │ └── operator: :+ + │ └── binary_operator: :+ ├── @ DefNode (location: (7,0)-(7,21)) │ ├── name: :x │ ├── name_loc: (7,4)-(7,5) = "x" diff --git a/test/prism/snapshots/whitequark/op_asgn.txt b/test/prism/snapshots/whitequark/op_asgn.txt index 8f24a35ad0d555..f72661790479b7 100644 --- a/test/prism/snapshots/whitequark/op_asgn.txt +++ b/test/prism/snapshots/whitequark/op_asgn.txt @@ -20,8 +20,8 @@ │ ├── message_loc: (1,4)-(1,5) = "A" │ ├── read_name: :A │ ├── write_name: :A= - │ ├── operator: :+ - │ ├── operator_loc: (1,6)-(1,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (1,6)-(1,8) = "+=" │ └── value: │ @ IntegerNode (location: (1,9)-(1,10)) │ ├── flags: decimal @@ -43,8 +43,8 @@ │ ├── message_loc: (3,4)-(3,5) = "a" │ ├── read_name: :a │ ├── write_name: :a= - │ ├── operator: :+ - │ ├── operator_loc: (3,6)-(3,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (3,6)-(3,8) = "+=" │ └── value: │ @ IntegerNode (location: (3,9)-(3,10)) │ ├── flags: decimal @@ -66,8 +66,8 @@ ├── message_loc: (5,5)-(5,6) = "a" ├── read_name: :a ├── write_name: :a= - ├── operator: :+ - ├── operator_loc: (5,7)-(5,9) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (5,7)-(5,9) = "+=" └── value: @ IntegerNode (location: (5,10)-(5,11)) ├── flags: decimal diff --git a/test/prism/snapshots/whitequark/op_asgn_cmd.txt b/test/prism/snapshots/whitequark/op_asgn_cmd.txt index 7d5ad21d55290a..d2d86b1bf9fc2f 100644 --- a/test/prism/snapshots/whitequark/op_asgn_cmd.txt +++ b/test/prism/snapshots/whitequark/op_asgn_cmd.txt @@ -20,8 +20,8 @@ │ ├── message_loc: (1,4)-(1,5) = "A" │ ├── read_name: :A │ ├── write_name: :A= - │ ├── operator: :+ - │ ├── operator_loc: (1,6)-(1,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (1,6)-(1,8) = "+=" │ └── value: │ @ CallNode (location: (1,9)-(1,14)) │ ├── flags: ignore_visibility @@ -63,8 +63,8 @@ │ ├── message_loc: (3,4)-(3,5) = "a" │ ├── read_name: :a │ ├── write_name: :a= - │ ├── operator: :+ - │ ├── operator_loc: (3,6)-(3,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (3,6)-(3,8) = "+=" │ └── value: │ @ CallNode (location: (3,9)-(3,14)) │ ├── flags: ignore_visibility @@ -106,7 +106,7 @@ │ │ ├── name: :A │ │ ├── delimiter_loc: (5,3)-(5,5) = "::" │ │ └── name_loc: (5,5)-(5,6) = "A" - │ ├── operator_loc: (5,7)-(5,9) = "+=" + │ ├── binary_operator_loc: (5,7)-(5,9) = "+=" │ ├── value: │ │ @ CallNode (location: (5,10)-(5,15)) │ │ ├── flags: ignore_visibility @@ -131,7 +131,7 @@ │ │ │ └── block: ∅ │ │ ├── closing_loc: ∅ │ │ └── block: ∅ - │ └── operator: :+ + │ └── binary_operator: :+ └── @ CallOperatorWriteNode (location: (7,0)-(7,15)) ├── flags: ∅ ├── receiver: @@ -149,8 +149,8 @@ ├── message_loc: (7,5)-(7,6) = "a" ├── read_name: :a ├── write_name: :a= - ├── operator: :+ - ├── operator_loc: (7,7)-(7,9) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (7,7)-(7,9) = "+=" └── value: @ CallNode (location: (7,10)-(7,15)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/whitequark/op_asgn_index.txt b/test/prism/snapshots/whitequark/op_asgn_index.txt index fe077fae13fe6c..b302abdafea65c 100644 --- a/test/prism/snapshots/whitequark/op_asgn_index.txt +++ b/test/prism/snapshots/whitequark/op_asgn_index.txt @@ -30,8 +30,8 @@ │ └── value: 1 ├── closing_loc: (1,8)-(1,9) = "]" ├── block: ∅ - ├── operator: :+ - ├── operator_loc: (1,10)-(1,12) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,10)-(1,12) = "+=" └── value: @ IntegerNode (location: (1,13)-(1,14)) ├── flags: decimal diff --git a/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt b/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt index 87082aad947c99..319ed1a51a533e 100644 --- a/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt +++ b/test/prism/snapshots/whitequark/op_asgn_index_cmd.txt @@ -30,8 +30,8 @@ │ └── value: 1 ├── closing_loc: (1,8)-(1,9) = "]" ├── block: ∅ - ├── operator: :+ - ├── operator_loc: (1,10)-(1,12) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (1,10)-(1,12) = "+=" └── value: @ CallNode (location: (1,13)-(1,18)) ├── flags: ignore_visibility diff --git a/test/prism/snapshots/whitequark/rescue_mod_op_assign.txt b/test/prism/snapshots/whitequark/rescue_mod_op_assign.txt index b269104f308bf2..840e5a4fc0976f 100644 --- a/test/prism/snapshots/whitequark/rescue_mod_op_assign.txt +++ b/test/prism/snapshots/whitequark/rescue_mod_op_assign.txt @@ -5,7 +5,7 @@ └── body: (length: 1) └── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,22)) ├── name_loc: (1,0)-(1,3) = "foo" - ├── operator_loc: (1,4)-(1,6) = "+=" + ├── binary_operator_loc: (1,4)-(1,6) = "+=" ├── value: │ @ RescueModifierNode (location: (1,7)-(1,22)) │ ├── expression: @@ -32,5 +32,5 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── name: :foo - ├── operator: :+ + ├── binary_operator: :+ └── depth: 0 diff --git a/test/prism/snapshots/whitequark/ruby_bug_12402.txt b/test/prism/snapshots/whitequark/ruby_bug_12402.txt index 20bcfeafbefa48..4935007f8a0b5a 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12402.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12402.txt @@ -5,7 +5,7 @@ └── body: (length: 14) ├── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,27)) │ ├── name_loc: (1,0)-(1,3) = "foo" - │ ├── operator_loc: (1,4)-(1,6) = "+=" + │ ├── binary_operator_loc: (1,4)-(1,6) = "+=" │ ├── value: │ │ @ RescueModifierNode (location: (1,7)-(1,27)) │ │ ├── expression: @@ -36,11 +36,11 @@ │ │ └── rescue_expression: │ │ @ NilNode (location: (1,24)-(1,27)) │ ├── name: :foo - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,28)) │ ├── name_loc: (3,0)-(3,3) = "foo" - │ ├── operator_loc: (3,4)-(3,6) = "+=" + │ ├── binary_operator_loc: (3,4)-(3,6) = "+=" │ ├── value: │ │ @ RescueModifierNode (location: (3,7)-(3,28)) │ │ ├── expression: @@ -71,7 +71,7 @@ │ │ └── rescue_expression: │ │ @ NilNode (location: (3,25)-(3,28)) │ ├── name: :foo - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableWriteNode (location: (5,0)-(5,26)) │ ├── name: :foo @@ -151,8 +151,8 @@ │ ├── message_loc: (9,4)-(9,5) = "C" │ ├── read_name: :C │ ├── write_name: :C= - │ ├── operator: :+ - │ ├── operator_loc: (9,6)-(9,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (9,6)-(9,8) = "+=" │ └── value: │ @ RescueModifierNode (location: (9,9)-(9,29)) │ ├── expression: @@ -192,8 +192,8 @@ │ ├── message_loc: (11,4)-(11,5) = "C" │ ├── read_name: :C │ ├── write_name: :C= - │ ├── operator: :+ - │ ├── operator_loc: (11,6)-(11,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (11,6)-(11,8) = "+=" │ └── value: │ @ RescueModifierNode (location: (11,9)-(11,30)) │ ├── expression: @@ -233,8 +233,8 @@ │ ├── message_loc: (13,4)-(13,5) = "m" │ ├── read_name: :m │ ├── write_name: :m= - │ ├── operator: :+ - │ ├── operator_loc: (13,6)-(13,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (13,6)-(13,8) = "+=" │ └── value: │ @ RescueModifierNode (location: (13,9)-(13,29)) │ ├── expression: @@ -274,8 +274,8 @@ │ ├── message_loc: (15,4)-(15,5) = "m" │ ├── read_name: :m │ ├── write_name: :m= - │ ├── operator: :+ - │ ├── operator_loc: (15,6)-(15,8) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (15,6)-(15,8) = "+=" │ └── value: │ @ RescueModifierNode (location: (15,9)-(15,30)) │ ├── expression: @@ -395,8 +395,8 @@ │ ├── message_loc: (21,5)-(21,6) = "m" │ ├── read_name: :m │ ├── write_name: :m= - │ ├── operator: :+ - │ ├── operator_loc: (21,7)-(21,9) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (21,7)-(21,9) = "+=" │ └── value: │ @ RescueModifierNode (location: (21,10)-(21,30)) │ ├── expression: @@ -436,8 +436,8 @@ │ ├── message_loc: (23,5)-(23,6) = "m" │ ├── read_name: :m │ ├── write_name: :m= - │ ├── operator: :+ - │ ├── operator_loc: (23,7)-(23,9) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (23,7)-(23,9) = "+=" │ └── value: │ @ RescueModifierNode (location: (23,10)-(23,31)) │ ├── expression: @@ -484,8 +484,8 @@ │ │ └── value: 0 │ ├── closing_loc: (25,5)-(25,6) = "]" │ ├── block: ∅ - │ ├── operator: :+ - │ ├── operator_loc: (25,7)-(25,9) = "+=" + │ ├── binary_operator: :+ + │ ├── binary_operator_loc: (25,7)-(25,9) = "+=" │ └── value: │ @ RescueModifierNode (location: (25,10)-(25,30)) │ ├── expression: @@ -532,8 +532,8 @@ │ └── value: 0 ├── closing_loc: (27,5)-(27,6) = "]" ├── block: ∅ - ├── operator: :+ - ├── operator_loc: (27,7)-(27,9) = "+=" + ├── binary_operator: :+ + ├── binary_operator_loc: (27,7)-(27,9) = "+=" └── value: @ RescueModifierNode (location: (27,10)-(27,31)) ├── expression: diff --git a/test/prism/snapshots/whitequark/ruby_bug_12669.txt b/test/prism/snapshots/whitequark/ruby_bug_12669.txt index 86b021351b8329..6151143ba8392f 100644 --- a/test/prism/snapshots/whitequark/ruby_bug_12669.txt +++ b/test/prism/snapshots/whitequark/ruby_bug_12669.txt @@ -5,11 +5,11 @@ └── body: (length: 4) ├── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,18)) │ ├── name_loc: (1,0)-(1,1) = "a" - │ ├── operator_loc: (1,2)-(1,4) = "+=" + │ ├── binary_operator_loc: (1,2)-(1,4) = "+=" │ ├── value: │ │ @ LocalVariableOperatorWriteNode (location: (1,5)-(1,18)) │ │ ├── name_loc: (1,5)-(1,6) = "b" - │ │ ├── operator_loc: (1,7)-(1,9) = "+=" + │ │ ├── binary_operator_loc: (1,7)-(1,9) = "+=" │ │ ├── value: │ │ │ @ CallNode (location: (1,10)-(1,18)) │ │ │ ├── flags: ignore_visibility @@ -31,14 +31,14 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── name: :b - │ │ ├── operator: :+ + │ │ ├── binary_operator: :+ │ │ └── depth: 0 │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableOperatorWriteNode (location: (3,0)-(3,17)) │ ├── name_loc: (3,0)-(3,1) = "a" - │ ├── operator_loc: (3,2)-(3,4) = "+=" + │ ├── binary_operator_loc: (3,2)-(3,4) = "+=" │ ├── value: │ │ @ LocalVariableWriteNode (location: (3,5)-(3,17)) │ │ ├── name: :b @@ -66,7 +66,7 @@ │ │ │ └── block: ∅ │ │ └── operator_loc: (3,7)-(3,8) = "=" │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 ├── @ LocalVariableWriteNode (location: (5,0)-(5,17)) │ ├── name: :a @@ -75,7 +75,7 @@ │ ├── value: │ │ @ LocalVariableOperatorWriteNode (location: (5,4)-(5,17)) │ │ ├── name_loc: (5,4)-(5,5) = "b" - │ │ ├── operator_loc: (5,6)-(5,8) = "+=" + │ │ ├── binary_operator_loc: (5,6)-(5,8) = "+=" │ │ ├── value: │ │ │ @ CallNode (location: (5,9)-(5,17)) │ │ │ ├── flags: ignore_visibility @@ -97,7 +97,7 @@ │ │ │ ├── closing_loc: ∅ │ │ │ └── block: ∅ │ │ ├── name: :b - │ │ ├── operator: :+ + │ │ ├── binary_operator: :+ │ │ └── depth: 0 │ └── operator_loc: (5,2)-(5,3) = "=" └── @ LocalVariableWriteNode (location: (7,0)-(7,16)) diff --git a/test/prism/snapshots/whitequark/var_op_asgn.txt b/test/prism/snapshots/whitequark/var_op_asgn.txt index f423a62dee9c8b..f20f612fa2addd 100644 --- a/test/prism/snapshots/whitequark/var_op_asgn.txt +++ b/test/prism/snapshots/whitequark/var_op_asgn.txt @@ -6,30 +6,30 @@ ├── @ ClassVariableOperatorWriteNode (location: (1,0)-(1,11)) │ ├── name: :@@var │ ├── name_loc: (1,0)-(1,5) = "@@var" - │ ├── operator_loc: (1,6)-(1,8) = "|=" + │ ├── binary_operator_loc: (1,6)-(1,8) = "|=" │ ├── value: │ │ @ IntegerNode (location: (1,9)-(1,11)) │ │ ├── flags: decimal │ │ └── value: 10 - │ └── operator: :| + │ └── binary_operator: :| ├── @ InstanceVariableOperatorWriteNode (location: (3,0)-(3,7)) │ ├── name: :@a │ ├── name_loc: (3,0)-(3,2) = "@a" - │ ├── operator_loc: (3,3)-(3,5) = "|=" + │ ├── binary_operator_loc: (3,3)-(3,5) = "|=" │ ├── value: │ │ @ IntegerNode (location: (3,6)-(3,7)) │ │ ├── flags: decimal │ │ └── value: 1 - │ └── operator: :| + │ └── binary_operator: :| ├── @ LocalVariableOperatorWriteNode (location: (5,0)-(5,6)) │ ├── name_loc: (5,0)-(5,1) = "a" - │ ├── operator_loc: (5,2)-(5,4) = "+=" + │ ├── binary_operator_loc: (5,2)-(5,4) = "+=" │ ├── value: │ │ @ IntegerNode (location: (5,5)-(5,6)) │ │ ├── flags: decimal │ │ └── value: 1 │ ├── name: :a - │ ├── operator: :+ + │ ├── binary_operator: :+ │ └── depth: 0 └── @ DefNode (location: (7,0)-(7,23)) ├── name: :a @@ -42,12 +42,12 @@ │ └── @ ClassVariableOperatorWriteNode (location: (7,7)-(7,18)) │ ├── name: :@@var │ ├── name_loc: (7,7)-(7,12) = "@@var" - │ ├── operator_loc: (7,13)-(7,15) = "|=" + │ ├── binary_operator_loc: (7,13)-(7,15) = "|=" │ ├── value: │ │ @ IntegerNode (location: (7,16)-(7,18)) │ │ ├── flags: decimal │ │ └── value: 10 - │ └── operator: :| + │ └── binary_operator: :| ├── locals: [] ├── def_keyword_loc: (7,0)-(7,3) = "def" ├── operator_loc: ∅ diff --git a/test/prism/snapshots/whitequark/var_op_asgn_cmd.txt b/test/prism/snapshots/whitequark/var_op_asgn_cmd.txt index d56c099c7eee01..0bfa06d5b7ccf1 100644 --- a/test/prism/snapshots/whitequark/var_op_asgn_cmd.txt +++ b/test/prism/snapshots/whitequark/var_op_asgn_cmd.txt @@ -5,7 +5,7 @@ └── body: (length: 1) └── @ LocalVariableOperatorWriteNode (location: (1,0)-(1,12)) ├── name_loc: (1,0)-(1,3) = "foo" - ├── operator_loc: (1,4)-(1,6) = "+=" + ├── binary_operator_loc: (1,4)-(1,6) = "+=" ├── value: │ @ CallNode (location: (1,7)-(1,12)) │ ├── flags: ignore_visibility @@ -24,5 +24,5 @@ │ ├── closing_loc: ∅ │ └── block: ∅ ├── name: :foo - ├── operator: :+ + ├── binary_operator: :+ └── depth: 0 From 77b6c980b2278951de206e0cdc5dd49a6f241eb3 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 10:49:33 -0400 Subject: [PATCH 067/151] [PRISM] Handle operator->binary_operator rename --- prism_compile.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/prism_compile.c b/prism_compile.c index 4ea263d45c1877..5ecc69470f9b1c 100644 --- a/prism_compile.c +++ b/prism_compile.c @@ -1737,7 +1737,7 @@ pm_compile_index_operator_write_node(rb_iseq_t *iseq, const pm_index_operator_wr PUSH_SEND_R(ret, location, idAREF, INT2FIX(argc), NULL, INT2FIX(flag & ~(VM_CALL_ARGS_SPLAT_MUT | VM_CALL_KW_SPLAT_MUT)), keywords); PM_COMPILE_NOT_POPPED(node->value); - ID id_operator = pm_constant_id_lookup(scope_node, node->operator); + ID id_operator = pm_constant_id_lookup(scope_node, node->binary_operator); PUSH_SEND(ret, location, id_operator, INT2FIX(1)); if (!popped) { @@ -4820,7 +4820,7 @@ pm_compile_constant_operator_write_node(rb_iseq_t *iseq, const pm_constant_opera const pm_line_column_t location = *node_location; VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name)); - ID method_id = pm_constant_id_lookup(scope_node, node->operator); + ID method_id = pm_constant_id_lookup(scope_node, node->binary_operator); pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node); @@ -5020,7 +5020,7 @@ pm_compile_constant_path_operator_write_node(rb_iseq_t *iseq, const pm_constant_ const pm_line_column_t location = *node_location; const pm_constant_path_node_t *target = node->target; - ID method_id = pm_constant_id_lookup(scope_node, node->operator); + ID method_id = pm_constant_id_lookup(scope_node, node->binary_operator); VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name)); if (target->parent) { @@ -5542,7 +5542,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PUSH_SEND_WITH_FLAG(ret, location, id_read_name, INT2FIX(0), INT2FIX(flag)); PM_COMPILE_NOT_POPPED(cast->value); - ID id_operator = pm_constant_id_lookup(scope_node, cast->operator); + ID id_operator = pm_constant_id_lookup(scope_node, cast->binary_operator); PUSH_SEND(ret, location, id_operator, INT2FIX(1)); if (!popped) { @@ -6046,7 +6046,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PUSH_INSN2(ret, location, getclassvariable, name, get_cvar_ic_value(iseq, name_id)); PM_COMPILE_NOT_POPPED(cast->value); - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); + ID method_id = pm_constant_id_lookup(scope_node, cast->binary_operator); int flags = VM_CALL_ARGS_SIMPLE; PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(flags)); @@ -6537,7 +6537,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PUSH_INSN1(ret, location, getglobal, name); PM_COMPILE_NOT_POPPED(cast->value); - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); + ID method_id = pm_constant_id_lookup(scope_node, cast->binary_operator); int flags = VM_CALL_ARGS_SIMPLE; PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(flags)); @@ -6735,7 +6735,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PUSH_INSN2(ret, location, getinstancevariable, name, get_ivar_ic_value(iseq, name_id)); PM_COMPILE_NOT_POPPED(cast->value); - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); + ID method_id = pm_constant_id_lookup(scope_node, cast->binary_operator); int flags = VM_CALL_ARGS_SIMPLE; PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(flags)); @@ -6985,7 +6985,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, PM_COMPILE_NOT_POPPED(cast->value); - ID method_id = pm_constant_id_lookup(scope_node, cast->operator); + ID method_id = pm_constant_id_lookup(scope_node, cast->binary_operator); PUSH_SEND_WITH_FLAG(ret, location, method_id, INT2NUM(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); if (!popped) PUSH_INSN(ret, location, dup); From 955f13238d951dd52a12733a69a6787008fd82cc Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 11:06:31 -0400 Subject: [PATCH 068/151] [PRISM] Enable passing IRB tests --- test/.excludes-prism/TestIRB/RubyLexTest.rb | 1 - test/.excludes-prism/TestSyntax.rb | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) delete mode 100644 test/.excludes-prism/TestIRB/RubyLexTest.rb diff --git a/test/.excludes-prism/TestIRB/RubyLexTest.rb b/test/.excludes-prism/TestIRB/RubyLexTest.rb deleted file mode 100644 index d2635f96117ab2..00000000000000 --- a/test/.excludes-prism/TestIRB/RubyLexTest.rb +++ /dev/null @@ -1 +0,0 @@ -exclude(:test_code_block_open_with_should_continue, "https://github.com/ruby/irb/pull/954") diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index fe1e8f0d5c22aa..fdeb25d5281046 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -1,14 +1,14 @@ -exclude(:test__END___cr, "unknown") -exclude(:test_argument_forwarding_with_super, "unknown") -exclude(:test_argument_forwarding, "unknown") -exclude(:test_dedented_heredoc_continued_line, "unknown") -exclude(:test_duplicated_when, "unknown") -exclude(:test_error_message_encoding, "unknown") +exclude(:test__END___cr, "error message format") +exclude(:test_argument_forwarding_with_super, "error message format") +exclude(:test_argument_forwarding, "error message format") +exclude(:test_dedented_heredoc_continued_line, "heredoc line continuation dedent calculation") +exclude(:test_duplicated_when, "error message format") +exclude(:test_error_message_encoding, "syntax error message encoding") exclude(:test_it, "https://github.com/ruby/prism/issues/2323") -exclude(:test_numbered_parameter, "unknown") -exclude(:test_syntax_error_at_newline, "unknown") -exclude(:test_unterminated_heredoc_cr, "unknown") -exclude(:test_warn_balanced, "unknown") +exclude(:test_numbered_parameter, "should raise syntax error for numbered parameters in inner blocks") +exclude(:test_syntax_error_at_newline, "error message format") +exclude(:test_unterminated_heredoc_cr, "quoted \r heredoc terminators should not match \r\n") +exclude(:test_warn_balanced, "missing warning for ** being interpreted as a binary operator") exclude(:test_optional_self_reference, "https://bugs.ruby-lang.org/issues/20478") exclude(:test_keyword_self_reference, "https://bugs.ruby-lang.org/issues/20478") From 83f481ebf0ab8987bd2bc15767e7a1fac18f05b5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 11:39:51 -0400 Subject: [PATCH 069/151] [ruby/prism] Enhance parameter forwarding error messages https://github.com/ruby/prism/commit/826657232e --- prism/config.yml | 3 ++ prism/prism.c | 69 ++++++++++++++-------------- prism/templates/src/diagnostic.c.erb | 4 +- prism/templates/src/token_type.c.erb | 4 +- test/prism/errors_test.rb | 18 ++++---- 5 files changed, 50 insertions(+), 48 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index eb22d5730110bd..c48e5f28dc7992 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -193,6 +193,7 @@ errors: - PARAMETER_ASSOC_SPLAT_MULTI - PARAMETER_BLOCK_MULTI - PARAMETER_CIRCULAR + - PARAMETER_FORWARDING_AFTER_REST - PARAMETER_METHOD_NAME - PARAMETER_NAME_DUPLICATED - PARAMETER_NO_DEFAULT @@ -3084,6 +3085,8 @@ nodes: # On parsing error of `f(**kwargs, ...)` or `f(**nil, ...)`, the keyword_rest value is moved here: - KeywordRestParameterNode - NoKeywordsParameterNode + # On parsing error of `f(..., ...)`, the first forwarding parameter is moved here: + - ForwardingParameterNode - name: keywords type: node[] kind: diff --git a/prism/prism.c b/prism/prism.c index b517aa959e15f5..4c8b42f8020e8d 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -14118,31 +14118,37 @@ static pm_parameters_order_t parameters_ordering[PM_TOKEN_MAXIMUM] = { * Check if current parameter follows valid parameters ordering. If not it adds * an error to the list without stopping the parsing, otherwise sets the * parameters state to the one corresponding to the current parameter. + * + * It returns true if it was successful, and false otherwise. */ -static void +static bool update_parameter_state(pm_parser_t *parser, pm_token_t *token, pm_parameters_order_t *current) { pm_parameters_order_t state = parameters_ordering[token->type]; - if (state == PM_PARAMETERS_NO_CHANGE) return; + if (state == PM_PARAMETERS_NO_CHANGE) return true; // If we see another ordered argument after a optional argument // we only continue parsing ordered arguments until we stop seeing ordered arguments. if (*current == PM_PARAMETERS_ORDER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) { *current = PM_PARAMETERS_ORDER_AFTER_OPTIONAL; - return; + return true; } else if (*current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL && state == PM_PARAMETERS_ORDER_NAMED) { - return; + return true; } if (token->type == PM_TOKEN_USTAR && *current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL) { pm_parser_err_token(parser, token, PM_ERR_PARAMETER_STAR); - } - - if (*current == PM_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) { + return false; + } else if (token->type == PM_TOKEN_UDOT_DOT_DOT && (*current >= PM_PARAMETERS_ORDER_KEYWORDS_REST && *current <= PM_PARAMETERS_ORDER_AFTER_OPTIONAL)) { + pm_parser_err_token(parser, token, *current == PM_PARAMETERS_ORDER_AFTER_OPTIONAL ? PM_ERR_PARAMETER_FORWARDING_AFTER_REST : PM_ERR_PARAMETER_ORDER); + return false; + } else if (*current == PM_PARAMETERS_ORDER_NOTHING_AFTER || state > *current) { // We know what transition we failed on, so we can provide a better error here. pm_parser_err_token(parser, token, PM_ERR_PARAMETER_ORDER); - } else if (state < *current) { - *current = state; + return false; } + + if (state < *current) *current = state; + return true; } /** @@ -14211,27 +14217,22 @@ parse_parameters( pm_parser_err_current(parser, PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES); } - if (order > PM_PARAMETERS_ORDER_NOTHING_AFTER) { - update_parameter_state(parser, &parser->current, &order); - parser_lex(parser); + bool succeeded = update_parameter_state(parser, &parser->current, &order); + parser_lex(parser); - parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL; + parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_ALL; + pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous); - pm_forwarding_parameter_node_t *param = pm_forwarding_parameter_node_create(parser, &parser->previous); - if (params->keyword_rest != NULL) { - // If we already have a keyword rest parameter, then we replace it with the - // forwarding parameter and move the keyword rest parameter to the posts list. - pm_node_t *keyword_rest = params->keyword_rest; - pm_parameters_node_posts_append(params, keyword_rest); - pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); - params->keyword_rest = NULL; - } - pm_parameters_node_keyword_rest_set(params, (pm_node_t *)param); - } else { - update_parameter_state(parser, &parser->current, &order); - parser_lex(parser); + if (params->keyword_rest != NULL) { + // If we already have a keyword rest parameter, then we replace it with the + // forwarding parameter and move the keyword rest parameter to the posts list. + pm_node_t *keyword_rest = params->keyword_rest; + pm_parameters_node_posts_append(params, keyword_rest); + if (succeeded) pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_FWD); + params->keyword_rest = NULL; } + pm_parameters_node_keyword_rest_set(params, (pm_node_t *) param); break; } case PM_TOKEN_CLASS_VARIABLE: @@ -14896,7 +14897,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept arguments->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous); } else { pm_accepts_block_stack_push(parser, true); - parse_arguments(parser, arguments, true, PM_TOKEN_PARENTHESIS_RIGHT); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT); if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_type_human(parser->current.type)); @@ -14914,7 +14915,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept // If we get here, then the subsequent token cannot be used as an infix // operator. In this case we assume the subsequent token is part of an // argument to this method call. - parse_arguments(parser, arguments, true, PM_TOKEN_EOF); + parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF); // If we have done with the arguments and still not consumed the comma, // then we have a trailing comma where we need to check whether it is @@ -14945,11 +14946,8 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept if (arguments->block == NULL && !arguments->has_forwarding) { arguments->block = (pm_node_t *) block; } else { - if (arguments->has_forwarding) { - pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_FORWARDING); - } else { - pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI); - } + pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI); + if (arguments->block != NULL) { if (arguments->arguments == NULL) { arguments->arguments = pm_arguments_node_create(parser); @@ -17048,7 +17046,8 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, pm_token_type_human(parser->previous.type)); break; } - case PM_ERR_HASH_VALUE: { + case PM_ERR_HASH_VALUE: + case PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR: { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type)); break; } @@ -20329,7 +20328,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t // In this case we have an operator but we don't know what it's for. // We need to treat it as an error. For now, we'll mark it as an error // and just skip right past it. - pm_parser_err_previous(parser, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR); + PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, pm_token_type_human(parser->current.type)); return node; } } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 75a00958fc8cec..451f9c3f7cd80c 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -91,7 +91,6 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ARGUMENT_AFTER_BLOCK] = { "unexpected argument after a block argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES] = { "unexpected argument after `...`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BARE_HASH] = { "unexpected bare hash argument", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ARGUMENT_BLOCK_FORWARDING] = { "both a block argument and a forwarding argument; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_BLOCK_MULTI] = { "both block arg and actual block given; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_CONFLICT_AMPERSAND] = { "unexpected `&`; anonymous block parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ARGUMENT_CONFLICT_STAR] = { "unexpected `*`; anonymous rest parameter is also used within block", PM_ERROR_LEVEL_SYNTAX }, @@ -177,7 +176,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL] = { "expected an expression after `=`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS] = { "expected an expression after `<<`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_LPAREN] = { "expected an expression after `(`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "expected an expression after the operator", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR] = { "unexpected %s; expected an expression after the operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_LEVEL_SYNTAX }, @@ -276,6 +275,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_PARAMETER_ASSOC_SPLAT_MULTI] = { "unexpected multiple `**` splat parameters", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_BLOCK_MULTI] = { "multiple block parameters; only one block is allowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_CIRCULAR] = { "circular argument reference - %.*s", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_PARAMETER_FORWARDING_AFTER_REST] = { "... after rest argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_METHOD_NAME] = { "unexpected name for a parameter", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_NAME_DUPLICATED] = { "duplicated argument name", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_PARAMETER_NO_DEFAULT] = { "expected a default value for the parameter", PM_ERROR_LEVEL_SYNTAX }, diff --git a/prism/templates/src/token_type.c.erb b/prism/templates/src/token_type.c.erb index 0587fc6cdf0b16..a3095eeab8543f 100644 --- a/prism/templates/src/token_type.c.erb +++ b/prism/templates/src/token_type.c.erb @@ -90,9 +90,9 @@ pm_token_type_human(pm_token_type_t token_type) { case PM_TOKEN_DOT: return "'.'"; case PM_TOKEN_DOT_DOT: - return "'..'"; + return ".."; case PM_TOKEN_DOT_DOT_DOT: - return "'...'"; + return "..."; case PM_TOKEN_EMBDOC_BEGIN: return "'=begin'"; case PM_TOKEN_EMBDOC_END: diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index db4d2af5e1c15b..5d18780dddb564 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -99,7 +99,7 @@ def test_pre_execution_context ) assert_errors expected, "BEGIN { 1 + }", [ - ["expected an expression after the operator", 10..11], + ["unexpected '}'; expected an expression after the operator", 12..13], ["unexpected '}', assuming it is closing the parent 'BEGIN' block", 12..13] ] end @@ -210,7 +210,7 @@ def test_missing_terminator_in_parentheses def test_unterminated_argument_expression assert_errors expression('a %'), 'a %', [ ["invalid `%` token", 2..3], - ["expected an expression after the operator", 2..3], + ["unexpected end of file; expected an expression after the operator", 3..3], ["unexpected end of file, assuming it is closing the parent top level context", 3..3] ] end @@ -864,7 +864,7 @@ def test_double_arguments_forwarding :foo, Location(), nil, - ParametersNode([], [], nil, [], [], ForwardingParameterNode(), nil), + ParametersNode([], [], nil, [ForwardingParameterNode()], [], ForwardingParameterNode(), nil), nil, [], Location(), @@ -1466,7 +1466,7 @@ def test_loop_conditional_is_closed def test_forwarding_arg_after_keyword_rest source = "def f(**,...);end" assert_errors expression(source), source, [ - ["unexpected `...` in parameters", 9..12], + ["unexpected parameter order", 9..12] ] end @@ -1942,10 +1942,10 @@ def test_binary_range_with_left_unary_range RUBY assert_errors expression(source), source, [ - ["unexpected '..', expecting end-of-input", 3..5], - ["unexpected '..', ignoring it", 3..5], - ["unexpected '..', expecting end-of-input", 10..12], - ["unexpected '..', ignoring it", 10..12] + ["unexpected .., expecting end-of-input", 3..5], + ["unexpected .., ignoring it", 3..5], + ["unexpected .., expecting end-of-input", 10..12], + ["unexpected .., ignoring it", 10..12] ] end @@ -2082,7 +2082,7 @@ def test_block_arg_and_block def test_forwarding_arg_and_block source = 'def foo(...) = foo(...) { }' assert_errors expression(source), source, [ - ['both a block argument and a forwarding argument; only one block is allowed', 24..27] + ['both block arg and actual block given; only one block is allowed', 24..27] ] end From 2e4f3739fbf7ec9625c78a7114970bf102e6ec3c Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 11:55:19 -0400 Subject: [PATCH 070/151] [PRISM] Enable passing argument forwarding tests --- test/.excludes-prism/TestSyntax.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index fdeb25d5281046..0d312618c72836 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -1,6 +1,4 @@ exclude(:test__END___cr, "error message format") -exclude(:test_argument_forwarding_with_super, "error message format") -exclude(:test_argument_forwarding, "error message format") exclude(:test_dedented_heredoc_continued_line, "heredoc line continuation dedent calculation") exclude(:test_duplicated_when, "error message format") exclude(:test_error_message_encoding, "syntax error message encoding") From afdfff933fefa17a8ef12f791b7f363780b1f61b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Fri, 10 May 2024 13:09:45 -0400 Subject: [PATCH 071/151] [PRISM] Bump to version 0.29.0 --- lib/prism/prism.gemspec | 2 +- prism/extension.h | 2 +- prism/templates/lib/prism/serialize.rb.erb | 2 +- prism/version.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec index 73ec01251f0128..374591bb70731f 100644 --- a/lib/prism/prism.gemspec +++ b/lib/prism/prism.gemspec @@ -2,7 +2,7 @@ Gem::Specification.new do |spec| spec.name = "prism" - spec.version = "0.28.0" + spec.version = "0.29.0" spec.authors = ["Shopify"] spec.email = ["ruby@shopify.com"] diff --git a/prism/extension.h b/prism/extension.h index 93ad58fdc8f5b2..b15a2c5e61b492 100644 --- a/prism/extension.h +++ b/prism/extension.h @@ -1,7 +1,7 @@ #ifndef PRISM_EXT_NODE_H #define PRISM_EXT_NODE_H -#define EXPECTED_PRISM_VERSION "0.28.0" +#define EXPECTED_PRISM_VERSION "0.29.0" #include #include diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb index 370b6297997689..756821cf7d7362 100644 --- a/prism/templates/lib/prism/serialize.rb.erb +++ b/prism/templates/lib/prism/serialize.rb.erb @@ -10,7 +10,7 @@ module Prism # The minor version of prism that we are expecting to find in the serialized # strings. - MINOR_VERSION = 28 + MINOR_VERSION = 29 # The patch version of prism that we are expecting to find in the serialized # strings. diff --git a/prism/version.h b/prism/version.h index 195d1dab0a03be..154e967944abcb 100644 --- a/prism/version.h +++ b/prism/version.h @@ -14,7 +14,7 @@ /** * The minor version of the Prism library as an int. */ -#define PRISM_VERSION_MINOR 28 +#define PRISM_VERSION_MINOR 29 /** * The patch version of the Prism library as an int. @@ -24,6 +24,6 @@ /** * The version of the Prism library as a constant string. */ -#define PRISM_VERSION "0.28.0" +#define PRISM_VERSION "0.29.0" #endif From 3ec5a9325fe86f65326dcc8746db80a3982e7b80 Mon Sep 17 00:00:00 2001 From: git Date: Fri, 10 May 2024 17:10:55 +0000 Subject: [PATCH 072/151] Update default gems list at afdfff933fefa17a8ef12f791b7f36 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index c47ff32912d8c3..4c950e884f56f1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -49,7 +49,7 @@ The following default gems are updated. * json 2.7.2 * net-http 0.4.1 * optparse 0.5.0 -* prism 0.28.0 +* prism 0.29.0 * rdoc 6.6.3.1 * reline 0.5.6 * resolv 0.4.0 From 68b6fe70484b1fed2767fc9b838a487aa47d3560 Mon Sep 17 00:00:00 2001 From: tomoya ishida Date: Sat, 11 May 2024 02:19:38 +0900 Subject: [PATCH 073/151] [ruby/reline] Avoid STDIN.winsize called in `require "reline"` (https://github.com/ruby/reline/pull/703) https://github.com/ruby/reline/commit/21891c47c4 --- lib/reline/line_editor.rb | 2 +- test/reline/test_reline.rb | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 9e221f4c9ce6d6..4c76932c1097a5 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -75,7 +75,7 @@ def lines(screen_width) def initialize(config, encoding) @config = config @completion_append_character = '' - @screen_size = Reline::IOGate.get_screen_size + @screen_size = [0, 0] # Should be initialized with actual winsize in LineEditor#reset reset_variables(encoding: encoding) end diff --git a/test/reline/test_reline.rb b/test/reline/test_reline.rb index 40c880c11f312c..a20a5c9f44e341 100644 --- a/test/reline/test_reline.rb +++ b/test/reline/test_reline.rb @@ -378,10 +378,28 @@ def test_dumb_terminal assert_equal("Reline::GeneralIO", out.chomp) end + def test_require_reline_should_not_trigger_winsize + pend if win? + lib = File.expand_path("../../lib", __dir__) + code = <<~RUBY + require "io/console" + def STDIN.tty?; true; end + def STDOUT.tty?; true; end + def STDIN.winsize; raise; end + require("reline") && p(Reline.core.io_gate) + RUBY + out = IO.popen([{}, Reline.test_rubybin, "-I#{lib}", "-e", code], &:read) + assert_equal("Reline::ANSI", out.chomp) + end + + def win? + /mswin|mingw/.match?(RUBY_PLATFORM) + end + def get_reline_encoding if encoding = Reline.core.encoding encoding - elsif RUBY_PLATFORM =~ /mswin|mingw/ + elsif win? Encoding::UTF_8 else Encoding::default_external From 7e604a02637275f7f2f1b13074abe1d5f146829b Mon Sep 17 00:00:00 2001 From: yui-knk Date: Sat, 11 May 2024 17:08:22 +0900 Subject: [PATCH 074/151] Fix SEGV when ripper hits `backref_error` on `command_asgn` or `arg` --- parse.y | 4 ++-- test/ripper/test_parser_events.rb | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index 5ff8394c2781e1..838f273760021f 100644 --- a/parse.y +++ b/parse.y @@ -3382,7 +3382,7 @@ command_asgn : lhs '=' lex_ctxt command_rhs rb_backref_error(p, $1); /*% %*/ $$ = NEW_ERROR(&@$); - /*% ripper[error]: backref_error(p, RNODE($:1), assign!(var_field(p, get_value($:1)), $:4)) %*/ + /*% ripper[error]: backref_error(p, $1, assign!(var_field(p, get_value($:1)), $:4)) %*/ } ; @@ -3981,7 +3981,7 @@ arg : lhs '=' lex_ctxt arg_rhs /*%%%*/ $$ = NEW_ERROR(&@$); /*% %*/ - /*% ripper[error]: backref_error(p, RNODE($:1), opassign!(var_field(p, get_value($:1)), $:2, $:4)) %*/ + /*% ripper[error]: backref_error(p, $1, opassign!(var_field(p, get_value($:1)), $:2, $:4)) %*/ } | arg tDOT2 arg { diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index cbae6e7ed59b0a..8f37d4c94e8fcf 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -278,6 +278,18 @@ def test_assign_error_backref parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error assert_equal '[massign([assign_error(var_field($`)),var_field(_)],1)]', result + + thru_assign_error = false + result = + parse('$` += 1', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + assert_equal '[assign_error(opassign(var_field($`),+=,1))]', result + + thru_assign_error = false + result = + parse('$` += cmd 1, 2', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + assert_equal '[assign_error(assign(var_field($`),command(cmd,[1,2])))]', result end def test_assign_error_const_qualified From 4edd9b072c4382a901f7317c2c0c9e143554b709 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 12 May 2024 13:47:10 +0900 Subject: [PATCH 075/151] [ruby/irb] Clean up tmpdir https://github.com/ruby/irb/commit/7d60349499 --- test/irb/test_init.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/irb/test_init.rb b/test/irb/test_init.rb index 64567870126378..3207c2898ba72c 100644 --- a/test/irb/test_init.rb +++ b/test/irb/test_init.rb @@ -273,7 +273,7 @@ def setup @original_home = ENV["HOME"] @original_irbrc = ENV["IRBRC"] # To prevent the test from using the user's .irbrc file - ENV["HOME"] = Dir.mktmpdir + ENV["HOME"] = @home = Dir.mktmpdir IRB.instance_variable_set(:@existing_rc_name_generators, nil) super end @@ -283,6 +283,7 @@ def teardown ENV["IRBRC"] = @original_irbrc ENV["HOME"] = @original_home File.unlink(@irbrc) + Dir.rmdir(@home) end def test_irb_name_converts_non_string_values_to_string From d9e6e6fb60ae71f5288f54f0d34fad1e8806cf67 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 4 May 2024 22:15:47 +0900 Subject: [PATCH 076/151] [Bug #7759] Fix instance variable names to be checked --- test/ruby/test_marshal.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index 79d95777372e12..69e92488f28f49 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -570,13 +570,13 @@ def test_marshal_load_ivar def test_class_ivar assert_raise(TypeError) {Marshal.load("\x04\x08Ic\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} - assert_not_operator(TestClass, :instance_variable_defined?, :@bug) + assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug) end def test_module_ivar assert_raise(TypeError) {Marshal.load("\x04\x08Im\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")} assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")} - assert_not_operator(TestModule, :instance_variable_defined?, :@bug) + assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug) end class TestForRespondToFalse From 8b9b150512b7b9514143a6b971992c9a539ead2f Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 4 May 2024 22:17:04 +0900 Subject: [PATCH 077/151] [Bug #20481] Check for unmarshaling ivar Prohibit setting instance variables of existing classes and modules via link. --- marshal.c | 15 ++++++++++++--- test/ruby/test_marshal.rb | 6 ++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/marshal.c b/marshal.c index e26c600ca2f87c..83134371fa08a3 100644 --- a/marshal.c +++ b/marshal.c @@ -1696,6 +1696,11 @@ r_copy_ivar(VALUE v, VALUE data) return v; } +#define override_ivar_error(type, str) \ + rb_raise(rb_eTypeError, \ + "can't override instance variable of "type" '%"PRIsVALUE"'", \ + (str)) + static void r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg) { @@ -1703,6 +1708,12 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg) len = r_long(arg); if (len > 0) { + if (RB_TYPE_P(obj, T_MODULE)) { + override_ivar_error("module", rb_mod_name(obj)); + } + else if (RB_TYPE_P(obj, T_CLASS)) { + override_ivar_error("class", rb_class_name(obj)); + } do { VALUE sym = r_symbol(arg); VALUE val = r_object(arg); @@ -1795,9 +1806,7 @@ append_extmod(VALUE obj, VALUE extmod) #define prohibit_ivar(type, str) do { \ if (!ivp || !*ivp) break; \ - rb_raise(rb_eTypeError, \ - "can't override instance variable of "type" '%"PRIsVALUE"'", \ - (str)); \ + override_ivar_error(type, str); \ } while (0) static VALUE r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int type); diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb index 69e92488f28f49..bcd8892f238591 100644 --- a/test/ruby/test_marshal.rb +++ b/test/ruby/test_marshal.rb @@ -571,12 +571,18 @@ def test_class_ivar assert_raise(TypeError) {Marshal.load("\x04\x08Ic\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")} assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug) + + assert_raise(TypeError) {Marshal.load("\x04\x08[\x07c\x1bTestMarshal::TestClassI@\x06\x06:\x0e@ivar_bug\"\x08bug")} + assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug) end def test_module_ivar assert_raise(TypeError) {Marshal.load("\x04\x08Im\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")} assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")} assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug) + + assert_raise(TypeError) {Marshal.load("\x04\x08[\x07m\x1cTestMarshal::TestModuleI@\x06\x06:\x0e@ivar_bug\"\x08bug")} + assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug) end class TestForRespondToFalse From a1fb6cc978ffba6c4a8284a4fcca3efcef684714 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 10 May 2024 22:46:12 +0900 Subject: [PATCH 078/151] ripper: Use `$&` instead of quoting charaters in tests --- test/ripper/test_parser_events.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index 8f37d4c94e8fcf..8f393e79ee4542 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -269,27 +269,27 @@ def test_assign_error def test_assign_error_backref thru_assign_error = false result = - parse('$` = 1', :on_assign_error) {thru_assign_error = true} + parse('$& = 1', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error - assert_equal '[assign(assign_error(var_field($`)),1)]', result + assert_equal '[assign(assign_error(var_field($&)),1)]', result thru_assign_error = false result = - parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true} + parse('$&, _ = 1', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error - assert_equal '[massign([assign_error(var_field($`)),var_field(_)],1)]', result + assert_equal '[massign([assign_error(var_field($&)),var_field(_)],1)]', result thru_assign_error = false result = - parse('$` += 1', :on_assign_error) {thru_assign_error = true} + parse('$& += 1', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error - assert_equal '[assign_error(opassign(var_field($`),+=,1))]', result + assert_equal '[assign_error(opassign(var_field($&),+=,1))]', result thru_assign_error = false result = - parse('$` += cmd 1, 2', :on_assign_error) {thru_assign_error = true} + parse('$& += cmd 1, 2', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error - assert_equal '[assign_error(assign(var_field($`),command(cmd,[1,2])))]', result + assert_equal '[assign_error(assign(var_field($&),command(cmd,[1,2])))]', result end def test_assign_error_const_qualified From 5695c5df95460ed9949e1c8f8ca89b4a5c5cc4dd Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 12 May 2024 15:38:22 +0900 Subject: [PATCH 079/151] ripper: Fix opassign when assignment to backref variables --- parse.y | 2 +- test/ripper/test_parser_events.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index 838f273760021f..5fe9babefaea05 100644 --- a/parse.y +++ b/parse.y @@ -3382,7 +3382,7 @@ command_asgn : lhs '=' lex_ctxt command_rhs rb_backref_error(p, $1); /*% %*/ $$ = NEW_ERROR(&@$); - /*% ripper[error]: backref_error(p, $1, assign!(var_field(p, get_value($:1)), $:4)) %*/ + /*% ripper[error]: backref_error(p, $1, opassign!(var_field(p, get_value($:1)), $:2, $:4)) %*/ } ; diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index 8f393e79ee4542..dc94da01eed701 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -289,7 +289,7 @@ def test_assign_error_backref result = parse('$& += cmd 1, 2', :on_assign_error) {thru_assign_error = true} assert_equal true, thru_assign_error - assert_equal '[assign_error(assign(var_field($&),command(cmd,[1,2])))]', result + assert_equal '[assign_error(opassign(var_field($&),+=,command(cmd,[1,2])))]', result end def test_assign_error_const_qualified From b911d2222f907d3fad397938e8f513ecfb4635b8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 12 May 2024 16:23:00 +0900 Subject: [PATCH 080/151] [Bug #20482] [DOC] Clarify about pattern maching guard clause Guard clauses can only be used in `case` pattern matching statements, not in `=>`/`in` operators. --- doc/syntax/pattern_matching.rdoc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc index e49c09a1f8b3e2..6a30380f46b4b1 100644 --- a/doc/syntax/pattern_matching.rdoc +++ b/doc/syntax/pattern_matching.rdoc @@ -422,7 +422,8 @@ These core and library classes implement deconstruction: == Guard clauses -+if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: ++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions. +This condition may use bound variables: case [1, 2] in a, b if b == a*2 @@ -450,6 +451,11 @@ These core and library classes implement deconstruction: end #=> "matched" +Note that => and +in+ operator can not have a guard clause. +The following examples is parsed as a standalone expression with modifier +if+. + + [1, 2] in a, b if b == a*2 + == Appendix A. Pattern syntax Approximate syntax is: From 3c16d93cd3a7c4d1362e07070c9ed9826a7272a8 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 12 May 2024 23:12:02 +0900 Subject: [PATCH 081/151] Constify encoding type in universal parser Fixed warning about discarding modifiers. ``` ../src/ruby_parser.c:677:48: warning: passing 'rb_encoding *' (aka 'const struct OnigEncodingTypeST *') to parameter of type 'void *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers] 677 | ast = rb_parser_compile(p, gets, ptr, len, enc, input, line); | ^~~ ../src/internal/parse.h:58:128: note: passing argument to parameter 'fname_enc' here 58 | rb_ast_t *rb_parser_compile(rb_parser_t *p, rb_parser_lex_gets_func *gets, const char *fname_ptr, long fname_len, rb_encoding *fname_enc, rb_parser_input_data input, int line); | ^ ``` --- internal/parse.h | 2 +- ruby_parser.c | 98 +++++++++++++++++++++++----------------------- rubyparser.h | 2 +- universal_parser.c | 2 +- 4 files changed, 53 insertions(+), 51 deletions(-) diff --git a/internal/parse.h b/internal/parse.h index a7e8e08912315f..5f52e8a8e3aacf 100644 --- a/internal/parse.h +++ b/internal/parse.h @@ -13,7 +13,7 @@ #include "internal/static_assert.h" #ifdef UNIVERSAL_PARSER -#define rb_encoding void +#define rb_encoding const void #endif struct rb_iseq_struct; /* in vm_core.h */ diff --git a/ruby_parser.c b/ruby_parser.c index f9d4e6d59ce0ac..1dcdfd8e79ecd8 100644 --- a/ruby_parser.c +++ b/ruby_parser.c @@ -32,6 +32,8 @@ #include "vm_core.h" #include "symbol.h" +#define parser_encoding const void + static int is_ascii_string2(VALUE str) { @@ -41,9 +43,9 @@ is_ascii_string2(VALUE str) RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0) static VALUE syntax_error_append(VALUE exc, VALUE file, int line, int column, - void *enc, const char *fmt, va_list args) + parser_encoding *enc, const char *fmt, va_list args) { - return rb_syntax_error_append(exc, file, line, column, (rb_encoding *)enc, fmt, args); + return rb_syntax_error_append(exc, file, line, column, enc, fmt, args); } static int @@ -59,9 +61,9 @@ dvar_defined(ID id, const void *p) } static int -is_usascii_enc(void *enc) +is_usascii_enc(parser_encoding *enc) { - return rb_is_usascii_enc((rb_encoding *)enc); + return rb_is_usascii_enc(enc); } static int @@ -83,21 +85,21 @@ is_notop_id2(ID id) } static VALUE -enc_str_new(const char *ptr, long len, void *enc) +enc_str_new(const char *ptr, long len, parser_encoding *enc) { - return rb_enc_str_new(ptr, len, (rb_encoding *)enc); + return rb_enc_str_new(ptr, len, enc); } static int -enc_isalnum(OnigCodePoint c, void *enc) +enc_isalnum(OnigCodePoint c, parser_encoding *enc) { - return rb_enc_isalnum(c, (rb_encoding *)enc); + return rb_enc_isalnum(c, enc); } static int -enc_precise_mbclen(const char *p, const char *e, void *enc) +enc_precise_mbclen(const char *p, const char *e, parser_encoding *enc) { - return rb_enc_precise_mbclen(p, e, (rb_encoding *)enc); + return rb_enc_precise_mbclen(p, e, enc); } static int @@ -113,93 +115,93 @@ mbclen_charfound_len(int len) } static const char * -enc_name(void *enc) +enc_name(parser_encoding *enc) { - return rb_enc_name((rb_encoding *)enc); + return rb_enc_name(enc); } static char * -enc_prev_char(const char *s, const char *p, const char *e, void *enc) +enc_prev_char(const char *s, const char *p, const char *e, parser_encoding *enc) { - return rb_enc_prev_char(s, p, e, (rb_encoding *)enc); + return rb_enc_prev_char(s, p, e, enc); } -static void * +static parser_encoding * enc_get(VALUE obj) { - return (void *)rb_enc_get(obj); + return rb_enc_get(obj); } static int -enc_asciicompat(void *enc) +enc_asciicompat(parser_encoding *enc) { - return rb_enc_asciicompat((rb_encoding *)enc); + return rb_enc_asciicompat(enc); } -static void * +static parser_encoding * utf8_encoding(void) { - return (void *)rb_utf8_encoding(); + return rb_utf8_encoding(); } static VALUE -enc_associate(VALUE obj, void *enc) +enc_associate(VALUE obj, parser_encoding *enc) { - return rb_enc_associate(obj, (rb_encoding *)enc); + return rb_enc_associate(obj, enc); } -static void * +static parser_encoding * ascii8bit_encoding(void) { - return (void *)rb_ascii8bit_encoding(); + return rb_ascii8bit_encoding(); } static int -enc_codelen(int c, void *enc) +enc_codelen(int c, parser_encoding *enc) { - return rb_enc_codelen(c, (rb_encoding *)enc); + return rb_enc_codelen(c, enc); } static int -enc_mbcput(unsigned int c, void *buf, void *enc) +enc_mbcput(unsigned int c, void *buf, parser_encoding *enc) { - return rb_enc_mbcput(c, buf, (rb_encoding *)enc); + return rb_enc_mbcput(c, buf, enc); } static int -enc_mbclen(const char *p, const char *e, void *enc) +enc_mbclen(const char *p, const char *e, parser_encoding *enc) { - return rb_enc_mbclen(p, e, (rb_encoding *)enc); + return rb_enc_mbclen(p, e, enc); } -static void * +static parser_encoding * enc_from_index(int idx) { - return (void *)rb_enc_from_index(idx); + return rb_enc_from_index(idx); } static int -enc_isspace(OnigCodePoint c, void *enc) +enc_isspace(OnigCodePoint c, parser_encoding *enc) { - return rb_enc_isspace(c, (rb_encoding *)enc); + return rb_enc_isspace(c, enc); } static ID -intern3(const char *name, long len, void *enc) +intern3(const char *name, long len, parser_encoding *enc) { - return rb_intern3(name, len, (rb_encoding *)enc); + return rb_intern3(name, len, enc); } -static void * +static parser_encoding * usascii_encoding(void) { - return (void *)rb_usascii_encoding(); + return rb_usascii_encoding(); } static int -enc_symname_type(const char *name, long len, void *enc, unsigned int allowed_attrset) +enc_symname_type(const char *name, long len, parser_encoding *enc, unsigned int allowed_attrset) { - return rb_enc_symname_type(name, len, (rb_encoding *)enc, allowed_attrset); + return rb_enc_symname_type(name, len, enc, allowed_attrset); } typedef struct { @@ -220,7 +222,7 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end, long len = name_end - name; const char *s = (const char *)name; - return rb_reg_named_capture_assign_iter_impl(p, s, len, (void *)enc, &arg->succ_block, loc); + return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, loc); } static NODE * @@ -305,25 +307,25 @@ static_id2sym(ID id) } static long -str_coderange_scan_restartable(const char *s, const char *e, void *enc, int *cr) +str_coderange_scan_restartable(const char *s, const char *e, parser_encoding *enc, int *cr) { - return rb_str_coderange_scan_restartable(s, e, (rb_encoding *)enc, cr); + return rb_str_coderange_scan_restartable(s, e, enc, cr); } static int -enc_mbminlen(void *enc) +enc_mbminlen(parser_encoding *enc) { - return rb_enc_mbminlen((rb_encoding *)enc); + return rb_enc_mbminlen(enc); } static bool -enc_isascii(OnigCodePoint c, void *enc) +enc_isascii(OnigCodePoint c, parser_encoding *enc) { - return rb_enc_isascii(c, (rb_encoding *)enc); + return rb_enc_isascii(c, enc); } static OnigCodePoint -enc_mbc_to_codepoint(const char *p, const char *e, void *enc) +enc_mbc_to_codepoint(const char *p, const char *e, parser_encoding *enc) { const OnigUChar *up = RBIMPL_CAST((const OnigUChar *)p); const OnigUChar *ue = RBIMPL_CAST((const OnigUChar *)e); diff --git a/rubyparser.h b/rubyparser.h index cb90b847b66769..fc8be9633aa2ae 100644 --- a/rubyparser.h +++ b/rubyparser.h @@ -9,7 +9,7 @@ #ifdef UNIVERSAL_PARSER -#define rb_encoding void +#define rb_encoding const void #define OnigCodePoint unsigned int #include "parser_st.h" #ifndef RUBY_RUBY_H diff --git a/universal_parser.c b/universal_parser.c index 05445587ba0bc9..c5e557ca30370a 100644 --- a/universal_parser.c +++ b/universal_parser.c @@ -59,7 +59,7 @@ #undef st_lookup #define st_lookup rb_parser_st_lookup -#define rb_encoding void +#define rb_encoding const void #undef xmalloc #define xmalloc p->config->malloc From e9262983430e7a758a4151e39151062ac00d67bf Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Fri, 10 May 2024 16:11:51 +0200 Subject: [PATCH 082/151] [rubygems/rubygems] Require things right before they're needed https://github.com/rubygems/rubygems/commit/07022e3f2f --- lib/bundler/rubygems_ext.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index a7539f4adb7d46..0cd94d60ce6e9c 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -4,8 +4,6 @@ require "rubygems" unless defined?(Gem) -require "rubygems/specification" - # We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source` # redefinition below, so we need to load it upfront. The reason is that if # Bundler monkeypatches are loaded before RubyGems activates an executable (for @@ -17,10 +15,6 @@ # `Gem::Source` from the redefined `Gem::Specification#source`. require "rubygems/source" -require_relative "match_metadata" -require_relative "force_platform" -require_relative "match_platform" - # Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler # versions and ignore patchlevels # (https://github.com/rubygems/rubygems/pull/5472, @@ -31,7 +25,12 @@ end module Gem + require "rubygems/specification" + class Specification + require_relative "match_metadata" + require_relative "match_platform" + include ::Bundler::MatchMetadata include ::Bundler::MatchPlatform @@ -148,17 +147,23 @@ def dependencies_to_gemfile(dependencies, group = nil) module BetterPermissionError def data + require_relative "shared_helpers" + Bundler::SharedHelpers.filesystem_access(loaded_from, :read) do super end end end + require "rubygems/stub_specification" + class StubSpecification prepend BetterPermissionError end class Dependency + require_relative "force_platform" + include ::Bundler::ForcePlatform attr_accessor :source, :groups From 69c87619bd7a69936c44cc0d323b11148400e894 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Fri, 10 May 2024 16:14:26 +0200 Subject: [PATCH 083/151] [rubygems/rubygems] Avoid standard requires while loading shared helpers We should make sure Bundler does not trigger RubyGems require logic for gem activation until it had the chance to register its own monkeypatches to RubyGems. https://github.com/rubygems/rubygems/commit/fbd2ff86b9 --- lib/bundler/constants.rb | 2 ++ lib/bundler/rubygems_integration.rb | 6 ++---- lib/bundler/shared_helpers.rb | 10 ++++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/bundler/constants.rb b/lib/bundler/constants.rb index de9698b577e41b..bcbd228b187650 100644 --- a/lib/bundler/constants.rb +++ b/lib/bundler/constants.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "rbconfig" + module Bundler WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/ FREEBSD = RbConfig::CONFIG["host_os"].to_s.include?("bsd") diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 494030eab22846..6980b32236e503 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -4,9 +4,7 @@ module Bundler class RubygemsIntegration - require "monitor" - - EXT_LOCK = Monitor.new + autoload :Monitor, "monitor" def initialize @replaced_methods = {} @@ -173,7 +171,7 @@ def ui=(obj) end def ext_lock - EXT_LOCK + @ext_lock ||= Monitor.new end def spec_from_gem(path) diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb index 78760e6fa48c64..28f0cdff192c66 100644 --- a/lib/bundler/shared_helpers.rb +++ b/lib/bundler/shared_helpers.rb @@ -1,15 +1,17 @@ # frozen_string_literal: true -require "pathname" -require "rbconfig" - require_relative "version" -require_relative "constants" require_relative "rubygems_integration" require_relative "current_ruby" module Bundler + autoload :WINDOWS, File.expand_path("constants", __dir__) + autoload :FREEBSD, File.expand_path("constants", __dir__) + autoload :NULL, File.expand_path("constants", __dir__) + module SharedHelpers + autoload :Pathname, "pathname" + def root gemfile = find_gemfile raise GemfileNotFound, "Could not locate Gemfile" unless gemfile From 899568cce9f2929c765738bf52fcadaead953187 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 15:25:26 +0200 Subject: [PATCH 084/151] [rubygems/rubygems] Fix error when Bundler installation is corrupted If one upgrades the default copy of Bundler through `gem update --system`, and then reinstalls Ruby without removing the previous copy. Then the new installation will have a correct default bundler gemspec, but a higher copy installed in site_dir. This causes a crash when running Bundler and prints the bug report template. This could probably be fixed in Ruby install script, by removing any previous Bundler default copies, but if the problem is already there, I think it's best to print a proper user error. https://github.com/rubygems/rubygems/commit/ada6de765d --- lib/bundler/errors.rb | 14 +++++++++++++ lib/bundler/source/metadata.rb | 2 ++ spec/bundler/commands/install_spec.rb | 29 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb index b6a11cc7219518..c29b1bfed89122 100644 --- a/lib/bundler/errors.rb +++ b/lib/bundler/errors.rb @@ -230,4 +230,18 @@ def message status_code(38) end + + class CorruptBundlerInstallError < BundlerError + def initialize(loaded_spec) + @loaded_spec = loaded_spec + end + + def message + "The running version of Bundler (#{Bundler::VERSION}) does not match the version of the specification installed for it (#{@loaded_spec.version}). " \ + "This can be caused by reinstalling Ruby without removing previous installation, leaving around an upgraded default version of Bundler. " \ + "Reinstalling Ruby from scratch should fix the problem." + end + + status_code(39) + end end diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb index 4d27761365385e..6b05e177271be1 100644 --- a/lib/bundler/source/metadata.rb +++ b/lib/bundler/source/metadata.rb @@ -11,6 +11,8 @@ def specs end if local_spec = Gem.loaded_specs["bundler"] + raise CorruptBundlerInstallError.new(local_spec) if local_spec.version.to_s != Bundler::VERSION + idx << local_spec else idx << Gem::Specification.new do |s| diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb index 1e57414377e76f..edc5887d7bceda 100644 --- a/spec/bundler/commands/install_spec.rb +++ b/spec/bundler/commands/install_spec.rb @@ -1407,4 +1407,33 @@ def run expect(bundled_app(".bundle/config")).not_to exist end end + + context "when bundler installation is corrupt" do + before do + system_gems "bundler-9.99.8" + + replace_version_file("9.99.9", dir: system_gem_path("gems/bundler-9.99.8")) + end + + it "shows a proper error" do + lockfile <<~L + GEM + remote: #{file_uri_for(gem_repo1)}/ + specs: + + PLATFORMS + #{lockfile_platforms} + + DEPENDENCIES + + BUNDLED WITH + 9.99.8 + L + + install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", env: { "BUNDLER_VERSION" => "9.99.8" }, raise_on_error: false + + expect(err).not_to include("ERROR REPORT TEMPLATE") + expect(err).to include("The running version of Bundler (9.99.9) does not match the version of the specification installed for it (9.99.8)") + end + end end From a86ad47c940dee19bfe74a374c5ac61752026b7c Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 15:56:37 +0200 Subject: [PATCH 085/151] [rubygems/rubygems] Improve plugin removal test Instead of unit testing the `remove_plugins` method, test the whole removal process. https://github.com/rubygems/rubygems/commit/bfdc60af98 --- test/rubygems/test_gem_uninstaller.rb | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index 9e0c1aa3d89397..cd6d560ece1c86 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -188,20 +188,29 @@ def test_remove_plugins refute File.exist?(plugin_path), "plugin not removed" end - def test_remove_plugins_with_install_dir + def test_uninstall_with_install_dir_removes_plugins write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "# do nothing" end @spec.files += %w[lib/rubygems_plugin.rb] - Gem::Installer.at(Gem::Package.build(@spec), force: true).install + package = Gem::Package.build(@spec) + + Gem::Installer.at(package, force: true).install plugin_path = File.join Gem.plugindir, "a_plugin.rb" assert File.exist?(plugin_path), "plugin not written" - Dir.mkdir "#{@gemhome}2" - Gem::Uninstaller.new(nil, install_dir: "#{@gemhome}2").remove_plugins @spec + install_dir = "#{@gemhome}2" + + Gem::Installer.at(package, force: true, install_dir: install_dir).install + + install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb" + assert File.exist?(install_dir_plugin_path), "plugin not written" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall assert File.exist?(plugin_path), "plugin unintentionally removed" end From 5880103450faf26da193ac914421957e37d71604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Mon, 13 Mar 2023 14:32:19 +0100 Subject: [PATCH 086/151] [rubygems/rubygems] Use spec.base_dir to remove plugins The plugin loader from `@gem_home` was removed during uninstallation. However, this could leave behind the plugins for `--user-install` installed gems. Use `Gem::Specifictaions#base_dir` instead. This ensures that the plugin loader for associated .gemspec is uninstalled. https://github.com/rubygems/rubygems/commit/6047f78210 --- lib/rubygems/uninstaller.rb | 9 ++++++--- test/rubygems/test_gem_uninstaller.rb | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index c96df2a08536bb..f4202caa0a5a0f 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -50,7 +50,6 @@ def initialize(gem, options = {}) @gem = gem @version = options[:version] || Gem::Requirement.default @gem_home = File.realpath(options[:install_dir] || Gem.dir) - @plugins_dir = Gem.plugindir(@gem_home) @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @@ -284,7 +283,7 @@ def remove(spec) def remove_plugins(spec) # :nodoc: return if spec.plugins.empty? - remove_plugins_for(spec, @plugins_dir) + remove_plugins_for(spec, plugin_dir_for(spec)) end ## @@ -294,7 +293,7 @@ def regenerate_plugins latest = Gem::Specification.latest_spec_for(@spec.name) return if latest.nil? - regenerate_plugins_for(latest, @plugins_dir) + regenerate_plugins_for(latest, plugin_dir_for(@spec)) end ## @@ -406,4 +405,8 @@ def warn_cannot_uninstall_default_gems(specs) say "Gem #{spec.full_name} cannot be uninstalled because it is a default gem" end end + + def plugin_dir_for(spec) + Gem.plugindir(spec.base_dir) + end end diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index cd6d560ece1c86..20a0005341475c 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -215,6 +215,25 @@ def test_uninstall_with_install_dir_removes_plugins assert File.exist?(plugin_path), "plugin unintentionally removed" end + def test_remove_plugins_user_installed + write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| + io.write "# do nothing" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + Gem::Installer.at(Gem::Package.build(@spec), force: true, user_install: true).install + + plugin_path = File.join Gem.user_dir, "plugins/a_plugin.rb" + assert File.exist?(plugin_path), "plugin not written" + + Gem::Specification.dirs = [Gem.dir, Gem.user_dir] + + Gem::Uninstaller.new(@spec.name, executables: true, force: true, user_install: true).uninstall + + refute File.exist?(plugin_path), "plugin not removed" + end + def test_regenerate_plugins_for write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| io.write "# do nothing" From 02c8e6583b33c62b4050420234167a467f32fefa Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 20 Feb 2024 11:05:30 -0800 Subject: [PATCH 087/151] [rubygems/rubygems] Use a constant empty tar header to avoid extra allocations https://github.com/rubygems/rubygems/commit/716666f65f --- lib/rubygems/package/tar_header.rb | 24 +++++++++++++++---- test/rubygems/test_gem_package_tar_header.rb | 25 ++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb index 087f13f6c9e117..dd5e835a1e59b1 100644 --- a/lib/rubygems/package/tar_header.rb +++ b/lib/rubygems/package/tar_header.rb @@ -95,14 +95,14 @@ class Gem::Package::TarHeader attr_reader(*FIELDS) - EMPTY_HEADER = ("\0" * 512).freeze # :nodoc: + EMPTY_HEADER = ("\0" * 512).b.freeze # :nodoc: ## # Creates a tar header from IO +stream+ def self.from(stream) header = stream.read 512 - empty = (header == EMPTY_HEADER) + return EMPTY if header == EMPTY_HEADER fields = header.unpack UNPACK_FORMAT @@ -123,7 +123,7 @@ def self.from(stream) devminor: strict_oct(fields.shift), prefix: fields.shift, - empty: empty + empty: false end def self.strict_oct(str) @@ -172,6 +172,22 @@ def initialize(vals) @empty = vals[:empty] end + EMPTY = new({ # :nodoc: + checksum: 0, + gname: "", + linkname: "", + magic: "", + mode: 0, + name: "", + prefix: "", + size: 0, + uname: "", + version: 0, + + empty: true, + }).freeze + private_constant :EMPTY + ## # Is the tar entry empty? @@ -241,7 +257,7 @@ def header(checksum = @checksum) header = header.pack PACK_FORMAT - header << ("\0" * ((512 - header.size) % 512)) + header.ljust 512, "\0" end def oct(num, len) diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb index 4469750f9a5657..a3f95bb7704f91 100644 --- a/test/rubygems/test_gem_package_tar_header.rb +++ b/test/rubygems/test_gem_package_tar_header.rb @@ -99,6 +99,31 @@ def test_empty_eh assert_empty @tar_header end + def test_empty + @tar_header = Gem::Package::TarHeader.from(StringIO.new(Gem::Package::TarHeader::EMPTY_HEADER)) + + assert_empty @tar_header + assert_equal Gem::Package::TarHeader.new( + checksum: 0, + devmajor: 0, + devminor: 0, + empty: true, + gid: 0, + gname: "", + linkname: "", + magic: "", + mode: 0, + mtime: 0, + name: "", + prefix: "", + size: 0, + typeflag: "0", + uid: 0, + uname: "", + version: 0, + ), @tar_header + end + def test_equals2 assert_equal @tar_header, @tar_header assert_equal @tar_header, @tar_header.dup From e6340258f88064cabba5150cfef1f8898f6aa9d8 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 13 May 2024 11:26:39 -0400 Subject: [PATCH 088/151] [ruby/prism] Autoload newlines and comment visitors Having the @newline instance variable in every node adds up, and since it is so rarely used, we only want to add it when necessary. Moving this into an autoloaded file and moving the instance variable out of the default initializers reduces allocated memory because the nodes are now smaller and some fit into the compact list. On my machine, I'm seeing about an 8% drop. https://github.com/ruby/prism/commit/eea92c07d2 --- lib/prism.rb | 2 - lib/prism/parse_result.rb | 17 +++ lib/prism/parse_result/comments.rb | 7 -- lib/prism/parse_result/newlines.rb | 111 ++++++++++++++++-- .../lib/prism/inspect_visitor.rb.erb | 7 +- prism/templates/lib/prism/node.rb.erb | 32 ----- 6 files changed, 118 insertions(+), 58 deletions(-) diff --git a/lib/prism.rb b/lib/prism.rb index 19774538e7a9e1..2bb7f79bf644d0 100644 --- a/lib/prism.rb +++ b/lib/prism.rb @@ -71,8 +71,6 @@ def self.load(source, serialized) require_relative "prism/node" require_relative "prism/node_ext" require_relative "prism/parse_result" -require_relative "prism/parse_result/comments" -require_relative "prism/parse_result/newlines" # This is a Ruby implementation of the prism parser. If we're running on CRuby # and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 63cc72a96640b2..798fde09e5a7c8 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -574,6 +574,12 @@ def failure? # This is a result specific to the `parse` and `parse_file` methods. class ParseResult < Result + autoload :Comments, "prism/parse_result/comments" + autoload :Newlines, "prism/parse_result/newlines" + + private_constant :Comments + private_constant :Newlines + # The syntax tree that was parsed from the source code. attr_reader :value @@ -587,6 +593,17 @@ def initialize(value, comments, magic_comments, data_loc, errors, warnings, sour def deconstruct_keys(keys) super.merge!(value: value) end + + # Attach the list of comments to their respective locations in the tree. + def attach_comments! + Comments.new(self).attach! # steep:ignore + end + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + def mark_newlines! + value.accept(Newlines.new(source.offsets.size)) # steep:ignore + end end # This is a result specific to the `lex` and `lex_file` methods. diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb index 3fa0603d74ce71..22c4148b2c168c 100644 --- a/lib/prism/parse_result/comments.rb +++ b/lib/prism/parse_result/comments.rb @@ -183,12 +183,5 @@ def nearest_targets(node, comment) [preceding, NodeTarget.new(node), following] end end - - private_constant :Comments - - # Attach the list of comments to their respective locations in the tree. - def attach_comments! - Comments.new(self).attach! # steep:ignore - end end end diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb index 4a8151cc09a090..cc1343dfdacc28 100644 --- a/lib/prism/parse_result/newlines.rb +++ b/lib/prism/parse_result/newlines.rb @@ -17,21 +17,26 @@ class ParseResult < Result # Note that the logic in this file should be kept in sync with the Java # MarkNewlinesVisitor, since that visitor is responsible for marking the # newlines for JRuby/TruffleRuby. + # + # This file is autoloaded only when `mark_newlines!` is called, so the + # re-opening of the various nodes in this file will only be performed in + # that case. We do that to avoid storing the extra `@newline` instance + # variable on every node if we don't need it. class Newlines < Visitor # Create a new Newlines visitor with the given newline offsets. - def initialize(newline_marked) - @newline_marked = newline_marked + def initialize(lines) + @lines = Array.new(1 + lines, false) end # Permit block/lambda nodes to mark newlines within themselves. def visit_block_node(node) - old_newline_marked = @newline_marked - @newline_marked = Array.new(old_newline_marked.size, false) + old_lines = @lines + @lines = Array.new(old_lines.size, false) begin super(node) ensure - @newline_marked = old_newline_marked + @lines = old_lines end end @@ -39,7 +44,7 @@ def visit_block_node(node) # Mark if/unless nodes as newlines. def visit_if_node(node) - node.set_newline_flag(@newline_marked) + node.newline!(@lines) super(node) end @@ -48,17 +53,101 @@ def visit_if_node(node) # Permit statements lists to mark newlines within themselves. def visit_statements_node(node) node.body.each do |child| - child.set_newline_flag(@newline_marked) + child.newline!(@lines) end super(node) end end + end + + class Node + def newline? # :nodoc: + @newline ? true : false + end + + def newline!(lines) # :nodoc: + line = location.start_line + unless lines[line] + lines[line] = true + @newline = true + end + end + end + + class BeginNode < Node + def newline!(lines) # :nodoc: + # Never mark BeginNode with a newline flag, mark children instead. + end + end + + class ParenthesesNode < Node + def newline!(lines) # :nodoc: + # Never mark ParenthesesNode with a newline flag, mark children instead. + end + end + + class IfNode < Node + def newline!(lines) # :nodoc: + predicate.newline!(lines) + end + end + + class UnlessNode < Node + def newline!(lines) # :nodoc: + predicate.newline!(lines) + end + end + + class UntilNode < Node + def newline!(lines) # :nodoc: + predicate.newline!(lines) + end + end + + class WhileNode < Node + def newline!(lines) # :nodoc: + predicate.newline!(lines) + end + end + + class RescueModifierNode < Node + def newline!(lines) # :nodoc: + expression.newline!(lines) + end + end + + class InterpolatedMatchLastLineNode < Node + def newline!(lines) # :nodoc: + first = parts.first + first.newline!(lines) if first + end + end + + class InterpolatedRegularExpressionNode < Node + def newline!(lines) # :nodoc: + first = parts.first + first.newline!(lines) if first + end + end + + class InterpolatedStringNode < Node + def newline!(lines) # :nodoc: + first = parts.first + first.newline!(lines) if first + end + end - private_constant :Newlines + class InterpolatedSymbolNode < Node + def newline!(lines) # :nodoc: + first = parts.first + first.newline!(lines) if first + end + end - # Walk the tree and mark nodes that are on a new line. - def mark_newlines! - value.accept(Newlines.new(Array.new(1 + source.offsets.size, false))) # steep:ignore + class InterpolatedXStringNode < Node + def newline!(lines) # :nodoc: + first = parts.first + first.newline!(lines) if first end end end diff --git a/prism/templates/lib/prism/inspect_visitor.rb.erb b/prism/templates/lib/prism/inspect_visitor.rb.erb index 8e7902f0f1ff2d..9328da636b0739 100644 --- a/prism/templates/lib/prism/inspect_visitor.rb.erb +++ b/prism/templates/lib/prism/inspect_visitor.rb.erb @@ -116,13 +116,8 @@ module Prism # Compose a header for the given node. def inspect_node(name, node) - result = +"@ #{name} (" - location = node.location - result << "location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column})" - result << ", newline: true" if node.newline? - - result << ")\n" + "@ #{name} (location: (#{location.start_line},#{location.start_column})-(#{location.end_line},#{location.end_column}))\n" end # Compose a string representing the given inner location field. diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 50e622a8d12ca8..f0ce226defcff9 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -28,18 +28,6 @@ module Prism location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF)) end - def newline? # :nodoc: - @newline ? true : false - end - - def set_newline_flag(newline_marked) # :nodoc: - line = location.start_line - unless newline_marked[line] - newline_marked[line] = true - @newline = true - end - end - # Returns all of the lines of the source code associated with this node. def source_lines location.source_lines @@ -181,7 +169,6 @@ module Prism # def initialize: (<%= (node.fields.map { |field| "#{field.rbs_class} #{field.name}" } + ["Location location"]).join(", ") %>) -> void def initialize(source, <%= (node.fields.map(&:name) + ["location"]).join(", ") %>) @source = source - @newline = false @location = location <%- node.fields.each do |field| -%> <%- if Prism::Template::CHECK_FIELD_KIND && field.respond_to?(:check_field_kind) -%> @@ -195,25 +182,6 @@ module Prism def accept(visitor) visitor.visit_<%= node.human %>(self) end - <%- if node.newline == false -%> - - def set_newline_flag(newline_marked) # :nodoc: - # Never mark <%= node.name %> with a newline flag, mark children instead - end - <%- elsif node.newline.is_a?(String) -%> - - def set_newline_flag(newline_marked) # :nodoc: - <%- field = node.fields.find { |f| f.name == node.newline } or raise node.newline -%> - <%- case field -%> - <%- when Prism::Template::NodeField -%> - <%= field.name %>.set_newline_flag(newline_marked) - <%- when Prism::Template::NodeListField -%> - first = <%= field.name %>.first - first.set_newline_flag(newline_marked) if first - <%- else raise field.class.name -%> - <%- end -%> - end - <%- end -%> # def child_nodes: () -> Array[nil | Node] def child_nodes From 5931f857abf704c6fc62a93d2fc933b13950392d Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Mon, 13 May 2024 16:56:01 +0900 Subject: [PATCH 089/151] [ruby/prism] Add error handling for missing `parser` gem in `Prism::Translation` Resolves https://github.com/ruby/prism/pull/2803. This PR adds error handling for missing `parser` gem in `Prism::Translation`. The `parser` gem is a required runtime dependency when using `Prism::Translation::Parser`. But it is not required for other uses of Prism. To avoid unnecessary dependencies, it is not added as a `runtime_dependency` in the prism.gemspec. Instead, if the dependency is missing, instructions are given to add it to Gemfile. ## Before ```console $ bundle exec ruby -e 'require "prism"; require "prism/translation/parser33"' /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require': cannot load such file -- parser (LoadError) from /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' from /Users/koic/src/github.com/ruby/prism/lib/prism/translation/parser.rb:3:in `' from /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' from /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' from /Users/koic/src/github.com/ruby/prism/lib/prism/translation/parser33.rb:6:in `' from /Users/koic/src/github.com/ruby/prism/lib/prism/translation/parser33.rb:4:in `' from /Users/koic/src/github.com/ruby/prism/lib/prism/translation/parser33.rb:3:in `' from /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `require' from /Users/koic/.rbenv/versions/3.3.1/lib/ruby/3.3.0/bundled_gems.rb:74:in `block (2 levels) in replace_require' from -e:1:in `
' ``` ## After ```console $ bundle exec ruby -e 'require "prism"; require "prism/translation/parser33"' Error: Unable to load parser. Add `gem "parser"` to your Gemfile. ``` https://github.com/ruby/prism/commit/4880aec22d --- lib/prism/translation/parser.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index 193bbae406e536..8052e38570c8f8 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -1,6 +1,11 @@ # frozen_string_literal: true -require "parser" +begin + require "parser" +rescue LoadError => e + warn 'Error: Unable to load parser. Add `gem "parser"` to your Gemfile.' + exit! +end module Prism module Translation From b5e53e2f32e19e826eacbf9e2e301b1deae146df Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Mon, 13 May 2024 12:31:47 -0400 Subject: [PATCH 090/151] [ruby/prism] Rescue LoadError for ruby_parser as well https://github.com/ruby/prism/commit/d4eb13e703 --- lib/prism/translation/parser.rb | 6 +++--- lib/prism/translation/ruby_parser.rb | 7 ++++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb index 8052e38570c8f8..3748fc896e9826 100644 --- a/lib/prism/translation/parser.rb +++ b/lib/prism/translation/parser.rb @@ -2,9 +2,9 @@ begin require "parser" -rescue LoadError => e - warn 'Error: Unable to load parser. Add `gem "parser"` to your Gemfile.' - exit! +rescue LoadError + warn(%q{Error: Unable to load parser. Add `gem "parser"` to your Gemfile.}) + exit(1) end module Prism diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb index d01a762a033b24..43aac23be7b7dd 100644 --- a/lib/prism/translation/ruby_parser.rb +++ b/lib/prism/translation/ruby_parser.rb @@ -1,6 +1,11 @@ # frozen_string_literal: true -require "ruby_parser" +begin + require "ruby_parser" +rescue LoadError + warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.}) + exit(1) +end module Prism module Translation From 22dab739714208bde73a7c86ebcc2667e534b39e Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 15:02:43 +0200 Subject: [PATCH 091/151] [rubygems/rubygems] Don't depend on Pathname unnecessarily https://github.com/rubygems/rubygems/commit/8c8aaecc48 --- lib/bundler/rubygems_ext.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 0cd94d60ce6e9c..fa61664a90bc67 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -1,7 +1,5 @@ # frozen_string_literal: true -require "pathname" - require "rubygems" unless defined?(Gem) # We can't let `Gem::Source` be autoloaded in the `Gem::Specification#source` @@ -47,7 +45,7 @@ def source def full_gem_path if source.respond_to?(:root) - Pathname.new(loaded_from).dirname.expand_path(source.root).to_s + File.expand_path(File.dirname(loaded_from), source.root) else rg_full_gem_path end From d1c172dfd0296efda404e85bfc42cd8720b65cea Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 15:03:13 +0200 Subject: [PATCH 092/151] [rubygems/rubygems] Don't load `SharedHelpers` unnecessarily https://github.com/rubygems/rubygems/commit/de4650f629 --- lib/bundler/rubygems_ext.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index fa61664a90bc67..14b870321313c0 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -145,11 +145,9 @@ def dependencies_to_gemfile(dependencies, group = nil) module BetterPermissionError def data - require_relative "shared_helpers" - - Bundler::SharedHelpers.filesystem_access(loaded_from, :read) do - super - end + super + rescue Errno::EACCES + raise Bundler::PermissionError.new(loaded_from, :read) end end From 5319587ac32e168dbaba452585e3f3861082ee8d Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 15:03:32 +0200 Subject: [PATCH 093/151] [rubygems/rubygems] Restore previous way of loading monitor I'm not sure why but this particular change seems to have introduced some flaky test failures. So I'll revert it. https://github.com/rubygems/rubygems/commit/668488014b --- lib/bundler/rubygems_integration.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb index 6980b32236e503..494030eab22846 100644 --- a/lib/bundler/rubygems_integration.rb +++ b/lib/bundler/rubygems_integration.rb @@ -4,7 +4,9 @@ module Bundler class RubygemsIntegration - autoload :Monitor, "monitor" + require "monitor" + + EXT_LOCK = Monitor.new def initialize @replaced_methods = {} @@ -171,7 +173,7 @@ def ui=(obj) end def ext_lock - @ext_lock ||= Monitor.new + EXT_LOCK end def spec_from_gem(path) From 9d01f657b30f51f60ac6dec7fb47d13549d26bcd Mon Sep 17 00:00:00 2001 From: Mari Imaizumi Date: Tue, 14 May 2024 10:58:27 +0900 Subject: [PATCH 094/151] [ruby/reline] Implement the undo command (https://github.com/ruby/reline/pull/701) * Refactor send * Implement the undo command * Fix @past_lines initialization * Improve assertion * Hide to save buffer in insert_pasted_text * Replace @using_delete_command with @undoing * Refactor `@past_lines` https://github.com/ruby/reline/commit/4ab72f9cbd --- lib/reline/key_actor/emacs.rb | 2 +- lib/reline/line_editor.rb | 61 ++++++++++++++++-- test/reline/test_key_actor_emacs.rb | 68 +++++++++++++++++++++ test/reline/yamatanooroti/test_rendering.rb | 13 ++++ 4 files changed, 138 insertions(+), 6 deletions(-) diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb index 9c797ba43e97bc..edd88289a3c940 100644 --- a/lib/reline/key_actor/emacs.rb +++ b/lib/reline/key_actor/emacs.rb @@ -63,7 +63,7 @@ class Reline::KeyActor::Emacs < Reline::KeyActor::Base # 30 ^^ :ed_unassigned, # 31 ^_ - :ed_unassigned, + :undo, # 32 SPACE :ed_insert, # 33 ! diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 4c76932c1097a5..23ece602203432 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -4,7 +4,6 @@ require 'tempfile' class Reline::LineEditor - # TODO: undo # TODO: Use "private alias_method" idiom after drop Ruby 2.5. attr_reader :byte_pointer attr_accessor :confirm_multiline_termination_proc @@ -251,6 +250,8 @@ def reset_variables(prompt = '', encoding:) @resized = false @cache = {} @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0) + @past_lines = [] + @undoing = false reset_line end @@ -948,7 +949,8 @@ def dialog_proc_scope_completion_journey_data unless @waiting_proc byte_pointer_diff = @byte_pointer - old_byte_pointer @byte_pointer = old_byte_pointer - send(@vi_waiting_operator, byte_pointer_diff) + method_obj = method(@vi_waiting_operator) + wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff) cleanup_waiting end else @@ -1009,7 +1011,8 @@ def wrap_method_call(method_symbol, method_obj, key, with_operator = false) if @vi_waiting_operator byte_pointer_diff = @byte_pointer - old_byte_pointer @byte_pointer = old_byte_pointer - send(@vi_waiting_operator, byte_pointer_diff) + method_obj = method(@vi_waiting_operator) + wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff) cleanup_waiting end @kill_ring.process @@ -1106,6 +1109,7 @@ def update(key) end def input_key(key) + save_old_buffer @config.reset_oneshot_key_bindings @dialogs.each do |dialog| if key.char.instance_of?(Symbol) and key.char == dialog.name @@ -1120,7 +1124,6 @@ def input_key(key) finish return end - old_lines = @buffer_of_lines.dup @first_char = false @completion_occurs = false @@ -1134,12 +1137,15 @@ def input_key(key) @completion_journey_state = nil end + push_past_lines unless @undoing + @undoing = false + if @in_pasting clear_dialogs return end - modified = old_lines != @buffer_of_lines + modified = @old_buffer_of_lines != @buffer_of_lines if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion # Auto complete starts only when edited process_insert(force: true) @@ -1148,6 +1154,26 @@ def input_key(key) modified end + def save_old_buffer + @old_buffer_of_lines = @buffer_of_lines.dup + @old_byte_pointer = @byte_pointer.dup + @old_line_index = @line_index.dup + end + + def push_past_lines + if @old_buffer_of_lines != @buffer_of_lines + @past_lines.push([@old_buffer_of_lines, @old_byte_pointer, @old_line_index]) + end + trim_past_lines + end + + MAX_PAST_LINES = 100 + def trim_past_lines + if @past_lines.size > MAX_PAST_LINES + @past_lines.shift + end + end + def scroll_into_view _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position if wrapped_cursor_y < screen_scroll_top @@ -1224,6 +1250,18 @@ def set_current_line(line, byte_pointer = nil) process_auto_indent end + def set_current_lines(lines, byte_pointer = nil, line_index = 0) + cursor = current_byte_pointer_cursor + @buffer_of_lines = lines + @line_index = line_index + if byte_pointer + @byte_pointer = byte_pointer + else + calculate_nearest_cursor(cursor) + end + process_auto_indent + end + def retrieve_completion_block(set_completion_quote_character = false) if Reline.completer_word_break_characters.empty? word_break_regexp = nil @@ -1306,6 +1344,7 @@ def confirm_multiline_termination end def insert_pasted_text(text) + save_old_buffer pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer) post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..) lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1) @@ -1313,6 +1352,7 @@ def insert_pasted_text(text) @buffer_of_lines[@line_index, 1] = lines @line_index += lines.size - 1 @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize + push_past_lines end def insert_text(text) @@ -2487,4 +2527,15 @@ def finish private def vi_editing_mode(key) @config.editing_mode = :vi_insert end + + private def undo(_key) + return if @past_lines.empty? + + @undoing = true + + target_lines, target_cursor_x, target_cursor_y = @past_lines.last + set_current_lines(target_lines, target_cursor_x, target_cursor_y) + + @past_lines.pop + end end diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb index 409a7334cbbe9d..013ca2f7b36040 100644 --- a/test/reline/test_key_actor_emacs.rb +++ b/test/reline/test_key_actor_emacs.rb @@ -1437,4 +1437,72 @@ def test_vi_editing_mode @line_editor.__send__(:vi_editing_mode, nil) assert(@config.editing_mode_is?(:vi_insert)) end + + def test_undo + input_keys("\C-_", false) + assert_line_around_cursor('', '') + input_keys("aあb\C-h\C-h\C-h", false) + assert_line_around_cursor('', '') + input_keys("\C-_", false) + assert_line_around_cursor('a', '') + input_keys("\C-_", false) + assert_line_around_cursor('aあ', '') + input_keys("\C-_", false) + assert_line_around_cursor('aあb', '') + input_keys("\C-_", false) + assert_line_around_cursor('aあ', '') + input_keys("\C-_", false) + assert_line_around_cursor('a', '') + input_keys("\C-_", false) + assert_line_around_cursor('', '') + end + + def test_undo_with_cursor_position + input_keys("abc\C-b\C-h", false) + assert_line_around_cursor('a', 'c') + input_keys("\C-_", false) + assert_line_around_cursor('ab', 'c') + input_keys("あいう\C-b\C-h", false) + assert_line_around_cursor('abあ', 'うc') + input_keys("\C-_", false) + assert_line_around_cursor('abあい', 'うc') + end + + def test_undo_with_multiline + @line_editor.multiline_on + @line_editor.confirm_multiline_termination_proc = proc {} + input_keys("1\n2\n3", false) + assert_whole_lines(["1", "2", "3"]) + assert_line_index(2) + assert_line_around_cursor('3', '') + input_keys("\C-p\C-h\C-h", false) + assert_whole_lines(["1", "3"]) + assert_line_index(0) + assert_line_around_cursor('1', '') + input_keys("\C-_", false) + assert_whole_lines(["1", "", "3"]) + assert_line_index(1) + assert_line_around_cursor('', '') + input_keys("\C-_", false) + assert_whole_lines(["1", "2", "3"]) + assert_line_index(1) + assert_line_around_cursor('2', '') + input_keys("\C-_", false) + assert_whole_lines(["1", "2", ""]) + assert_line_index(2) + assert_line_around_cursor('', '') + input_keys("\C-_", false) + assert_whole_lines(["1", "2"]) + assert_line_index(1) + assert_line_around_cursor('2', '') + end + + def test_undo_with_many_times + str = "a" + "b" * 100 + input_keys(str, false) + 100.times { input_keys("\C-_", false) } + assert_line_around_cursor('a', '') + input_keys("\C-_", false) + assert_line_around_cursor('a', '') + end end diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb index 9e8d7da78fdfe6..37a1c1a1930907 100644 --- a/test/reline/yamatanooroti/test_rendering.rb +++ b/test/reline/yamatanooroti/test_rendering.rb @@ -556,6 +556,19 @@ def test_bracketed_paste EOC end + def test_bracketed_paste_with_undo + omit if Reline.core.io_gate.win? + start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') + write("abc") + write("\e[200~def hoge\r\t3\rend\e[201~") + write("\C-_") + close + assert_screen(<<~EOC) + Multiline REPL. + prompt> abc + EOC + end + def test_backspace_until_returns_to_initial start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.') write("ABC") From b60f09442a0220e2fc053de020fdc58b642f851e Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 10 May 2024 12:28:59 +0300 Subject: [PATCH 095/151] Fix TestPatternMatching#test_deconstruct_keys test Before the change `C.keys` returned keys captured in some previous test case that by chance captured `nil` value what made this test passed successfully. Now it returns keys captured in this test case. --- test/ruby/test_pattern_matching.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb index db6ad06b82d12a..cfe3bd1e1939a3 100644 --- a/test/ruby/test_pattern_matching.rb +++ b/test/ruby/test_pattern_matching.rb @@ -1331,7 +1331,7 @@ def test_deconstruct_keys end assert_block do - case {} + case C.new({}) in {} C.keys == nil end From 4a1e4436a99c5794b022f03e8c0589cf8bae1c71 Mon Sep 17 00:00:00 2001 From: Mari Imaizumi Date: Tue, 14 May 2024 17:18:28 +0900 Subject: [PATCH 096/151] [ruby/reline] Bump version to 0.5.7 (https://github.com/ruby/reline/pull/704) https://github.com/ruby/reline/commit/b9b3d392ff --- lib/reline/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/reline/version.rb b/lib/reline/version.rb index ef7d617a4504fe..46613a59520d21 100644 --- a/lib/reline/version.rb +++ b/lib/reline/version.rb @@ -1,3 +1,3 @@ module Reline - VERSION = '0.5.6' + VERSION = '0.5.7' end From 44f50f41796ee24fbd955fb768ca17f24b99b0ed Mon Sep 17 00:00:00 2001 From: git Date: Tue, 14 May 2024 08:19:43 +0000 Subject: [PATCH 097/151] Update default gems list at 4a1e4436a99c5794b022f03e8c0589 [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 4c950e884f56f1..ce626248a566ad 100644 --- a/NEWS.md +++ b/NEWS.md @@ -51,7 +51,7 @@ The following default gems are updated. * optparse 0.5.0 * prism 0.29.0 * rdoc 6.6.3.1 -* reline 0.5.6 +* reline 0.5.7 * resolv 0.4.0 * stringio 3.1.1 * strscan 3.1.1 From 41e6fd066e8ea82c460ba392a1dd55d624a19763 Mon Sep 17 00:00:00 2001 From: Alexander Ross Date: Tue, 14 May 2024 10:22:36 +0200 Subject: [PATCH 098/151] [DOC] Fix typo in example code for `String#encode` method The example code in the documentation for the `String#encode` method has a typo in the `fallback` option. The example code uses `h` as the fallback option, but it should use `hash` instead to match the variable name in the example code. --- doc/encodings.rdoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/encodings.rdoc b/doc/encodings.rdoc index 97c0d2261600ff..d85099cdbccbba 100644 --- a/doc/encodings.rdoc +++ b/doc/encodings.rdoc @@ -419,7 +419,7 @@ These keyword-value pairs specify encoding options: hash = {"\u3042" => 'xyzzy'} hash.default = 'XYZZY' - s.encode('ASCII', fallback: h) # => "xyzzyfooXYZZY" + s.encode('ASCII', fallback: hash) # => "xyzzyfooXYZZY" def (fallback = "U+%.4X").escape(x) self % x.unpack("U") From 4dc0b2301806cc5214b4cfc40e300b03e893726f Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Fri, 3 May 2024 23:38:05 +0200 Subject: [PATCH 099/151] [rubygems/rubygems] Remove redundant receivers https://github.com/rubygems/rubygems/commit/7b71965a70 --- lib/rubygems/specification.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index a1eaf1248ed6a2..5fedc8bc7963be 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -859,7 +859,7 @@ def self.stubs_for(name) # optionally filtering out specs not matching the current platform # def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc: - installed_stubs = installed_stubs(Gem::Specification.dirs, pattern) + installed_stubs = installed_stubs(dirs, pattern) installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform stubs = installed_stubs + default_stubs(pattern) stubs = stubs.uniq(&:full_name) @@ -1125,7 +1125,7 @@ def self.from_yaml(input) # +prerelease+ is true. def self.latest_specs(prerelease = false) - _latest_specs Gem::Specification.stubs, prerelease + _latest_specs stubs, prerelease end ## From 8d28e635662a44b8f4a0e6dd6d655e0734f99271 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 17:13:48 +0200 Subject: [PATCH 100/151] [rubygems/rubygems] Simplify test teardown If we move test directory removal to the very end, I think we should not leak anything. https://github.com/rubygems/rubygems/commit/fb3d8944b5 --- test/rubygems/helper.rb | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index b90b7f28ebaa3c..771faf6488f3bd 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -76,8 +76,6 @@ class Gem::TestCase < Test::Unit::TestCase attr_accessor :uri # :nodoc: - @@tempdirs = [] - def assert_activate(expected, *specs) specs.each do |spec| case spec @@ -451,8 +449,6 @@ def teardown Dir.chdir @current_dir - FileUtils.rm_rf @tempdir - ENV.replace(@orig_env) Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE @@ -481,12 +477,9 @@ def teardown @back_ui.close - refute_directory_exists @tempdir, "may be still in use" - ghosts = @@tempdirs.filter_map do |test_name, tempdir| - test_name if File.exist?(tempdir) - end - @@tempdirs << [method_name, @tempdir] - assert_empty ghosts + FileUtils.rm_rf @tempdir + + refute_directory_exists @tempdir, "#{@tempdir} used by test #{method_name} is still in use" end def credential_setup From 64542380728b2f0cb0a76a09d08735538350cd9f Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 12:15:44 +0200 Subject: [PATCH 101/151] [rubygems/rubygems] Make `Gem.clear_paths` test less implementation dependent https://github.com/rubygems/rubygems/commit/b545daa95d --- test/rubygems/helper.rb | 10 ++++++++++ test/rubygems/test_gem.rb | 5 ++++- test/rubygems/test_gem_ci_detector.rb | 14 +------------- 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 771faf6488f3bd..856dc535882435 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -534,6 +534,16 @@ def without_any_upwards_gemfiles ENV["BUNDLE_GEMFILE"] = File.join(@tempdir, "Gemfile") end + def with_env(overrides, &block) + @orig_env = ENV.to_h + ENV.replace(overrides) + begin + block.call + ensure + ENV.replace(@orig_env) + end + end + ## # A git_gem is used with a gem dependencies file. The gem created here # has no files, just a gem specification for the given +name+ and +version+. diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3fb66e14072c54..40a473f8d69f8f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -516,7 +516,10 @@ def test_self_clear_paths Gem.clear_paths - assert_nil Gem::Specification.send(:class_variable_get, :@@all) + with_env("GEM_HOME" => "foo", "GEM_PATH" => "bar") do + assert_equal("foo", Gem.dir) + assert_equal("bar", Gem.path.first) + end end def test_self_configuration diff --git a/test/rubygems/test_gem_ci_detector.rb b/test/rubygems/test_gem_ci_detector.rb index 3caefce97d72b1..a28ee49f4b2e55 100644 --- a/test/rubygems/test_gem_ci_detector.rb +++ b/test/rubygems/test_gem_ci_detector.rb @@ -3,7 +3,7 @@ require_relative "helper" require "rubygems" -class TestCiDetector < Test::Unit::TestCase +class TestCiDetector < Gem::TestCase def test_ci? with_env("FOO" => "bar") { assert_equal(false, Gem::CIDetector.ci?) } with_env("CI" => "true") { assert_equal(true, Gem::CIDetector.ci?) } @@ -29,16 +29,4 @@ def test_ci_strings assert_equal(["dsari", "taskcluster"], Gem::CIDetector.ci_strings) end end - - private - - def with_env(overrides, &block) - @orig_env = ENV.to_h - ENV.replace(overrides) - begin - block.call - ensure - ENV.replace(@orig_env) - end - end end From 91e387197010586b0fc815f2a83c77832a0f0aa3 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 15:33:44 +0200 Subject: [PATCH 102/151] [rubygems/rubygems] Simplify documentation I don't think this method is any worse than others, let's only document what it does. https://github.com/rubygems/rubygems/commit/dec722187f --- lib/rubygems/specification.rb | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 5fedc8bc7963be..ca418cd394f371 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -923,16 +923,7 @@ def self.all end ## - # Sets the known specs to +specs+. Not guaranteed to work for you in - # the future. Use at your own risk. Caveat emptor. Doomy doom doom. - # Etc etc. - # - #-- - # Makes +specs+ the known specs - # Listen, time is a river - # Winter comes, code breaks - # - # -- wilsonb + # Sets the known specs to +specs+. def self.all=(specs) @@stubs_by_name = specs.group_by(&:name) From 5628cc1229ea1f53788a263cc0a6ae8df1ad428f Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 15:34:23 +0200 Subject: [PATCH 103/151] [rubygems/rubygems] Add missing docs Other analog methods are documented, so document this one too. https://github.com/rubygems/rubygems/commit/76da34d44d --- lib/rubygems/specification.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index ca418cd394f371..e369516bdd6060 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -1044,6 +1044,10 @@ def self.find_inactive_by_path(path) stub&.to_spec end + ## + # Return the best specification that contains the file matching +path+, among + # those already activated. + def self.find_active_stub_by_path(path) stub = @@active_stub_with_requirable_file[path] ||= stubs.find do |s| s.activated? && s.contains_requirable_file?(path) From c219ee00b446fb22657031aa4a47b9daf72d514c Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 15:36:57 +0200 Subject: [PATCH 104/151] [rubygems/rubygems] Fix typo in attribute documentation https://github.com/rubygems/rubygems/commit/8c9807092c --- lib/rubygems/uninstaller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index f4202caa0a5a0f..7dad521a93b9df 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -32,7 +32,7 @@ class Gem::Uninstaller attr_reader :bin_dir ## - # The gem repository the gem will be installed into + # The gem repository the gem will be uninstalled from attr_reader :gem_home From bd8423616947738d2efb3602791db91587b822bb Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 15:41:42 +0200 Subject: [PATCH 105/151] [rubygems/rubygems] Extract a `Gem::SpecificationRecord` class This class handles all logic to handle the list of specifications, given a set of GEM_PATH directories. Makes `Gem::Specification` has less responsibilities and will help with fixing some bugs next. https://github.com/rubygems/rubygems/commit/df280dbbed --- lib/rubygems/specification.rb | 107 ++++----------- lib/rubygems/specification_record.rb | 171 ++++++++++++++++++++++++ test/rubygems/test_gem_specification.rb | 11 +- 3 files changed, 202 insertions(+), 87 deletions(-) create mode 100644 lib/rubygems/specification_record.rb diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index e369516bdd6060..e27901923e772d 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -11,6 +11,7 @@ require_relative "basic_specification" require_relative "stub_specification" require_relative "platform" +require_relative "specification_record" require_relative "util/list" require "rbconfig" @@ -179,19 +180,9 @@ class Gem::Specification < Gem::BasicSpecification @@default_value[k].nil? end - def self.clear_specs # :nodoc: - @@all = nil - @@stubs = nil - @@stubs_by_name = {} - @@spec_with_requirable_file = {} - @@active_stub_with_requirable_file = {} - end - private_class_method :clear_specs - - clear_specs - # Sentinel object to represent "not found" stubs NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc: + deprecate_constant :NOT_FOUND # Tracking removed method calls to warn users during build time. REMOVED_METHODS = [:rubyforge_project=, :mark_version].freeze # :nodoc: @@ -770,7 +761,7 @@ def extensions_dir attr_accessor :specification_version def self._all # :nodoc: - @@all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) + specification_record.all end def self.clear_load_cache # :nodoc: @@ -788,26 +779,9 @@ def self.each_gemspec(dirs) # :nodoc: end end - def self.gemspec_stubs_in(dir, pattern) + def self.gemspec_stubs_in(dir, pattern) # :nodoc: Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?) end - private_class_method :gemspec_stubs_in - - def self.installed_stubs(dirs, pattern) - map_stubs(dirs, pattern) do |path, base_dir, gems_dir| - Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir) - end - end - private_class_method :installed_stubs - - def self.map_stubs(dirs, pattern) # :nodoc: - dirs.flat_map do |dir| - base_dir = File.dirname dir - gems_dir = File.join base_dir, "gems" - gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir } - end - end - private_class_method :map_stubs def self.each_spec(dirs) # :nodoc: each_gemspec(dirs) do |path| @@ -820,13 +794,7 @@ def self.each_spec(dirs) # :nodoc: # Returns a Gem::StubSpecification for every installed gem def self.stubs - @@stubs ||= begin - pattern = "*.gemspec" - stubs = stubs_for_pattern(pattern, false) - - @@stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name) - stubs - end + specification_record.stubs end ## @@ -845,13 +813,7 @@ def self.default_stubs(pattern = "*.gemspec") # only returns stubs that match Gem.platforms def self.stubs_for(name) - if @@stubs - @@stubs_by_name[name] || [] - else - @@stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s| - s.name == name - end - end + specification_record.stubs_for(name) end ## @@ -859,12 +821,7 @@ def self.stubs_for(name) # optionally filtering out specs not matching the current platform # def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc: - installed_stubs = installed_stubs(dirs, pattern) - installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform - stubs = installed_stubs + default_stubs(pattern) - stubs = stubs.uniq(&:full_name) - _resort!(stubs) - stubs + specification_record.stubs_for_pattern(pattern, match_platform) end def self._resort!(specs) # :nodoc: @@ -893,23 +850,14 @@ def self.load_defaults # properly sorted. def self.add_spec(spec) - return if _all.include? spec - - _all << spec - stubs << spec - (@@stubs_by_name[spec.name] ||= []) << spec - - _resort!(@@stubs_by_name[spec.name]) - _resort!(stubs) + specification_record.add_spec(spec) end ## # Removes +spec+ from the known specs. def self.remove_spec(spec) - _all.delete spec.to_spec - stubs.delete spec - (@@stubs_by_name[spec.name] || []).delete spec + specification_record.remove_spec(spec) end ## @@ -926,15 +874,14 @@ def self.all # Sets the known specs to +specs+. def self.all=(specs) - @@stubs_by_name = specs.group_by(&:name) - @@all = @@stubs = specs + specification_record.all = specs end ## # Return full names of all specs in sorted order. def self.all_names - _all.map(&:full_name) + specification_record.all_names end ## @@ -1024,12 +971,7 @@ def self.find_by_full_name(full_name) # Return the best specification that contains the file matching +path+. def self.find_by_path(path) - path = path.dup.freeze - spec = @@spec_with_requirable_file[path] ||= stubs.find do |s| - s.contains_requirable_file? path - end || NOT_FOUND - - spec.to_spec + specification_record.find_by_path(path) end ## @@ -1037,11 +979,7 @@ def self.find_by_path(path) # amongst the specs that are not activated. def self.find_inactive_by_path(path) - stub = stubs.find do |s| - next if s.activated? - s.contains_requirable_file? path - end - stub&.to_spec + specification_record.find_inactive_by_path(path) end ## @@ -1049,11 +987,7 @@ def self.find_inactive_by_path(path) # those already activated. def self.find_active_stub_by_path(path) - stub = @@active_stub_with_requirable_file[path] ||= stubs.find do |s| - s.activated? && s.contains_requirable_file?(path) - end || NOT_FOUND - - stub.this + specification_record.find_active_stub_by_path(path) end ## @@ -1120,14 +1054,14 @@ def self.from_yaml(input) # +prerelease+ is true. def self.latest_specs(prerelease = false) - _latest_specs stubs, prerelease + specification_record.latest_specs(prerelease) end ## # Return the latest installed spec for gem +name+. def self.latest_spec_for(name) - latest_specs(true).find {|installed_spec| installed_spec.name == name } + specification_record.latest_spec_for(name) end def self._latest_specs(specs, prerelease = false) # :nodoc: @@ -1265,7 +1199,7 @@ def self.required_attributes def self.reset @@dirs = nil Gem.pre_reset_hooks.each(&:call) - clear_specs + @specification_record = nil clear_load_cache unresolved = unresolved_deps unless unresolved.empty? @@ -1286,6 +1220,13 @@ def self.reset Gem.post_reset_hooks.each(&:call) end + ## + # Keeps track of all currently known specifications + + def self.specification_record + @specification_record ||= Gem::SpecificationRecord.new(dirs) + end + # DOC: This method needs documented or nodoc'd def self.unresolved_deps @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n } diff --git a/lib/rubygems/specification_record.rb b/lib/rubygems/specification_record.rb new file mode 100644 index 00000000000000..bdce0b3a099184 --- /dev/null +++ b/lib/rubygems/specification_record.rb @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +module Gem + class SpecificationRecord + def initialize(dirs) + @all = nil + @stubs = nil + @stubs_by_name = {} + @spec_with_requirable_file = {} + @active_stub_with_requirable_file = {} + + @dirs = dirs + end + + # Sentinel object to represent "not found" stubs + NOT_FOUND = Struct.new(:to_spec, :this).new + private_constant :NOT_FOUND + + ## + # Returns the list of all specifications in the record + + def all + @all ||= Gem.loaded_specs.values | stubs.map(&:to_spec) + end + + ## + # Returns a Gem::StubSpecification for every specification in the record + + def stubs + @stubs ||= begin + pattern = "*.gemspec" + stubs = stubs_for_pattern(pattern, false) + + @stubs_by_name = stubs.select {|s| Gem::Platform.match_spec? s }.group_by(&:name) + stubs + end + end + + ## + # Returns a Gem::StubSpecification for every specification in the record + # named +name+ only returns stubs that match Gem.platforms + + def stubs_for(name) + if @stubs + @stubs_by_name[name] || [] + else + @stubs_by_name[name] ||= stubs_for_pattern("#{name}-*.gemspec").select do |s| + s.name == name + end + end + end + + ## + # Finds stub specifications matching a pattern in the record, optionally + # filtering out specs not matching the current platform + + def stubs_for_pattern(pattern, match_platform = true) + installed_stubs = installed_stubs(pattern) + installed_stubs.select! {|s| Gem::Platform.match_spec? s } if match_platform + stubs = installed_stubs + Gem::Specification.default_stubs(pattern) + stubs = stubs.uniq(&:full_name) + Gem::Specification._resort!(stubs) + stubs + end + + ## + # Adds +spec+ to the the record, keeping the collection properly sorted. + + def add_spec(spec) + return if all.include? spec + + all << spec + stubs << spec + (@stubs_by_name[spec.name] ||= []) << spec + + Gem::Specification._resort!(@stubs_by_name[spec.name]) + Gem::Specification._resort!(stubs) + end + + ## + # Removes +spec+ from the record. + + def remove_spec(spec) + all.delete spec.to_spec + stubs.delete spec + (@stubs_by_name[spec.name] || []).delete spec + end + + ## + # Sets the specs known by the record to +specs+. + + def all=(specs) + @stubs_by_name = specs.group_by(&:name) + @all = @stubs = specs + end + + ## + # Return full names of all specs in the record in sorted order. + + def all_names + all.map(&:full_name) + end + + ## + # Return the best specification in the record that contains the file matching +path+. + + def find_by_path(path) + path = path.dup.freeze + spec = @spec_with_requirable_file[path] ||= stubs.find do |s| + s.contains_requirable_file? path + end || NOT_FOUND + + spec.to_spec + end + + ## + # Return the best specification in the record that contains the file + # matching +path+ amongst the specs that are not activated. + + def find_inactive_by_path(path) + stub = stubs.find do |s| + next if s.activated? + s.contains_requirable_file? path + end + stub&.to_spec + end + + ## + # Return the best specification in the record that contains the file + # matching +path+, among those already activated. + + def find_active_stub_by_path(path) + stub = @active_stub_with_requirable_file[path] ||= stubs.find do |s| + s.activated? && s.contains_requirable_file?(path) + end || NOT_FOUND + + stub.this + end + + ## + # Return the latest specs in the record, optionally including prerelease + # specs if +prerelease+ is true. + + def latest_specs(prerelease) + Gem::Specification._latest_specs stubs, prerelease + end + + ## + # Return the latest installed spec in the record for gem +name+. + + def latest_spec_for(name) + latest_specs(true).find {|installed_spec| installed_spec.name == name } + end + + private + + def installed_stubs(pattern) + map_stubs(pattern) do |path, base_dir, gems_dir| + Gem::StubSpecification.gemspec_stub(path, base_dir, gems_dir) + end + end + + def map_stubs(pattern) + @dirs.flat_map do |dir| + base_dir = File.dirname dir + gems_dir = File.join base_dir, "gems" + Gem::Specification.gemspec_stubs_in(dir, pattern) {|path| yield path, base_dir, gems_dir } + end + end + end +end diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb index f9f063c7976071..9395e34f75188b 100644 --- a/test/rubygems/test_gem_specification.rb +++ b/test/rubygems/test_gem_specification.rb @@ -967,7 +967,10 @@ def test_self_remove_spec_removed def test_self_stubs_for_lazy_loading Gem.loaded_specs.clear - Gem::Specification.class_variable_set(:@@stubs, nil) + + specification_record = Gem::Specification.specification_record + + specification_record.instance_variable_set(:@stubs, nil) dir_standard_specs = File.join Gem.dir, "specifications" @@ -975,9 +978,9 @@ def test_self_stubs_for_lazy_loading save_gemspec("b-1", "1", dir_standard_specs) {|s| s.name = "b" } assert_equal ["a-1"], Gem::Specification.stubs_for("a").map(&:full_name) - assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length + assert_equal 1, specification_record.instance_variable_get(:@stubs_by_name).length assert_equal ["b-1"], Gem::Specification.stubs_for("b").map(&:full_name) - assert_equal 2, Gem::Specification.class_variable_get(:@@stubs_by_name).length + assert_equal 2, specification_record.instance_variable_get(:@stubs_by_name).length assert_equal( Gem::Specification.stubs_for("a").map(&:object_id), @@ -986,7 +989,7 @@ def test_self_stubs_for_lazy_loading Gem.loaded_specs.delete "a" Gem.loaded_specs.delete "b" - Gem::Specification.class_variable_set(:@@stubs, nil) + specification_record.instance_variable_set(:@stubs, nil) end def test_self_stubs_for_no_lazy_loading_after_all_specs_setup From 965cb3ab4c659a1be96b6f26df68b75d85585978 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 6 May 2024 21:00:14 +0200 Subject: [PATCH 106/151] [rubygems/rubygems] Fix issue when cleaning up plugin stubs When `gem uninstall --install-dir ` is run, if the version removed had a plugin, and that same version happened to also be installed globally, then the plugin stub would fail to be removed. https://github.com/rubygems/rubygems/commit/4e2fa0be77 --- lib/rubygems/specification.rb | 6 ++---- lib/rubygems/specification_record.rb | 10 +++++++++ lib/rubygems/uninstaller.rb | 8 ++++--- test/rubygems/test_gem_uninstaller.rb | 31 +++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index e27901923e772d..eb846095293ef7 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -906,9 +906,7 @@ def self.attribute_names # Return the directories that Specification uses to find specs. def self.dirs - @@dirs ||= Gem.path.collect do |dir| - File.join dir, "specifications" - end + @@dirs ||= Gem::SpecificationRecord.dirs_from(Gem.path) end ## @@ -918,7 +916,7 @@ def self.dirs def self.dirs=(dirs) reset - @@dirs = Array(dirs).map {|dir| File.join dir, "specifications" } + @@dirs = Gem::SpecificationRecord.dirs_from(Array(dirs)) end extend Enumerable diff --git a/lib/rubygems/specification_record.rb b/lib/rubygems/specification_record.rb index bdce0b3a099184..812431fa3297a7 100644 --- a/lib/rubygems/specification_record.rb +++ b/lib/rubygems/specification_record.rb @@ -2,6 +2,16 @@ module Gem class SpecificationRecord + def self.dirs_from(paths) + paths.map do |path| + File.join(path, "specifications") + end + end + + def self.from_path(path) + new(dirs_from([path])) + end + def initialize(dirs) @all = nil @stubs = nil diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index 7dad521a93b9df..e1f82e6a21bdbb 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -49,7 +49,8 @@ def initialize(gem, options = {}) # TODO: document the valid options @gem = gem @version = options[:version] || Gem::Requirement.default - @gem_home = File.realpath(options[:install_dir] || Gem.dir) + @install_dir = options[:install_dir] + @gem_home = File.realpath(@install_dir || Gem.dir) @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @@ -69,7 +70,7 @@ def initialize(gem, options = {}) # only add user directory if install_dir is not set @user_install = false - @user_install = options[:user_install] unless options[:install_dir] + @user_install = options[:user_install] unless @install_dir # Optimization: populated during #uninstall @default_specs_matching_uninstall_params = [] @@ -290,7 +291,8 @@ def remove_plugins(spec) # :nodoc: # Regenerates plugin wrappers after removal. def regenerate_plugins - latest = Gem::Specification.latest_spec_for(@spec.name) + specification_record = @install_dir ? Gem::SpecificationRecord.from_path(@install_dir) : Gem::Specification.specification_record + latest = specification_record.latest_spec_for(@spec.name) return if latest.nil? regenerate_plugins_for(latest, plugin_dir_for(@spec)) diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index 20a0005341475c..eb25b505e6cbd3 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -213,6 +213,37 @@ def test_uninstall_with_install_dir_removes_plugins Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall assert File.exist?(plugin_path), "plugin unintentionally removed" + refute File.exist?(install_dir_plugin_path), "plugin not removed" + end + + def test_uninstall_with_install_dir_regenerates_plugins + write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io| + io.write "# do nothing" + end + + @spec.files += %w[lib/rubygems_plugin.rb] + + install_dir = "#{@gemhome}2" + + package = Gem::Package.build(@spec) + + spec_v9 = @spec.dup + spec_v9.version = "9" + package_v9 = Gem::Package.build(spec_v9) + + Gem::Installer.at(package, force: true, install_dir: install_dir).install + Gem::Installer.at(package_v9, force: true, install_dir: install_dir).install + + install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb" + assert File.exist?(install_dir_plugin_path), "plugin not written" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, version: "9", executables: true, install_dir: install_dir).uninstall + assert File.exist?(install_dir_plugin_path), "plugin unintentionally removed" + + Gem::Specification.dirs = [install_dir] + Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall + refute File.exist?(install_dir_plugin_path), "plugin not removed" end def test_remove_plugins_user_installed From cb1a574e46f38b9598e98a2648969ac818cf2aa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 14 May 2024 02:42:23 +0000 Subject: [PATCH 107/151] Bump github/codeql-action from 3.25.4 to 3.25.5 Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.4 to 3.25.5. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/ccf74c947955fd1cf117aef6a0e4e66191ef6f61...b7cec7526559c32f1616476ff32d17ba4c59b2d6) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/codeql-analysis.yml | 8 ++++---- .github/workflows/scorecards.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8191d6beb29852..5fa6da51700ef7 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -80,15 +80,15 @@ jobs: run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 + uses: github/codeql-action/init@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 with: languages: ${{ matrix.language }} - name: Autobuild - uses: github/codeql-action/autobuild@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 + uses: github/codeql-action/autobuild@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 + uses: github/codeql-action/analyze@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 with: category: '/language:${{ matrix.language }}' upload: False @@ -118,7 +118,7 @@ jobs: continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v3.25.4 + uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5 with: sarif_file: sarif-results/${{ matrix.language }}.sarif continue-on-error: true diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 602902e6a18082..bfc7b958635227 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -67,6 +67,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@ccf74c947955fd1cf117aef6a0e4e66191ef6f61 # v2.1.27 + uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v2.1.27 with: sarif_file: results.sarif From e33336cb37b47834c0448921c6c4942e3fa63996 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 20 Dec 2023 18:30:06 -0800 Subject: [PATCH 108/151] [ruby/zlib] Avoid allocating intermediary strings when read/readpartial are passed an outbuf This accounts for a significant number of string allocations when reading rubygems, but we can avoid that in many places by only copying into the outbuf when present https://github.com/ruby/zlib/commit/d25ef406c1 --- ext/zlib/zlib.c | 105 ++++++++++++++++++++++++++--------------- test/zlib/test_zlib.rb | 25 +++++++++- 2 files changed, 90 insertions(+), 40 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index fe030725760aea..b1623546e674b0 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -90,7 +90,7 @@ static void zstream_expand_buffer_into(struct zstream*, unsigned long); static int zstream_expand_buffer_non_stream(struct zstream *z); static void zstream_append_buffer(struct zstream*, const Bytef*, long); static VALUE zstream_detach_buffer(struct zstream*); -static VALUE zstream_shift_buffer(struct zstream*, long); +static VALUE zstream_shift_buffer(struct zstream*, long, VALUE); static void zstream_buffer_ungets(struct zstream*, const Bytef*, unsigned long); static void zstream_buffer_ungetbyte(struct zstream*, int); static void zstream_append_input(struct zstream*, const Bytef*, long); @@ -170,8 +170,8 @@ static void gzfile_check_footer(struct gzfile*, VALUE outbuf); static void gzfile_write(struct gzfile*, Bytef*, long); static long gzfile_read_more(struct gzfile*, VALUE outbuf); static void gzfile_calc_crc(struct gzfile*, VALUE); -static VALUE gzfile_read(struct gzfile*, long); -static VALUE gzfile_read_all(struct gzfile*); +static VALUE gzfile_read(struct gzfile*, long, VALUE); +static VALUE gzfile_read_all(struct gzfile*, VALUE); static void gzfile_ungets(struct gzfile*, const Bytef*, long); static void gzfile_ungetbyte(struct gzfile*, int); static VALUE gzfile_writer_end_run(VALUE); @@ -820,19 +820,31 @@ zstream_detach_buffer(struct zstream *z) } static VALUE -zstream_shift_buffer(struct zstream *z, long len) +zstream_shift_buffer(struct zstream *z, long len, VALUE dst) { - VALUE dst; char *bufptr; long buflen = ZSTREAM_BUF_FILLED(z); if (buflen <= len) { - return zstream_detach_buffer(z); + if (NIL_P(dst) || (!ZSTREAM_IS_FINISHED(z) && !ZSTREAM_IS_GZFILE(z) && + rb_block_given_p())) { + return zstream_detach_buffer(z); + } else { + bufptr = RSTRING_PTR(z->buf); + rb_str_resize(dst, buflen); + memcpy(RSTRING_PTR(dst), bufptr, buflen); + } + buflen = 0; + } else { + bufptr = RSTRING_PTR(z->buf); + if (NIL_P(dst)) { + dst = rb_str_new(bufptr, len); + } else { + rb_str_resize(dst, len); + memcpy(RSTRING_PTR(dst), bufptr, len); + } + buflen -= len; } - - bufptr = RSTRING_PTR(z->buf); - dst = rb_str_new(bufptr, len); - buflen -= len; memmove(bufptr, bufptr + len, buflen); rb_str_set_len(z->buf, buflen); z->stream.next_out = (Bytef*)RSTRING_END(z->buf); @@ -2874,18 +2886,18 @@ gzfile_newstr(struct gzfile *gz, VALUE str) } static long -gzfile_fill(struct gzfile *gz, long len) +gzfile_fill(struct gzfile *gz, long len, VALUE outbuf) { if (len < 0) rb_raise(rb_eArgError, "negative length %ld given", len); if (len == 0) return 0; while (!ZSTREAM_IS_FINISHED(&gz->z) && ZSTREAM_BUF_FILLED(&gz->z) < len) { - gzfile_read_more(gz, Qnil); + gzfile_read_more(gz, outbuf); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz, Qnil); + gzfile_check_footer(gz, outbuf); } return -1; } @@ -2893,14 +2905,27 @@ gzfile_fill(struct gzfile *gz, long len) } static VALUE -gzfile_read(struct gzfile *gz, long len) +gzfile_read(struct gzfile *gz, long len, VALUE outbuf) { VALUE dst; - len = gzfile_fill(gz, len); - if (len == 0) return rb_str_new(0, 0); - if (len < 0) return Qnil; - dst = zstream_shift_buffer(&gz->z, len); + len = gzfile_fill(gz, len, outbuf); + + if (len < 0) { + if (!NIL_P(outbuf)) + rb_str_resize(outbuf, 0); + return Qnil; + } + if (len == 0) { + if (NIL_P(outbuf)) + return rb_str_new(0, 0); + else { + rb_str_resize(outbuf, 0); + return outbuf; + } + } + + dst = zstream_shift_buffer(&gz->z, len, outbuf); if (!NIL_P(dst)) gzfile_calc_crc(gz, dst); return dst; } @@ -2933,7 +2958,7 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) rb_raise(rb_eEOFError, "end of file reached"); } - dst = zstream_shift_buffer(&gz->z, len); + dst = zstream_shift_buffer(&gz->z, len, outbuf); gzfile_calc_crc(gz, dst); if (!NIL_P(outbuf)) { @@ -2945,17 +2970,19 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) } static VALUE -gzfile_read_all(struct gzfile *gz) +gzfile_read_all(struct gzfile *gz, VALUE dst) { - VALUE dst; - while (!ZSTREAM_IS_FINISHED(&gz->z)) { - gzfile_read_more(gz, Qnil); + gzfile_read_more(gz, dst); } if (GZFILE_IS_FINISHED(gz)) { if (!(gz->z.flags & GZFILE_FLAG_FOOTER_FINISHED)) { - gzfile_check_footer(gz, Qnil); + gzfile_check_footer(gz, dst); } + if (!NIL_P(dst)) { + rb_str_resize(dst, 0); + return dst; + } return rb_str_new(0, 0); } @@ -2993,7 +3020,7 @@ gzfile_getc(struct gzfile *gz) de = (unsigned char *)ds + GZFILE_CBUF_CAPA; (void)rb_econv_convert(gz->ec, &sp, se, &dp, de, ECONV_PARTIAL_INPUT|ECONV_AFTER_OUTPUT); rb_econv_check_error(gz->ec); - dst = zstream_shift_buffer(&gz->z, sp - ss); + dst = zstream_shift_buffer(&gz->z, sp - ss, Qnil); gzfile_calc_crc(gz, dst); rb_str_resize(cbuf, dp - ds); return cbuf; @@ -3001,7 +3028,7 @@ gzfile_getc(struct gzfile *gz) else { buf = gz->z.buf; len = rb_enc_mbclen(RSTRING_PTR(buf), RSTRING_END(buf), gz->enc); - dst = gzfile_read(gz, len); + dst = gzfile_read(gz, len, Qnil); if (NIL_P(dst)) return dst; return gzfile_newstr(gz, dst); } @@ -3909,7 +3936,7 @@ rb_gzreader_s_zcat(int argc, VALUE *argv, VALUE klass) if (!buf) { buf = rb_str_new(0, 0); } - tmpbuf = gzfile_read_all(get_gzfile(obj)); + tmpbuf = gzfile_read_all(get_gzfile(obj), Qnil); rb_str_cat(buf, RSTRING_PTR(tmpbuf), RSTRING_LEN(tmpbuf)); } @@ -4011,19 +4038,19 @@ static VALUE rb_gzreader_read(int argc, VALUE *argv, VALUE obj) { struct gzfile *gz = get_gzfile(obj); - VALUE vlen; + VALUE vlen, outbuf; long len; - rb_scan_args(argc, argv, "01", &vlen); + rb_scan_args(argc, argv, "02", &vlen, &outbuf); if (NIL_P(vlen)) { - return gzfile_read_all(gz); + return gzfile_read_all(gz, outbuf); } len = NUM2INT(vlen); if (len < 0) { rb_raise(rb_eArgError, "negative length %ld given", len); } - return gzfile_read(gz, len); + return gzfile_read(gz, len, outbuf); } /* @@ -4096,7 +4123,7 @@ rb_gzreader_getbyte(VALUE obj) struct gzfile *gz = get_gzfile(obj); VALUE dst; - dst = gzfile_read(gz, 1); + dst = gzfile_read(gz, 1, Qnil); if (!NIL_P(dst)) { dst = INT2FIX((unsigned int)(RSTRING_PTR(dst)[0]) & 0xff); } @@ -4217,7 +4244,7 @@ gzreader_skip_linebreaks(struct gzfile *gz) } } - str = zstream_shift_buffer(&gz->z, n - 1); + str = zstream_shift_buffer(&gz->z, n - 1, Qnil); gzfile_calc_crc(gz, str); } @@ -4238,7 +4265,7 @@ gzreader_charboundary(struct gzfile *gz, long n) if (l < n) { int n_bytes = rb_enc_precise_mbclen(p, e, gz->enc); if (MBCLEN_NEEDMORE_P(n_bytes)) { - if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes))) > 0) { + if ((l = gzfile_fill(gz, n + MBCLEN_NEEDMORE_LEN(n_bytes), Qnil)) > 0) { return l; } } @@ -4290,10 +4317,10 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) if (NIL_P(rs)) { if (limit < 0) { - dst = gzfile_read_all(gz); + dst = gzfile_read_all(gz, Qnil); if (RSTRING_LEN(dst) == 0) return Qnil; } - else if ((n = gzfile_fill(gz, limit)) <= 0) { + else if ((n = gzfile_fill(gz, limit, Qnil)) <= 0) { return Qnil; } else { @@ -4303,7 +4330,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) else { n = limit; } - dst = zstream_shift_buffer(&gz->z, n); + dst = zstream_shift_buffer(&gz->z, n, Qnil); if (NIL_P(dst)) return dst; gzfile_calc_crc(gz, dst); dst = gzfile_newstr(gz, dst); @@ -4330,7 +4357,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) while (ZSTREAM_BUF_FILLED(&gz->z) < rslen) { if (ZSTREAM_IS_FINISHED(&gz->z)) { if (ZSTREAM_BUF_FILLED(&gz->z) > 0) gz->lineno++; - return gzfile_read(gz, rslen); + return gzfile_read(gz, rslen, Qnil); } gzfile_read_more(gz, Qnil); } @@ -4367,7 +4394,7 @@ gzreader_gets(int argc, VALUE *argv, VALUE obj) } gz->lineno++; - dst = gzfile_read(gz, n); + dst = gzfile_read(gz, n, Qnil); if (NIL_P(dst)) return dst; if (rspara) { gzreader_skip_linebreaks(gz); diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index ae4adc21fe2cf8..15e5bd852fe5d3 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -991,6 +991,25 @@ def test_read assert_raise(ArgumentError) { f.read(-1) } assert_equal(str, f.read) end + + Zlib::GzipReader.open(t.path) do |f| + s = "".b + + assert_raise(ArgumentError) { f.read(-1, s) } + + assert_same s, f.read(1, s) + assert_equal "\xE3".b, s + + assert_same s, f.read(2, s) + assert_equal "\x81\x82".b, s + + assert_same s, f.read(6, s) + assert_equal "\u3044\u3046".b, s + + assert_nil f.read(1, s) + assert_equal "".b, s + assert_predicate f, :eof? + end } end @@ -1005,10 +1024,14 @@ def test_readpartial Zlib::GzipReader.open(t.path) do |f| s = "".dup - f.readpartial(3, s) + assert_same s, f.readpartial(3, s) assert("foo".start_with?(s)) assert_raise(ArgumentError) { f.readpartial(-1) } + + assert_same s, f.readpartial(3, s) + + assert_predicate f, :eof? end } end From e3e1e53098f3214ef12849b3441791465ad7c0a5 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 11 Apr 2024 14:28:07 -0500 Subject: [PATCH 109/151] [ruby/zlib] Avoid double copying into provided outbuf https://github.com/ruby/zlib/commit/07f44b7546 --- ext/zlib/zlib.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index b1623546e674b0..aad9f8d28a4374 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -2961,11 +2961,6 @@ gzfile_readpartial(struct gzfile *gz, long len, VALUE outbuf) dst = zstream_shift_buffer(&gz->z, len, outbuf); gzfile_calc_crc(gz, dst); - if (!NIL_P(outbuf)) { - rb_str_resize(outbuf, RSTRING_LEN(dst)); - memcpy(RSTRING_PTR(outbuf), RSTRING_PTR(dst), RSTRING_LEN(dst)); - dst = outbuf; - } return dst; } From e73f6618d5d7a36e0599df14d2423544007bdf7c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 15 May 2024 16:53:27 +0900 Subject: [PATCH 110/151] [rubygems/rubygems] Do not override `@orig_env` It is saved in `setup` and restored in `teardown`. https://github.com/rubygems/rubygems/commit/880c5de667 --- test/rubygems/helper.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb index 856dc535882435..7014843bba0fdd 100644 --- a/test/rubygems/helper.rb +++ b/test/rubygems/helper.rb @@ -535,12 +535,12 @@ def without_any_upwards_gemfiles end def with_env(overrides, &block) - @orig_env = ENV.to_h + orig_env = ENV.to_h ENV.replace(overrides) begin block.call ensure - ENV.replace(@orig_env) + ENV.replace(orig_env) end end From c4a5866798589fb78393b694fcd3359f0ec52b16 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:14:57 -0400 Subject: [PATCH 111/151] [ruby/prism] Replace end of file with end-of-input https://github.com/ruby/prism/commit/dd532ded95 --- prism/prism.c | 49 +++++++++++++++------------- prism/templates/src/token_type.c.erb | 2 +- test/prism/errors_test.rb | 14 ++++---- 3 files changed, 33 insertions(+), 32 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 4c8b42f8020e8d..480252cc056d7f 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -13552,8 +13552,8 @@ parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_ */ static pm_statements_node_t * parse_statements(pm_parser_t *parser, pm_context_t context) { - // First, skip past any optional terminators that might be at the beginning of - // the statements. + // First, skip past any optional terminators that might be at the beginning + // of the statements. while (accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE)); // If we have a terminator, then we can just return NULL. @@ -13569,20 +13569,20 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION); pm_statements_node_body_append(parser, statements, node); - // If we're recovering from a syntax error, then we need to stop parsing the - // statements now. + // If we're recovering from a syntax error, then we need to stop parsing + // the statements now. if (parser->recovering) { - // If this is the level of context where the recovery has happened, then - // we can mark the parser as done recovering. + // If this is the level of context where the recovery has happened, + // then we can mark the parser as done recovering. if (context_terminator(context, &parser->current)) parser->recovering = false; break; } - // If we have a terminator, then we will parse all consecutive terminators - // and then continue parsing the statements list. + // If we have a terminator, then we will parse all consecutive + // terminators and then continue parsing the statements list. if (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) { - // If we have a terminator, then we will continue parsing the statements - // list. + // If we have a terminator, then we will continue parsing the + // statements list. while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); if (context_terminator(context, &parser->current)) break; @@ -13590,27 +13590,28 @@ parse_statements(pm_parser_t *parser, pm_context_t context) { continue; } - // At this point we have a list of statements that are not terminated by a - // newline or semicolon. At this point we need to check if we're at the end - // of the statements list. If we are, then we should break out of the loop. + // At this point we have a list of statements that are not terminated by + // a newline or semicolon. At this point we need to check if we're at + // the end of the statements list. If we are, then we should break out + // of the loop. if (context_terminator(context, &parser->current)) break; // At this point, we have a syntax error, because the statement was not // terminated by a newline or semicolon, and we're not at the end of the - // statements list. Ideally we should scan forward to determine if we should - // insert a missing terminator or break out of parsing the statements list - // at this point. + // statements list. Ideally we should scan forward to determine if we + // should insert a missing terminator or break out of parsing the + // statements list at this point. // - // We don't have that yet, so instead we'll do a more naive approach. If we - // were unable to parse an expression, then we will skip past this token and - // continue parsing the statements list. Otherwise we'll add an error and - // continue parsing the statements list. + // We don't have that yet, so instead we'll do a more naive approach. If + // we were unable to parse an expression, then we will skip past this + // token and continue parsing the statements list. Otherwise we'll add + // an error and continue parsing the statements list. if (PM_NODE_TYPE_P(node, PM_MISSING_NODE)) { parser_lex(parser); while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)); if (context_terminator(context, &parser->current)) break; - } else if (!accept1(parser, PM_TOKEN_NEWLINE)) { + } else if (!accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_EOF)) { // This is an inlined version of accept1 because the error that we // want to add has varargs. If this happens again, we should // probably extract a helper function. @@ -17428,7 +17429,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b // If we didn't find a terminator and we didn't find a right // parenthesis, then this is a syntax error. - if (!terminator_found) { + if (!terminator_found && !match1(parser, PM_TOKEN_EOF)) { PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); } @@ -17457,7 +17458,9 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) break; } else if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) { break; - } else { + } else if (!match1(parser, PM_TOKEN_EOF)) { + // If we're at the end of the file, then we're going to add + // an error after this for the ) anyway. PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(parser->current.type)); } } diff --git a/prism/templates/src/token_type.c.erb b/prism/templates/src/token_type.c.erb index a3095eeab8543f..af6a2ad6fe2a86 100644 --- a/prism/templates/src/token_type.c.erb +++ b/prism/templates/src/token_type.c.erb @@ -30,7 +30,7 @@ const char * pm_token_type_human(pm_token_type_t token_type) { switch (token_type) { case PM_TOKEN_EOF: - return "end of file"; + return "end-of-input"; case PM_TOKEN_MISSING: return "missing token"; case PM_TOKEN_NOT_PROVIDED: diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 5d18780dddb564..c6991519c50a12 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -195,8 +195,7 @@ def test_unterminated_s_symbol def test_unterminated_parenthesized_expression assert_errors expression('(1 + 2'), '(1 + 2', [ - ["unexpected end of file, expecting end-of-input", 6..6], - ["unexpected end of file, assuming it is closing the parent top level context", 6..6], + ["unexpected end-of-input, assuming it is closing the parent top level context", 6..6], ["expected a matching `)`", 6..6] ] end @@ -210,8 +209,8 @@ def test_missing_terminator_in_parentheses def test_unterminated_argument_expression assert_errors expression('a %'), 'a %', [ ["invalid `%` token", 2..3], - ["unexpected end of file; expected an expression after the operator", 3..3], - ["unexpected end of file, assuming it is closing the parent top level context", 3..3] + ["unexpected end-of-input; expected an expression after the operator", 3..3], + ["unexpected end-of-input, assuming it is closing the parent top level context", 3..3] ] end @@ -365,7 +364,7 @@ def test_block_beginning_with_brace_and_ending_with_end assert_error_messages "x.each { x end", [ "unexpected 'end', expecting end-of-input", "unexpected 'end', ignoring it", - "unexpected end of file, assuming it is closing the parent top level context", + "unexpected end-of-input, assuming it is closing the parent top level context", "expected a block beginning with `{` to end with `}`" ] end @@ -1482,8 +1481,7 @@ def test_shadow_args_in_lambda assert_errors expression(source), source, [ ["expected a `do` keyword or a `{` to open the lambda block", 3..3], - ["unexpected end of file, expecting end-of-input", 7..7], - ["unexpected end of file, assuming it is closing the parent top level context", 7..7], + ["unexpected end-of-input, assuming it is closing the parent top level context", 7..7], ["expected a lambda block beginning with `do` to end with `end`", 7..7] ] end @@ -1541,7 +1539,7 @@ def test_while_endless_method assert_errors expression(source), source, [ ["expected a predicate expression for the `while` statement", 22..22], - ["unexpected end of file, assuming it is closing the parent top level context", 22..22], + ["unexpected end-of-input, assuming it is closing the parent top level context", 22..22], ["expected an `end` to close the `while` statement", 22..22] ] end From cbd1553800c173113f5ea8f1c5d52b00b283d677 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:47:01 -0400 Subject: [PATCH 112/151] [ruby/prism] Extend the bounds of the invalid global variable name error https://github.com/ruby/prism/commit/89d0d9851a --- prism/prism.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 480252cc056d7f..97d47c8985f109 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -8995,8 +8995,8 @@ lex_global_variable(pm_parser_t *parser) { // If we get here, then we have a $ followed by something that // isn't recognized as a global variable. pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL; - size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); - PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, (int) ((parser->current.end + width) - parser->current.start), (const char *) parser->current.start); + const uint8_t *end = parser->current.end + parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + PM_PARSER_ERR_FORMAT(parser, parser->current.start, end, diag_id, (int) (end - parser->current.start), (const char *) parser->current.start); } return PM_TOKEN_GLOBAL_VARIABLE; From 901f4c3fb77968cd9cb2f1dc2d860cf936a2457d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 12:49:03 -0400 Subject: [PATCH 113/151] [PRISM] Temporarily exclude IRB test --- test/.excludes-prism/TestIRB/RubyLexTest.rb | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/.excludes-prism/TestIRB/RubyLexTest.rb diff --git a/test/.excludes-prism/TestIRB/RubyLexTest.rb b/test/.excludes-prism/TestIRB/RubyLexTest.rb new file mode 100644 index 00000000000000..a2d0a574525d8e --- /dev/null +++ b/test/.excludes-prism/TestIRB/RubyLexTest.rb @@ -0,0 +1 @@ +exclude(:test_code_block_open_with_should_continue, "https://github.com/ruby/irb/pull/956") From cabc0e093cca984cd6edda0d070b70dc1c125363 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:25:13 -0400 Subject: [PATCH 114/151] [PRISM] Enable TestParse#test_unexpected_token_after_numeric --- test/.excludes-prism/TestParse.rb | 1 - test/ruby/test_parse.rb | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 7cf5f97dd26631..3b390dbedde8bc 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -6,5 +6,4 @@ exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") exclude(:test_unexpected_eof, "error message format") -exclude(:test_unexpected_token_after_numeric, "error message format") exclude(:test_void_value_in_rhs, "missing raising error for some void value expressions") diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index bd6dabf2c978d4..1e39fbf72f201e 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1336,9 +1336,9 @@ def test_unexpected_token_error end def test_unexpected_token_after_numeric - assert_syntax_error('0000xyz', /^ \^~~\Z/) - assert_syntax_error('1.2i1.1', /^ \^~~\Z/) - assert_syntax_error('1.2.3', /^ \^~\Z/) + assert_syntax_error('0000xyz', /(^|\| ) \^~~(?!~)/) + assert_syntax_error('1.2i1.1', /(^|\| ) \^~~(?!~)/) + assert_syntax_error('1.2.3', /(^|\| ) \^~(?!~)/) assert_syntax_error('1.', /unexpected end-of-input/) assert_syntax_error('1e', /expecting end-of-input/) end From be239cc7bc50d3882bc3dec2bbe1f4f0c1e797fa Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:27:03 -0400 Subject: [PATCH 115/151] [PRISM] Enable TestParse#test_unexpected_eof --- test/ruby/test_parse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 1e39fbf72f201e..c77cdc56739b04 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1390,7 +1390,7 @@ def test_eof_in_def end def test_unexpected_eof - assert_syntax_error('unless', /^ \^\Z/) + assert_syntax_error('unless', /(^|\| ) \^(?!~)/) end def test_location_of_invalid_token From cd8b28f0e7661498bbae259982809fc7f50e0581 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:40:52 -0400 Subject: [PATCH 116/151] [PRISM] Enable test_location_of_invalid_token --- test/.excludes-prism/TestParse.rb | 2 -- test/ruby/test_parse.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 3b390dbedde8bc..1c2349cfe51681 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,9 +1,7 @@ exclude(:test_global_variable, "error message format") exclude(:test_invalid_char, "error message format") -exclude(:test_location_of_invalid_token, "error message format") exclude(:test_percent, "error message format") exclude(:test_question, "error message format") exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") -exclude(:test_unexpected_eof, "error message format") exclude(:test_void_value_in_rhs, "missing raising error for some void value expressions") diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index c77cdc56739b04..0035f779570e6d 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1394,7 +1394,7 @@ def test_unexpected_eof end def test_location_of_invalid_token - assert_syntax_error('class xxx end', /^ \^~~\Z/) + assert_syntax_error('class xxx end', /(^|\| ) \^~~(?!~)/) end def test_whitespace_warning From 2aed14d65b6240d03fd9084792855e868e793b2d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Wed, 15 May 2024 11:48:20 -0400 Subject: [PATCH 117/151] [PRISM] Enable TestParse#test_global_variable --- test/.excludes-prism/TestParse.rb | 1 - test/ruby/test_parse.rb | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 1c2349cfe51681..8ff7dba1f4cdcd 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,4 +1,3 @@ -exclude(:test_global_variable, "error message format") exclude(:test_invalid_char, "error message format") exclude(:test_percent, "error message format") exclude(:test_question, "error message format") diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 0035f779570e6d..63539270fc0793 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -875,7 +875,8 @@ def test_global_variable $test_parse_foobarbazqux = nil assert_equal(nil, $&) assert_equal(nil, eval('alias $& $preserve_last_match')) - assert_syntax_error('a = $#', /as a global variable name\na = \$\#\n \^~$/) + assert_syntax_error('a = $#', /as a global variable name/) + assert_syntax_error('a = $#', /a = \$\#\n(^|.+?\| ) \^~(?!~)/) end def test_invalid_instance_variable From 9d69619623ec6b86c464b7cac911b7201f74dab7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sat, 20 Apr 2024 19:56:58 +0900 Subject: [PATCH 118/151] [rubygems/rubygems] Clean up generated and copied files > leaving the files after gem rebuild was intentional, for local > inspection, but the test suite should be made to clean up after > itself independently of that. https://github.com/rubygems/rubygems/pull/4913#issuecomment-2081710691 https://github.com/rubygems/rubygems/commit/185a2091fb --- test/rubygems/test_gem_commands_rebuild_command.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_commands_rebuild_command.rb b/test/rubygems/test_gem_commands_rebuild_command.rb index 5e8c797e2d11ad..3b7927c44e0308 100644 --- a/test/rubygems/test_gem_commands_rebuild_command.rb +++ b/test/rubygems/test_gem_commands_rebuild_command.rb @@ -105,7 +105,7 @@ def util_test_rebuild_gem(gem, args, original_gem_file, gemspec_file, timestamp) assert_equal old_spec.name, new_spec.name assert_equal old_spec.summary, new_spec.summary - reproduced + [reproduced, original] end def test_build_is_reproducible @@ -134,12 +134,21 @@ def test_build_is_reproducible # also testing that `gem rebuild` overrides the value. ENV["SOURCE_DATE_EPOCH"] = Time.new(2007, 8, 9, 10, 11, 12).to_s - rebuild_gem_file = util_test_rebuild_gem(@gem, [@gem_name, @gem_version], original_gem_file, gemspec_file, timestamp) + rebuild_gem_file, saved_gem_file = + util_test_rebuild_gem(@gem, [@gem_name, @gem_version], original_gem_file, gemspec_file, timestamp) rebuild_contents = File.read(rebuild_gem_file) assert_equal build_contents, rebuild_contents ensure ENV["SOURCE_DATE_EPOCH"] = epoch + if rebuild_gem_file + File.unlink(rebuild_gem_file) + dir = File.dirname(rebuild_gem_file) + Dir.rmdir(dir) + File.unlink(saved_gem_file) + Dir.rmdir(File.dirname(saved_gem_file)) + Dir.rmdir(File.dirname(dir)) + end end end From 2dd46bb82ffc4dff01d7ea70922f0e407acafb4e Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 16 May 2024 16:22:17 +0900 Subject: [PATCH 119/151] [Bug #20468] Fix safe navigation in `for` variable --- compile.c | 21 +++++++++++++++------ test/ruby/test_syntax.rb | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/compile.c b/compile.c index c319b72b524d78..5167f4d61c3b75 100644 --- a/compile.c +++ b/compile.c @@ -5380,12 +5380,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node)); + bool safenav_call = false; LINK_ELEMENT *insn_element = LAST_ELEMENT(pre); iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */ ASSUME(iobj); - ELEM_REMOVE(LAST_ELEMENT(pre)); - ELEM_REMOVE((LINK_ELEMENT *)iobj); - pre->last = iobj->link.prev; + ELEM_REMOVE(insn_element); + if (!IS_INSN_ID(iobj, send)) { + safenav_call = true; + iobj = (INSN *)get_prev_insn(iobj); + ELEM_INSERT_NEXT(&iobj->link, insn_element); + } + (pre->last = iobj->link.prev)->next = 0; const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0); int argc = vm_ci_argc(ci) + 1; @@ -5404,7 +5409,9 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const return COMPILE_NG; } - ADD_ELEM(lhs, (LINK_ELEMENT *)iobj); + iobj->link.prev = lhs->last; + lhs->last->next = &iobj->link; + for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next); if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { int argc = vm_ci_argc(ci); bool dupsplat = false; @@ -5437,9 +5444,11 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const } INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1)); } - ADD_INSN(lhs, line_node, pop); - if (argc != 1) { + if (!safenav_call) { ADD_INSN(lhs, line_node, pop); + if (argc != 1) { + ADD_INSN(lhs, line_node, pop); + } } for (int i=0; i < argc; i++) { ADD_INSN(post, line_node, pop); diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index 7b894eee79ec27..edc3a3cec3fb9d 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1248,6 +1248,20 @@ def test_safe_call_in_massign_lhs assert_syntax_error("a&.x,=0", /multiple assignment destination/) end + def test_safe_call_in_for_variable + assert_valid_syntax("for x&.bar in []; end") + assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}") + begin; + foo = nil + for foo&.bar in [1]; end + assert_nil(foo) + + foo = Struct.new(:bar).new + for foo&.bar in [1]; end + assert_equal(1, foo.bar) + end; + end + def test_no_warning_logop_literal assert_warning("") do eval("true||raise;nil") From 4db76d198b4a152c416d657e97959ade3e50a185 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 11:59:55 +0200 Subject: [PATCH 120/151] [rubygems/rubygems] Add a FreeBSD platform helper https://github.com/rubygems/rubygems/commit/535c83d5be --- lib/rubygems.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/rubygems.rb b/lib/rubygems.rb index ad7ab1075636a8..ac225ca70ae6a6 100644 --- a/lib/rubygems.rb +++ b/lib/rubygems.rb @@ -1012,6 +1012,13 @@ def self.solaris_platform? RUBY_PLATFORM.include?("solaris") end + ## + # Is this platform FreeBSD + + def self.freebsd_platform? + RbConfig::CONFIG["host_os"].to_s.include?("bsd") + end + ## # Load +plugins+ as Ruby files From 9fd41480fbdf7c137b2417851b517aeda33393a0 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 12:04:59 +0200 Subject: [PATCH 121/151] [rubygems/rubygems] Use RubyGems freebsd helper https://github.com/rubygems/rubygems/commit/5d03a346ab --- lib/bundler/cli/install.rb | 2 +- lib/bundler/rubygems_ext.rb | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb index 6c102d537dfd0f..a233d5d2e5a183 100644 --- a/lib/bundler/cli/install.rb +++ b/lib/bundler/cli/install.rb @@ -14,7 +14,7 @@ def run Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed - Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Bundler::FREEBSD + Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Gem.freebsd_platform? # Disable color in deployment mode Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment] diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb index 14b870321313c0..18180a81a1c3f9 100644 --- a/lib/bundler/rubygems_ext.rb +++ b/lib/bundler/rubygems_ext.rb @@ -23,6 +23,13 @@ end module Gem + # Can be removed once RubyGems 3.5.11 support is dropped + unless Gem.respond_to?(:freebsd_platform?) + def self.freebsd_platform? + RbConfig::CONFIG["host_os"].to_s.include?("bsd") + end + end + require "rubygems/specification" class Specification From 29a9ab0ba674f3739e453b2c7a68c138c8802b99 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 13 May 2024 12:05:24 +0200 Subject: [PATCH 122/151] [rubygems/rubygems] Deprecate Bundler constants https://github.com/rubygems/rubygems/commit/6166e4bce1 --- lib/bundler/constants.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/bundler/constants.rb b/lib/bundler/constants.rb index bcbd228b187650..9564771e78afbb 100644 --- a/lib/bundler/constants.rb +++ b/lib/bundler/constants.rb @@ -4,6 +4,11 @@ module Bundler WINDOWS = RbConfig::CONFIG["host_os"] =~ /(msdos|mswin|djgpp|mingw)/ + deprecate_constant :WINDOWS + FREEBSD = RbConfig::CONFIG["host_os"].to_s.include?("bsd") - NULL = File::NULL + deprecate_constant :FREEBSD + + NULL = File::NULL + deprecate_constant :NULL end From 7857061ecd740ef88d8451c5119827e91d57a4fd Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Tue, 14 May 2024 20:07:15 +0200 Subject: [PATCH 123/151] [rubygems/rubygems] Fix regression when caching gems from secondary sources If `cache_all_platforms` setting is enabled, the secondary source was no longer considering cached gems. That means that if the remote secondary source has removed its gems, then this was now resulting in an error while before the previously cached gem from the source would still be used. This commit restores previous behavior. https://github.com/rubygems/rubygems/commit/2d2cd00255 --- lib/bundler/spec_set.rb | 1 + spec/bundler/commands/cache_spec.rb | 60 +++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb index 2933d284500668..8e1130e40ed81f 100644 --- a/lib/bundler/spec_set.rb +++ b/lib/bundler/spec_set.rb @@ -129,6 +129,7 @@ def materialize(deps) def materialized_for_all_platforms @specs.map do |s| next s unless s.is_a?(LazySpecification) + s.source.cached! s.source.remote! spec = s.materialize_for_installation raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb index 70e2c84961d377..37d8b3ac1a47ff 100644 --- a/spec/bundler/commands/cache_spec.rb +++ b/spec/bundler/commands/cache_spec.rb @@ -386,6 +386,66 @@ expect(the_bundle).to include_gems "rack 1.0.0" end + it "uses cached gems for secondary sources when cache_all_platforms configured" do + build_repo4 do + build_gem "foo", "1.0.0" do |s| + s.platform = "x86_64-linux" + end + + build_gem "foo", "1.0.0" do |s| + s.platform = "arm64-darwin" + end + end + + gemfile <<~G + source "https://gems.repo2" + + source "https://gems.repo4" do + gem "foo" + end + G + + lockfile <<~L + GEM + remote: https://gems.repo2/ + specs: + + GEM + remote: https://gems.repo4/ + specs: + foo (1.0.0-x86_64-linux) + foo (1.0.0-arm64-darwin) + + PLATFORMS + arm64-darwin + ruby + x86_64-linux + + DEPENDENCIES + foo + + BUNDLED WITH + #{Bundler::VERSION} + L + + simulate_platform "x86_64-linux" do + bundle "config set cache_all_platforms true" + bundle "config set path vendor/bundle" + bundle :cache, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + + build_repo4 do + # simulate removal of all remote gems + end + + # delete compact index cache + FileUtils.rm_rf home(".bundle/cache/compact_index") + + bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s } + + expect(the_bundle).to include_gems "foo 1.0.0 x86_64-linux" + end + end + it "does not reinstall already-installed gems" do install_gemfile <<-G source "#{file_uri_for(gem_repo1)}" From 847fc9af1805d8d2277827eb19c0cb4df8509973 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 20:16:32 +0200 Subject: [PATCH 124/151] [rubygems/rubygems] Fix error message calling method removed a long time ago https://github.com/rubygems/rubygems/commit/5fbe5e43d6 --- lib/rubygems/commands/uninstall_command.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb index 2a77ec72cf1033..283bc96ce3e8cd 100644 --- a/lib/rubygems/commands/uninstall_command.rb +++ b/lib/rubygems/commands/uninstall_command.rb @@ -184,7 +184,7 @@ def uninstall_gem(gem_name) rescue Gem::GemNotInHomeException => e spec = e.spec alert("In order to remove #{spec.name}, please execute:\n" \ - "\tgem uninstall #{spec.name} --install-dir=#{spec.installation_path}") + "\tgem uninstall #{spec.name} --install-dir=#{spec.base_dir}") rescue Gem::UninstallError => e spec = e.spec alert_error("Error: unable to successfully uninstall '#{spec.name}' which is " \ From b19693f0ae5077c074ab5a1799cae91e1ef5d7e6 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 20:17:44 +0200 Subject: [PATCH 125/151] [rubygems/rubygems] Improve uninstaller tests Tests have two copies of b-2 installed, one in default home and another in user home. But only the one in default home was visible because of not reloading paths. The user install test was working by chance. https://github.com/rubygems/rubygems/commit/667537a08f --- test/rubygems/test_gem_uninstaller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index eb25b505e6cbd3..2e4fca011216fb 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -429,7 +429,7 @@ def test_uninstall_not_ok end def test_uninstall_user_install - @user_spec = Gem::Specification.find_by_name "b" + Gem::Specification.dirs = [Gem.user_dir] uninstaller = Gem::Uninstaller.new(@user_spec.name, executables: true, From 5111b3d479c413c3c14df1c4b4dc5d22c9270edb Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 20:51:23 +0200 Subject: [PATCH 126/151] [rubygems/rubygems] Fix `gem uninstall --user-install` for symlinked HOME's https://github.com/rubygems/rubygems/commit/7f0706a897 --- lib/rubygems/uninstaller.rb | 5 +++-- test/rubygems/test_gem_uninstaller.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb index e1f82e6a21bdbb..4d72f6fd0a2cfd 100644 --- a/lib/rubygems/uninstaller.rb +++ b/lib/rubygems/uninstaller.rb @@ -51,6 +51,7 @@ def initialize(gem, options = {}) @version = options[:version] || Gem::Requirement.default @install_dir = options[:install_dir] @gem_home = File.realpath(@install_dir || Gem.dir) + @user_dir = File.exist?(Gem.user_dir) ? File.realpath(Gem.user_dir) : Gem.user_dir @force_executables = options[:executables] @force_all = options[:all] @force_ignore = options[:ignore] @@ -105,7 +106,7 @@ def uninstall list, other_repo_specs = list.partition do |spec| @gem_home == spec.base_dir || - (@user_install && spec.base_dir == Gem.user_dir) + (@user_install && spec.base_dir == @user_dir) end list.sort! @@ -239,7 +240,7 @@ def remove_all(list) def remove(spec) unless path_ok?(@gem_home, spec) || - (@user_install && path_ok?(Gem.user_dir, spec)) + (@user_install && path_ok?(@user_dir, spec)) e = Gem::GemNotInHomeException.new \ "Gem '#{spec.full_name}' is not installed in directory #{@gem_home}" e.spec = spec diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb index 2e4fca011216fb..aa5ab0ed67684d 100644 --- a/test/rubygems/test_gem_uninstaller.rb +++ b/test/rubygems/test_gem_uninstaller.rb @@ -453,6 +453,32 @@ def test_uninstall_user_install assert_same uninstaller, @post_uninstall_hook_arg end + def test_uninstall_user_install_with_symlinked_home + pend "Symlinks not supported or not enabled" unless symlink_supported? + + Gem::Specification.dirs = [Gem.user_dir] + + symlinked_home = File.join(@tempdir, "new-home") + FileUtils.ln_s(Gem.user_home, symlinked_home) + + ENV["HOME"] = symlinked_home + Gem.instance_variable_set(:@user_home, nil) + Gem.instance_variable_set(:@data_home, nil) + + uninstaller = Gem::Uninstaller.new(@user_spec.name, + executables: true, + user_install: true, + force: true) + + gem_dir = File.join @user_spec.gem_dir + + assert_path_exist gem_dir + + uninstaller.uninstall + + assert_path_not_exist gem_dir + end + def test_uninstall_wrong_repo Dir.mkdir "#{@gemhome}2" Gem.use_paths "#{@gemhome}2", [@gemhome] From d076101af93b28beff15eaa1fcb92ce4f070e9cc Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 16 May 2024 21:25:52 +0900 Subject: [PATCH 127/151] Fix dump of NODE [ci skip] --- misc/lldb_rb/utils.py | 451 +++++++++++++++++++++--------------------- 1 file changed, 230 insertions(+), 221 deletions(-) diff --git a/misc/lldb_rb/utils.py b/misc/lldb_rb/utils.py index 86b5bdda2d8a13..1b0e4f9f2ab0bb 100644 --- a/misc/lldb_rb/utils.py +++ b/misc/lldb_rb/utils.py @@ -60,6 +60,9 @@ def inspect(self, val): rbUndef = self.ruby_globals["RUBY_Qundef"] rbImmediateMask = self.ruby_globals["RUBY_IMMEDIATE_MASK"] + if self.inspect_node(val): + return + num = val.GetValueAsSigned() if num == rbFalse: print('false', file=self.result) @@ -245,227 +248,6 @@ def inspect(self, val): print("T_DATA:", file=self.result) self._append_expression("*(struct RData *) %0#x" % val.GetValueAsUnsigned()) - elif rval.is_type("RUBY_T_NODE"): - tRNode = self.target.FindFirstType("struct RNode").GetPointerType() - rbNodeTypeMask = self.ruby_globals["RUBY_NODE_TYPEMASK"] - rbNodeTypeShift = self.ruby_globals["RUBY_NODE_TYPESHIFT"] - - nd_type = (rval.flags & rbNodeTypeMask) >> rbNodeTypeShift - val = val.Cast(tRNode) - - self._append_expression("(node_type) %d" % nd_type) - - if nd_type == self.ruby_globals["NODE_SCOPE"]: - self._append_expression("*(struct RNode_SCOPE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_BLOCK"]: - self._append_expression("*(struct RNode_BLOCK *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_IF"]: - self._append_expression("*(struct RNode_IF *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_UNLESS"]: - self._append_expression("*(struct RNode_UNLESS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CASE"]: - self._append_expression("*(struct RNode_CASE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CASE2"]: - self._append_expression("*(struct RNode_CASE2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CASE3"]: - self._append_expression("*(struct RNode_CASE3 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_WHEN"]: - self._append_expression("*(struct RNode_WHEN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_IN"]: - self._append_expression("*(struct RNode_IN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_WHILE"]: - self._append_expression("*(struct RNode_WHILE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_UNTIL"]: - self._append_expression("*(struct RNode_UNTIL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ITER"]: - self._append_expression("*(struct RNode_ITER *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FOR"]: - self._append_expression("*(struct RNode_FOR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FOR_MASGN"]: - self._append_expression("*(struct RNode_FOR_MASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_BREAK"]: - self._append_expression("*(struct RNode_BREAK *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_NEXT"]: - self._append_expression("*(struct RNode_NEXT *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_REDO"]: - self._append_expression("*(struct RNode_REDO *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_RETRY"]: - self._append_expression("*(struct RNode_RETRY *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_BEGIN"]: - self._append_expression("*(struct RNode_BEGIN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_RESCUE"]: - self._append_expression("*(struct RNode_RESCUE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_RESBODY"]: - self._append_expression("*(struct RNode_RESBODY *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ENSURE"]: - self._append_expression("*(struct RNode_ENSURE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_AND"]: - self._append_expression("*(struct RNode_AND *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OR"]: - self._append_expression("*(struct RNode_OR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_MASGN"]: - self._append_expression("*(struct RNode_MASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_LASGN"]: - self._append_expression("*(struct RNode_LASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DASGN"]: - self._append_expression("*(struct RNode_DASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_GASGN"]: - self._append_expression("*(struct RNode_GASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_IASGN"]: - self._append_expression("*(struct RNode_IASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CDECL"]: - self._append_expression("*(struct RNode_CDECL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CVASGN"]: - self._append_expression("*(struct RNode_CVASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OP_ASGN1"]: - self._append_expression("*(struct RNode_OP_ASGN1 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OP_ASGN2"]: - self._append_expression("*(struct RNode_OP_ASGN2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OP_ASGN_AND"]: - self._append_expression("*(struct RNode_OP_ASGN_AND *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OP_ASGN_OR"]: - self._append_expression("*(struct RNode_OP_ASGN_OR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OP_CDECL"]: - self._append_expression("*(struct RNode_OP_CDECL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CALL"]: - self._append_expression("*(struct RNode_CALL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OPCALL"]: - self._append_expression("*(struct RNode_OPCALL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FCALL"]: - self._append_expression("*(struct RNode_FCALL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_VCALL"]: - self._append_expression("*(struct RNode_VCALL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_QCALL"]: - self._append_expression("*(struct RNode_QCALL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_SUPER"]: - self._append_expression("*(struct RNode_SUPER *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ZSUPER"]: - self._append_expression("*(struct RNode_ZSUPER *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_LIST"]: - self._append_expression("*(struct RNode_LIST *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ZLIST"]: - self._append_expression("*(struct RNode_ZLIST *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_HASH"]: - self._append_expression("*(struct RNode_HASH *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_RETURN"]: - self._append_expression("*(struct RNode_RETURN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_YIELD"]: - self._append_expression("*(struct RNode_YIELD *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_LVAR"]: - self._append_expression("*(struct RNode_LVAR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DVAR"]: - self._append_expression("*(struct RNode_DVAR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_GVAR"]: - self._append_expression("*(struct RNode_GVAR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CONST"]: - self._append_expression("*(struct RNode_CONST *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CVAR"]: - self._append_expression("*(struct RNode_CVAR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_NTH_REF"]: - self._append_expression("*(struct RNode_NTH_REF *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_BACK_REF"]: - self._append_expression("*(struct RNode_BACK_REF *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_MATCH"]: - self._append_expression("*(struct RNode_MATCH *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_MATCH2"]: - self._append_expression("*(struct RNode_MATCH2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_MATCH3"]: - self._append_expression("*(struct RNode_MATCH3 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_STR"]: - self._append_expression("*(struct RNode_STR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DSTR"]: - self._append_expression("*(struct RNode_DSTR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_XSTR"]: - self._append_expression("*(struct RNode_XSTR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DXSTR"]: - self._append_expression("*(struct RNode_DXSTR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_EVSTR"]: - self._append_expression("*(struct RNode_EVSTR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_REGX"]: - self._append_expression("*(struct RNode_REGX *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DREGX"]: - self._append_expression("*(struct RNode_DREGX *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ONCE"]: - self._append_expression("*(struct RNode_ONCE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ARGS"]: - self._append_expression("*(struct RNode_ARGS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ARGS_AUX"]: - self._append_expression("*(struct RNode_ARGS_AUX *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_OPT_ARG"]: - self._append_expression("*(struct RNode_OPT_ARG *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_KW_ARG"]: - self._append_expression("*(struct RNode_KW_ARG *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_POSTARG"]: - self._append_expression("*(struct RNode_POSTARG *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ARGSCAT"]: - self._append_expression("*(struct RNode_ARGSCAT *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ARGSPUSH"]: - self._append_expression("*(struct RNode_ARGSPUSH *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_SPLAT"]: - self._append_expression("*(struct RNode_SPLAT *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DEFN"]: - self._append_expression("*(struct RNode_DEFN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DEFS"]: - self._append_expression("*(struct RNode_DEFS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ALIAS"]: - self._append_expression("*(struct RNode_ALIAS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_VALIAS"]: - self._append_expression("*(struct RNode_VALIAS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_UNDEF"]: - self._append_expression("*(struct RNode_UNDEF *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_CLASS"]: - self._append_expression("*(struct RNode_CLASS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_MODULE"]: - self._append_expression("*(struct RNode_MODULE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_SCLASS"]: - self._append_expression("*(struct RNode_SCLASS *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_COLON2"]: - self._append_expression("*(struct RNode_COLON2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_COLON3"]: - self._append_expression("*(struct RNode_COLON3 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DOT2"]: - self._append_expression("*(struct RNode_DOT2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DOT3"]: - self._append_expression("*(struct RNode_DOT3 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FLIP2"]: - self._append_expression("*(struct RNode_FLIP2 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FLIP3"]: - self._append_expression("*(struct RNode_FLIP3 *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_SELF"]: - self._append_expression("*(struct RNode_SELF *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_NIL"]: - self._append_expression("*(struct RNode_NIL *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_TRUE"]: - self._append_expression("*(struct RNode_TRUE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FALSE"]: - self._append_expression("*(struct RNode_FALSE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ERRINFO"]: - self._append_expression("*(struct RNode_ERRINFO *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DEFINED"]: - self._append_expression("*(struct RNode_DEFINED *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_POSTEXE"]: - self._append_expression("*(struct RNode_POSTEXE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_DSYM"]: - self._append_expression("*(struct RNode_DSYM *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ATTRASGN"]: - self._append_expression("*(struct RNode_ATTRASGN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_LAMBDA"]: - self._append_expression("*(struct RNode_LAMBDA *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ARYPTN"]: - self._append_expression("*(struct RNode_ARYPTN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_HSHPTN"]: - self._append_expression("*(struct RNode_HSHPTN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FNDPTN"]: - self._append_expression("*(struct RNode_FNDPTN *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_ERROR"]: - self._append_expression("*(struct RNode_ERROR *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_LINE"]: - self._append_expression("*(struct RNode_LINE *) %0#x" % val.GetValueAsUnsigned()) - elif nd_type == self.ruby_globals["NODE_FILE"]: - self._append_expression("*(struct RNode_FILE *) %0#x" % val.GetValueAsUnsigned()) - else: - self._append_expression("*(struct RNode *) %0#x" % val.GetValueAsUnsigned()) - elif rval.is_type("RUBY_T_IMEMO"): imemo_type = ((rval.flags >> self.ruby_globals["RUBY_FL_USHIFT"]) & IMEMO_MASK) @@ -492,3 +274,230 @@ def inspect(self, val): else: print("Not-handled type %0#x" % rval.type, file=self.result) print(val, file=self.result) + + def inspect_node(self, val): + tRNode = self.target.FindFirstType("struct RNode").GetPointerType() + + # if val.GetType() != tRNode: does not work for unknown reason + + if val.GetType().GetPointeeType().name != "NODE": + return False + + rbNodeTypeMask = self.ruby_globals["RUBY_NODE_TYPEMASK"] + rbNodeTypeShift = self.ruby_globals["RUBY_NODE_TYPESHIFT"] + flags = val.Cast(tRNode).GetChildMemberWithName("flags").GetValueAsUnsigned() + nd_type = (flags & rbNodeTypeMask) >> rbNodeTypeShift + + self._append_expression("(node_type) %d" % nd_type) + + if nd_type == self.ruby_globals["NODE_SCOPE"]: + self._append_expression("*(struct RNode_SCOPE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_BLOCK"]: + self._append_expression("*(struct RNode_BLOCK *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_IF"]: + self._append_expression("*(struct RNode_IF *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_UNLESS"]: + self._append_expression("*(struct RNode_UNLESS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CASE"]: + self._append_expression("*(struct RNode_CASE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CASE2"]: + self._append_expression("*(struct RNode_CASE2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CASE3"]: + self._append_expression("*(struct RNode_CASE3 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_WHEN"]: + self._append_expression("*(struct RNode_WHEN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_IN"]: + self._append_expression("*(struct RNode_IN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_WHILE"]: + self._append_expression("*(struct RNode_WHILE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_UNTIL"]: + self._append_expression("*(struct RNode_UNTIL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ITER"]: + self._append_expression("*(struct RNode_ITER *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FOR"]: + self._append_expression("*(struct RNode_FOR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FOR_MASGN"]: + self._append_expression("*(struct RNode_FOR_MASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_BREAK"]: + self._append_expression("*(struct RNode_BREAK *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_NEXT"]: + self._append_expression("*(struct RNode_NEXT *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_REDO"]: + self._append_expression("*(struct RNode_REDO *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_RETRY"]: + self._append_expression("*(struct RNode_RETRY *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_BEGIN"]: + self._append_expression("*(struct RNode_BEGIN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_RESCUE"]: + self._append_expression("*(struct RNode_RESCUE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_RESBODY"]: + self._append_expression("*(struct RNode_RESBODY *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ENSURE"]: + self._append_expression("*(struct RNode_ENSURE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_AND"]: + self._append_expression("*(struct RNode_AND *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OR"]: + self._append_expression("*(struct RNode_OR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_MASGN"]: + self._append_expression("*(struct RNode_MASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_LASGN"]: + self._append_expression("*(struct RNode_LASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DASGN"]: + self._append_expression("*(struct RNode_DASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_GASGN"]: + self._append_expression("*(struct RNode_GASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_IASGN"]: + self._append_expression("*(struct RNode_IASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CDECL"]: + self._append_expression("*(struct RNode_CDECL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CVASGN"]: + self._append_expression("*(struct RNode_CVASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OP_ASGN1"]: + self._append_expression("*(struct RNode_OP_ASGN1 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OP_ASGN2"]: + self._append_expression("*(struct RNode_OP_ASGN2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OP_ASGN_AND"]: + self._append_expression("*(struct RNode_OP_ASGN_AND *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OP_ASGN_OR"]: + self._append_expression("*(struct RNode_OP_ASGN_OR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OP_CDECL"]: + self._append_expression("*(struct RNode_OP_CDECL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CALL"]: + self._append_expression("*(struct RNode_CALL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OPCALL"]: + self._append_expression("*(struct RNode_OPCALL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FCALL"]: + self._append_expression("*(struct RNode_FCALL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_VCALL"]: + self._append_expression("*(struct RNode_VCALL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_QCALL"]: + self._append_expression("*(struct RNode_QCALL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_SUPER"]: + self._append_expression("*(struct RNode_SUPER *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ZSUPER"]: + self._append_expression("*(struct RNode_ZSUPER *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_LIST"]: + self._append_expression("*(struct RNode_LIST *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ZLIST"]: + self._append_expression("*(struct RNode_ZLIST *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_HASH"]: + self._append_expression("*(struct RNode_HASH *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_RETURN"]: + self._append_expression("*(struct RNode_RETURN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_YIELD"]: + self._append_expression("*(struct RNode_YIELD *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_LVAR"]: + self._append_expression("*(struct RNode_LVAR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DVAR"]: + self._append_expression("*(struct RNode_DVAR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_GVAR"]: + self._append_expression("*(struct RNode_GVAR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CONST"]: + self._append_expression("*(struct RNode_CONST *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CVAR"]: + self._append_expression("*(struct RNode_CVAR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_NTH_REF"]: + self._append_expression("*(struct RNode_NTH_REF *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_BACK_REF"]: + self._append_expression("*(struct RNode_BACK_REF *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_MATCH"]: + self._append_expression("*(struct RNode_MATCH *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_MATCH2"]: + self._append_expression("*(struct RNode_MATCH2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_MATCH3"]: + self._append_expression("*(struct RNode_MATCH3 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_STR"]: + self._append_expression("*(struct RNode_STR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DSTR"]: + self._append_expression("*(struct RNode_DSTR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_XSTR"]: + self._append_expression("*(struct RNode_XSTR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DXSTR"]: + self._append_expression("*(struct RNode_DXSTR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_EVSTR"]: + self._append_expression("*(struct RNode_EVSTR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_REGX"]: + self._append_expression("*(struct RNode_REGX *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DREGX"]: + self._append_expression("*(struct RNode_DREGX *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ONCE"]: + self._append_expression("*(struct RNode_ONCE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ARGS"]: + self._append_expression("*(struct RNode_ARGS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ARGS_AUX"]: + self._append_expression("*(struct RNode_ARGS_AUX *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_OPT_ARG"]: + self._append_expression("*(struct RNode_OPT_ARG *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_KW_ARG"]: + self._append_expression("*(struct RNode_KW_ARG *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_POSTARG"]: + self._append_expression("*(struct RNode_POSTARG *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ARGSCAT"]: + self._append_expression("*(struct RNode_ARGSCAT *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ARGSPUSH"]: + self._append_expression("*(struct RNode_ARGSPUSH *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_SPLAT"]: + self._append_expression("*(struct RNode_SPLAT *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DEFN"]: + self._append_expression("*(struct RNode_DEFN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DEFS"]: + self._append_expression("*(struct RNode_DEFS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ALIAS"]: + self._append_expression("*(struct RNode_ALIAS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_VALIAS"]: + self._append_expression("*(struct RNode_VALIAS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_UNDEF"]: + self._append_expression("*(struct RNode_UNDEF *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_CLASS"]: + self._append_expression("*(struct RNode_CLASS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_MODULE"]: + self._append_expression("*(struct RNode_MODULE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_SCLASS"]: + self._append_expression("*(struct RNode_SCLASS *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_COLON2"]: + self._append_expression("*(struct RNode_COLON2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_COLON3"]: + self._append_expression("*(struct RNode_COLON3 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DOT2"]: + self._append_expression("*(struct RNode_DOT2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DOT3"]: + self._append_expression("*(struct RNode_DOT3 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FLIP2"]: + self._append_expression("*(struct RNode_FLIP2 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FLIP3"]: + self._append_expression("*(struct RNode_FLIP3 *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_SELF"]: + self._append_expression("*(struct RNode_SELF *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_NIL"]: + self._append_expression("*(struct RNode_NIL *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_TRUE"]: + self._append_expression("*(struct RNode_TRUE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FALSE"]: + self._append_expression("*(struct RNode_FALSE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ERRINFO"]: + self._append_expression("*(struct RNode_ERRINFO *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DEFINED"]: + self._append_expression("*(struct RNode_DEFINED *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_POSTEXE"]: + self._append_expression("*(struct RNode_POSTEXE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_DSYM"]: + self._append_expression("*(struct RNode_DSYM *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ATTRASGN"]: + self._append_expression("*(struct RNode_ATTRASGN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_LAMBDA"]: + self._append_expression("*(struct RNode_LAMBDA *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ARYPTN"]: + self._append_expression("*(struct RNode_ARYPTN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_HSHPTN"]: + self._append_expression("*(struct RNode_HSHPTN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FNDPTN"]: + self._append_expression("*(struct RNode_FNDPTN *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_ERROR"]: + self._append_expression("*(struct RNode_ERROR *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_LINE"]: + self._append_expression("*(struct RNode_LINE *) %0#x" % val.GetValueAsUnsigned()) + elif nd_type == self.ruby_globals["NODE_FILE"]: + self._append_expression("*(struct RNode_FILE *) %0#x" % val.GetValueAsUnsigned()) + else: + self._append_expression("*(struct RNode *) %0#x" % val.GetValueAsUnsigned()) + return True From 35c5c7edb9c77398de65cef0636a3cdd2e539bb5 Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 16:00:17 +0200 Subject: [PATCH 128/151] [rubygems/rubygems] Refactor `Gem::Specification#find_all_by_name` So that it can also be delegated to `Gem::SpecificationRecord`. https://github.com/rubygems/rubygems/commit/1407807a99 --- lib/rubygems/dependency.rb | 14 +------------- lib/rubygems/specification.rb | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb index d1bf074441e5e9..5ce9c5e84030a7 100644 --- a/lib/rubygems/dependency.rb +++ b/lib/rubygems/dependency.rb @@ -271,15 +271,7 @@ def merge(other) end def matching_specs(platform_only = false) - env_req = Gem.env_requirement(name) - matches = Gem::Specification.stubs_for(name).find_all do |spec| - requirement.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version) - end.map(&:to_spec) - - if prioritizes_bundler? - require_relative "bundler_version_finder" - Gem::BundlerVersionFinder.prioritize!(matches) - end + matches = Gem::Specification.find_all_by_name(name, requirement) if platform_only matches.reject! do |spec| @@ -297,10 +289,6 @@ def specific? @requirement.specific? end - def prioritizes_bundler? - name == "bundler" && !specific? - end - def to_specs matches = matching_specs true diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index eb846095293ef7..00ed1cd5810a97 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -937,9 +937,19 @@ def self.each # Returns every spec that matches +name+ and optional +requirements+. def self.find_all_by_name(name, *requirements) - requirements = Gem::Requirement.default if requirements.empty? + req = Gem::Requirement.create(*requirements) + env_req = Gem.env_requirement(name) + + matches = stubs_for(name).find_all do |spec| + req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version) + end.map(&:to_spec) + + if name == "bundler" && !req.specific? + require_relative "bundler_version_finder" + Gem::BundlerVersionFinder.prioritize!(matches) + end - Gem::Dependency.new(name, *requirements).matching_specs + matches end ## From c55c11d7d5813683dde3eb7791bc2a9d5d39556d Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Thu, 9 May 2024 17:51:44 +0200 Subject: [PATCH 129/151] [rubygems/rubygems] Fix binstubs sometimes not getting regenerated when `--destdir` is given This was only working for gems also installed in the default gem home. https://github.com/rubygems/rubygems/commit/47df02dbd9 --- lib/rubygems/commands/pristine_command.rb | 15 +++++---- lib/rubygems/commands/setup_command.rb | 2 ++ lib/rubygems/installer.rb | 2 +- lib/rubygems/specification.rb | 22 ++----------- lib/rubygems/specification_record.rb | 32 +++++++++++++++++++ .../test_gem_commands_setup_command.rb | 23 +++++++++++-- 6 files changed, 67 insertions(+), 29 deletions(-) diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb index 456d897df23d58..b272a15b6c9dbb 100644 --- a/lib/rubygems/commands/pristine_command.rb +++ b/lib/rubygems/commands/pristine_command.rb @@ -57,7 +57,7 @@ def initialize end add_option("-i", "--install-dir DIR", - "Gem repository to get binstubs and plugins installed") do |value, options| + "Gem repository to get gems restored") do |value, options| options[:install_dir] = File.expand_path(value) end @@ -103,21 +103,25 @@ def usage # :nodoc: end def execute + install_dir = options[:install_dir] + + specification_record = install_dir ? Gem::SpecificationRecord.from_path(install_dir) : Gem::Specification.specification_record + specs = if options[:all] - Gem::Specification.map + specification_record.map # `--extensions` must be explicitly given to pristine only gems # with extensions. elsif options[:extensions_set] && options[:extensions] && options[:args].empty? - Gem::Specification.select do |spec| + specification_record.select do |spec| spec.extensions && !spec.extensions.empty? end elsif options[:only_missing_extensions] - Gem::Specification.select(&:missing_extensions?) + specification_record.select(&:missing_extensions?) else get_all_gem_names.sort.map do |gem_name| - Gem::Specification.find_all_by_name(gem_name, options[:version]).reverse + specification_record.find_all_by_name(gem_name, options[:version]).reverse end.flatten end @@ -176,7 +180,6 @@ def execute end bin_dir = options[:bin_dir] if options[:bin_dir] - install_dir = options[:install_dir] if options[:install_dir] installer_options = { wrappers: true, diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb index 3f38074280538e..9c633d6ef73408 100644 --- a/lib/rubygems/commands/setup_command.rb +++ b/lib/rubygems/commands/setup_command.rb @@ -585,6 +585,8 @@ def regenerate_binstubs(bindir) args = %w[--all --only-executables --silent] args << "--bindir=#{bindir}" + args << "--install-dir=#{default_dir}" + if options[:env_shebang] args << "--env-shebang" end diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb index 8f6f9a5aa8e894..844f292ba25d3d 100644 --- a/lib/rubygems/installer.rb +++ b/lib/rubygems/installer.rb @@ -344,7 +344,7 @@ def install say spec.post_install_message if options[:post_install_message] && !spec.post_install_message.nil? - Gem::Specification.add_spec(spec) + Gem::Specification.add_spec(spec) unless @install_dir load_plugin diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb index 00ed1cd5810a97..57f9b45cf7ab07 100644 --- a/lib/rubygems/specification.rb +++ b/lib/rubygems/specification.rb @@ -925,31 +925,15 @@ def self.dirs=(dirs) # Enumerate every known spec. See ::dirs= and ::add_spec to set the list of # specs. - def self.each - return enum_for(:each) unless block_given? - - _all.each do |x| - yield x - end + def self.each(&block) + specification_record.each(&block) end ## # Returns every spec that matches +name+ and optional +requirements+. def self.find_all_by_name(name, *requirements) - req = Gem::Requirement.create(*requirements) - env_req = Gem.env_requirement(name) - - matches = stubs_for(name).find_all do |spec| - req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version) - end.map(&:to_spec) - - if name == "bundler" && !req.specific? - require_relative "bundler_version_finder" - Gem::BundlerVersionFinder.prioritize!(matches) - end - - matches + specification_record.find_all_by_name(name, *requirements) end ## diff --git a/lib/rubygems/specification_record.rb b/lib/rubygems/specification_record.rb index 812431fa3297a7..dd6aa7eafaee3e 100644 --- a/lib/rubygems/specification_record.rb +++ b/lib/rubygems/specification_record.rb @@ -111,6 +111,38 @@ def all_names all.map(&:full_name) end + include Enumerable + + ## + # Enumerate every known spec. + + def each + return enum_for(:each) unless block_given? + + all.each do |x| + yield x + end + end + + ## + # Returns every spec in the record that matches +name+ and optional +requirements+. + + def find_all_by_name(name, *requirements) + req = Gem::Requirement.create(*requirements) + env_req = Gem.env_requirement(name) + + matches = stubs_for(name).find_all do |spec| + req.satisfied_by?(spec.version) && env_req.satisfied_by?(spec.version) + end.map(&:to_spec) + + if name == "bundler" && !req.specific? + require_relative "bundler_version_finder" + Gem::BundlerVersionFinder.prioritize!(matches) + end + + matches + end + ## # Return the best specification in the record that contains the file matching +path+. diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb index 43f695f147a7d3..8eedb6c03aa48d 100644 --- a/test/rubygems/test_gem_commands_setup_command.rb +++ b/test/rubygems/test_gem_commands_setup_command.rb @@ -159,6 +159,23 @@ def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home end end + def test_destdir_flag_regenerates_binstubs + # install to destdir + destdir = File.join(@tempdir, "foo") + gem_bin_path = gem_install "destdir-only-gem", install_dir: destdir + + # change binstub manually + write_file gem_bin_path do |io| + io.puts "I changed it!" + end + + @cmd.options[:destdir] = destdir + @cmd.options[:prefix] = "/" + @cmd.execute + + assert_match(/\A#!/, File.read(gem_bin_path)) + end + def test_files_in assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem], @cmd.files_in("lib").sort @@ -412,7 +429,7 @@ def create_dummy_files(list) end end - def gem_install(name) + def gem_install(name, **options) gem = util_spec name do |s| s.executables = [name] s.files = %W[bin/#{name}] @@ -420,8 +437,8 @@ def gem_install(name) write_file File.join @tempdir, "bin", name do |f| f.puts "#!/usr/bin/ruby" end - install_gem gem - File.join @gemhome, "bin", name + install_gem gem, **options + File.join options[:install_dir] || @gemhome, "bin", name end def gem_install_with_plugin(name) From 477b13ba17d595cda5c8d38da145ef2600702af5 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 09:41:52 -0400 Subject: [PATCH 130/151] [ruby/prism] Update unterminated string error location https://github.com/ruby/prism/commit/33d12afa60 --- prism/prism.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/prism/prism.c b/prism/prism.c index 97d47c8985f109..41075502233727 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -16878,6 +16878,7 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { // start with a single string content node. pm_string_t unescaped; pm_token_t content; + if (match1(parser, PM_TOKEN_EOF)) { unescaped = PM_STRING_EMPTY; content = not_provided(parser); @@ -16940,7 +16941,19 @@ parse_strings(pm_parser_t *parser, pm_node_t *current) { if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) { node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped); pm_node_flag_set(node, parse_unescaped_encoding(parser)); - expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF); + + // Kind of odd behavior, but basically if we have an + // unterminated string and it ends in a newline, we back up one + // character so that the error message is on the last line of + // content in the string. + if (!accept1(parser, PM_TOKEN_STRING_END)) { + const uint8_t *location = parser->previous.end; + if (location > parser->start && location[-1] == '\n') location--; + pm_parser_err(parser, location, location, PM_ERR_STRING_LITERAL_EOF); + + parser->previous.start = parser->previous.end; + parser->previous.type = PM_TOKEN_MISSING; + } } else if (accept1(parser, PM_TOKEN_LABEL_END)) { node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)); } else { From 011668883ca62bc727f372fa8abb6a64e3a33aae Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 10:01:30 -0400 Subject: [PATCH 131/151] [ruby/prism] Always go to string lex mode even if EOF https://github.com/ruby/prism/commit/57d5c9be2c --- prism/prism.c | 5 +---- test/prism/errors_test.rb | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 41075502233727..e6f10f0810aab0 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11375,10 +11375,7 @@ parser_lex(pm_parser_t *parser) { const uint8_t delimiter = pm_lex_percent_delimiter(parser); lex_mode_push_string(parser, true, false, lex_mode_incrementor(delimiter), lex_mode_terminator(delimiter)); - - if (parser->current.end < parser->end) { - LEX(PM_TOKEN_STRING_BEGIN); - } + LEX(PM_TOKEN_STRING_BEGIN); } // Delimiters for %-literals cannot be alphanumeric. We diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index c6991519c50a12..65b913fc3242ef 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -222,7 +222,7 @@ def test_unterminated_interpolated_symbol def test_cr_without_lf_in_percent_expression assert_errors expression("%\r"), "%\r", [ - ["invalid `%` token", 0..2], + ["unterminated string meets end of file", 2..2], ] end From 7a4b9d1614bfea5277deaab842c30e19a842a827 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 10:23:31 -0400 Subject: [PATCH 132/151] [ruby/prism] Match CRuby error message for unknown % string https://github.com/ruby/prism/commit/863197629c --- prism/templates/src/diagnostic.c.erb | 2 +- test/prism/errors_test.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 451f9c3f7cd80c..8e63dd337b65c1 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -235,7 +235,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_MULTIBYTE_CHARACTER] = { "invalid multibyte character 0x%X", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_ESCAPE] = { "invalid multibyte escape: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_PRINTABLE_CHARACTER] = { "invalid character `%c`", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_INVALID_PERCENT] = { "invalid `%` token", PM_ERROR_LEVEL_SYNTAX }, // TODO WHAT? + [PM_ERR_INVALID_PERCENT] = { "unknown type of %string", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ELSE] = { "Invalid retry after else", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ENSURE] = { "Invalid retry after ensure", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_WITHOUT_RESCUE] = { "Invalid retry without rescue", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 65b913fc3242ef..0cf1c6925bb3fe 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -208,7 +208,7 @@ def test_missing_terminator_in_parentheses def test_unterminated_argument_expression assert_errors expression('a %'), 'a %', [ - ["invalid `%` token", 2..3], + ["unknown type of %string", 2..3], ["unexpected end-of-input; expected an expression after the operator", 3..3], ["unexpected end-of-input, assuming it is closing the parent top level context", 3..3] ] @@ -1400,7 +1400,7 @@ def test_invalid_number_underscores end def test_alnum_delimiters - error_messages = ["invalid `%` token"] + error_messages = ["unknown type of %string"] assert_error_messages "%qXfooX", error_messages assert_error_messages "%QXfooX", error_messages From 910bb4923066b29b42692a82c7310a7fbc36ebb9 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 10:38:16 -0400 Subject: [PATCH 133/151] [ruby/prism] Update error message for invalid % at EOF https://github.com/ruby/prism/commit/178d4f66fd --- prism/config.yml | 1 + prism/prism.c | 2 +- prism/templates/src/diagnostic.c.erb | 1 + test/prism/errors_test.rb | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/prism/config.yml b/prism/config.yml index c48e5f28dc7992..0652cc4a9fa2bf 100644 --- a/prism/config.yml +++ b/prism/config.yml @@ -153,6 +153,7 @@ errors: - INVALID_NUMBER_UNDERSCORE_INNER - INVALID_NUMBER_UNDERSCORE_TRAILING - INVALID_PERCENT + - INVALID_PERCENT_EOF - INVALID_PRINTABLE_CHARACTER - INVALID_RETRY_AFTER_ELSE - INVALID_RETRY_AFTER_ENSURE diff --git a/prism/prism.c b/prism/prism.c index e6f10f0810aab0..6befa6bab14590 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -11356,7 +11356,7 @@ parser_lex(pm_parser_t *parser) { // operator because we don't want to move into the string // lex mode unnecessarily. if ((lex_state_beg_p(parser) || lex_state_arg_p(parser)) && (parser->current.end >= parser->end)) { - pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT); + pm_parser_err_current(parser, PM_ERR_INVALID_PERCENT_EOF); LEX(PM_TOKEN_PERCENT); } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 8e63dd337b65c1..989283fef0892b 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -236,6 +236,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_MULTIBYTE_ESCAPE] = { "invalid multibyte escape: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_PRINTABLE_CHARACTER] = { "invalid character `%c`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_PERCENT] = { "unknown type of %string", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_PERCENT_EOF] = { "unterminated quoted string meets end of file", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ELSE] = { "Invalid retry after else", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_AFTER_ENSURE] = { "Invalid retry after ensure", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_RETRY_WITHOUT_RESCUE] = { "Invalid retry without rescue", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 0cf1c6925bb3fe..1357c97cf97ee5 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -208,7 +208,7 @@ def test_missing_terminator_in_parentheses def test_unterminated_argument_expression assert_errors expression('a %'), 'a %', [ - ["unknown type of %string", 2..3], + ["unterminated quoted string meets end of file", 2..3], ["unexpected end-of-input; expected an expression after the operator", 3..3], ["unexpected end-of-input, assuming it is closing the parent top level context", 3..3] ] From 0e11781f216c0dbf5f5f3dfbfbb43e14bdfd82ab Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 11:04:01 -0400 Subject: [PATCH 134/151] [ruby/prism] Match CRuby invalid character error message https://github.com/ruby/prism/commit/8d4c5c2bca --- prism/templates/src/diagnostic.c.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 989283fef0892b..16472bb9cf5b53 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -230,7 +230,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_INVALID_NUMBER_OCTAL] = { "invalid octal number; numeric literal without digits", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_UNDERSCORE_INNER] = { "invalid underscore placement in number", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_NUMBER_UNDERSCORE_TRAILING] = { "trailing '_' in number", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_INVALID_CHARACTER] = { "invalid character 0x%X", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_INVALID_CHARACTER] = { "Invalid char '\\x%02X' in expression", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_CHAR] = { "invalid multibyte char (%s)", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_CHARACTER] = { "invalid multibyte character 0x%X", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_INVALID_MULTIBYTE_ESCAPE] = { "invalid multibyte escape: /%.*s/", PM_ERROR_LEVEL_SYNTAX }, From d314d976d4542f4facbacb8f644014fcbdbcc34d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 11:10:43 -0400 Subject: [PATCH 135/151] [ruby/prism] Match CRuby invalid escape character syntax error message https://github.com/ruby/prism/commit/0ef5658dcc --- prism/templates/src/diagnostic.c.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index 16472bb9cf5b53..eab3dd26bff00c 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -158,10 +158,10 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_EMBVAR_INVALID] = { "invalid embedded variable", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_END_UPCASE_BRACE] = { "expected a `{` after `END`", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_END_UPCASE_TERM] = { "expected a `}` to close the `END` statement", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_CONTROL] = { "invalid control escape sequence", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_CONTROL] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT] = { "invalid control escape sequence; control cannot be repeated", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_HEXADECIMAL] = { "invalid hex escape sequence", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_META] = { "invalid meta escape sequence", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_META] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_LEVEL_SYNTAX }, From 14debd13210a9a187241a24360bad640e5cd2aa4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 09:24:38 -0400 Subject: [PATCH 136/151] [PRISM] Enable TestSyntax#test__END___cr --- test/.excludes-prism/TestSyntax.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index 0d312618c72836..c65ed92823387e 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -1,6 +1,4 @@ -exclude(:test__END___cr, "error message format") exclude(:test_dedented_heredoc_continued_line, "heredoc line continuation dedent calculation") -exclude(:test_duplicated_when, "error message format") exclude(:test_error_message_encoding, "syntax error message encoding") exclude(:test_it, "https://github.com/ruby/prism/issues/2323") exclude(:test_numbered_parameter, "should raise syntax error for numbered parameters in inner blocks") @@ -8,5 +6,6 @@ exclude(:test_unterminated_heredoc_cr, "quoted \r heredoc terminators should not match \r\n") exclude(:test_warn_balanced, "missing warning for ** being interpreted as a binary operator") +exclude(:test_duplicated_when, "https://bugs.ruby-lang.org/issues/20401") exclude(:test_optional_self_reference, "https://bugs.ruby-lang.org/issues/20478") exclude(:test_keyword_self_reference, "https://bugs.ruby-lang.org/issues/20478") From 52401a32e5699870d2eef9a492532a0729be204a Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 09:43:09 -0400 Subject: [PATCH 137/151] [PRISM] Enable TestSyntax#test_syntax_error_at_newline --- test/.excludes-prism/TestSyntax.rb | 1 - test/ruby/test_syntax.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/.excludes-prism/TestSyntax.rb b/test/.excludes-prism/TestSyntax.rb index c65ed92823387e..6e9f51604a370e 100644 --- a/test/.excludes-prism/TestSyntax.rb +++ b/test/.excludes-prism/TestSyntax.rb @@ -2,7 +2,6 @@ exclude(:test_error_message_encoding, "syntax error message encoding") exclude(:test_it, "https://github.com/ruby/prism/issues/2323") exclude(:test_numbered_parameter, "should raise syntax error for numbered parameters in inner blocks") -exclude(:test_syntax_error_at_newline, "error message format") exclude(:test_unterminated_heredoc_cr, "quoted \r heredoc terminators should not match \r\n") exclude(:test_warn_balanced, "missing warning for ** being interpreted as a binary operator") diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb index edc3a3cec3fb9d..56b97789e531ac 100644 --- a/test/ruby/test_syntax.rb +++ b/test/ruby/test_syntax.rb @@ -1601,7 +1601,7 @@ def test_syntax_error_in_rescue end def test_syntax_error_at_newline - expected = "\n ^" + expected = /(\n|\| ) \^/ assert_syntax_error("%[abcdef", expected) assert_syntax_error("%[abcdef\n", expected) end From 58f993c500ae3f1051fbaa76d21e85bec93fa1f7 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 10:51:04 -0400 Subject: [PATCH 138/151] [PRISM] Enable TestParse#test_percent --- test/.excludes-prism/TestParse.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 8ff7dba1f4cdcd..317b09250336c9 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,5 +1,4 @@ exclude(:test_invalid_char, "error message format") -exclude(:test_percent, "error message format") exclude(:test_question, "error message format") exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") From 7eb45a40fdc8d3e077089b13cef90f2d350509e1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 11:05:47 -0400 Subject: [PATCH 139/151] [PRISM] Enable TestParse#test_invalid_char --- test/.excludes-prism/TestParse.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index 317b09250336c9..cf5f1a873547cc 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,4 +1,3 @@ -exclude(:test_invalid_char, "error message format") exclude(:test_question, "error message format") exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") From 07241dfac8b64c16c0fc35da55fdb7da8a10dfe4 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 11:11:42 -0400 Subject: [PATCH 140/151] [PRISM] Enable TestParse#test_question --- test/.excludes-prism/TestParse.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index cf5f1a873547cc..ba718d063c0800 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,4 +1,3 @@ -exclude(:test_question, "error message format") exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") exclude(:test_void_value_in_rhs, "missing raising error for some void value expressions") From 286d3032a794500a81bcac9f10363f953d368ef6 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 12:29:14 -0400 Subject: [PATCH 141/151] [ruby/prism] More mixed encoding errors https://github.com/ruby/prism/commit/2a43b4f55c --- prism/prism.c | 8 ++++++++ prism/util/pm_strpbrk.c | 38 ++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 6befa6bab14590..be6b52f5b1bc26 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -15382,6 +15382,10 @@ parse_string_part(pm_parser_t *parser) { // "aaa #{bbb} #@ccc ddd" // ^^^^^^ case PM_TOKEN_EMBEXPR_BEGIN: { + // Ruby disallows seeing encoding around interpolation in strings, + // even though it is known at parse time. + parser->explicit_encoding = NULL; + pm_lex_state_t state = parser->lex_state; int brace_nesting = parser->brace_nesting; @@ -15414,6 +15418,10 @@ parse_string_part(pm_parser_t *parser) { // "aaa #{bbb} #@ccc ddd" // ^^^^^ case PM_TOKEN_EMBVAR: { + // Ruby disallows seeing encoding around interpolation in strings, + // even though it is known at parse time. + parser->explicit_encoding = NULL; + lex_state_set(parser, PM_LEX_STATE_BEG); parser_lex(parser); diff --git a/prism/util/pm_strpbrk.c b/prism/util/pm_strpbrk.c index 6c8dea183679c6..916a4cc3fd3c16 100644 --- a/prism/util/pm_strpbrk.c +++ b/prism/util/pm_strpbrk.c @@ -8,6 +8,27 @@ pm_strpbrk_invalid_multibyte_character(pm_parser_t *parser, const uint8_t *start pm_diagnostic_list_append_format(&parser->error_list, start, end, PM_ERR_INVALID_MULTIBYTE_CHARACTER, *start); } +/** + * Set the explicit encoding for the parser to the current encoding. + */ +static inline void +pm_strpbrk_explicit_encoding_set(pm_parser_t *parser, const uint8_t *source, size_t width) { + if (parser->explicit_encoding != NULL) { + if (parser->explicit_encoding == parser->encoding) { + // Okay, we already locked to this encoding. + } else if (parser->explicit_encoding == PM_ENCODING_UTF_8_ENTRY) { + // Not okay, we already found a Unicode escape sequence and this + // conflicts. + pm_diagnostic_list_append_format(&parser->error_list, source, source + width, PM_ERR_MIXED_ENCODING, parser->encoding->name); + } else { + // Should not be anything else. + assert(false && "unreachable"); + } + } + + parser->explicit_encoding = parser->encoding; +} + /** * This is the default path. */ @@ -52,7 +73,7 @@ pm_strpbrk_utf8(pm_parser_t *parser, const uint8_t *source, const uint8_t *chars * This is the path when the encoding is ASCII-8BIT. */ static inline const uint8_t * -pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maximum) { +pm_strpbrk_ascii_8bit(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; while (index < maximum) { @@ -60,6 +81,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi return source + index; } + if (validate && source[index] >= 0x80) pm_strpbrk_explicit_encoding_set(parser, source, 1); index++; } @@ -72,6 +94,7 @@ pm_strpbrk_ascii_8bit(const uint8_t *source, const uint8_t *charset, size_t maxi static inline const uint8_t * pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; + const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -81,7 +104,8 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t if (source[index] < 0x80) { index++; } else { - size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + if (validate) pm_strpbrk_explicit_encoding_set(parser, source, width); if (width > 0) { index += width; @@ -96,7 +120,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t do { index++; - } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); + } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index); } @@ -113,6 +137,7 @@ pm_strpbrk_multi_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t static inline const uint8_t * pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, size_t maximum, bool validate) { size_t index = 0; + const pm_encoding_t *encoding = parser->encoding; while (index < maximum) { if (strchr((const char *) charset, source[index]) != NULL) { @@ -122,7 +147,8 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t if (source[index] < 0x80 || !validate) { index++; } else { - size_t width = parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + size_t width = encoding->char_width(source + index, (ptrdiff_t) (maximum - index)); + pm_strpbrk_explicit_encoding_set(parser, source, width); if (width > 0) { index += width; @@ -135,7 +161,7 @@ pm_strpbrk_single_byte(pm_parser_t *parser, const uint8_t *source, const uint8_t do { index++; - } while (index < maximum && parser->encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); + } while (index < maximum && encoding->char_width(source + index, (ptrdiff_t) (maximum - index)) == 0); pm_strpbrk_invalid_multibyte_character(parser, source + start, source + index); } @@ -171,7 +197,7 @@ pm_strpbrk(pm_parser_t *parser, const uint8_t *source, const uint8_t *charset, p } else if (!parser->encoding_changed) { return pm_strpbrk_utf8(parser, source, charset, (size_t) length, validate); } else if (parser->encoding == PM_ENCODING_ASCII_8BIT_ENTRY) { - return pm_strpbrk_ascii_8bit(source, charset, (size_t) length); + return pm_strpbrk_ascii_8bit(parser, source, charset, (size_t) length, validate); } else if (parser->encoding->multibyte) { return pm_strpbrk_multi_byte(parser, source, charset, (size_t) length, validate); } else { From 0b4cf461e02b84c5ede91ff46b88d844353e1c3d Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 13:17:04 -0400 Subject: [PATCH 142/151] [PRISM] Enable TestM17N#test_string_mixed_unicode --- test/.excludes-prism/TestM17N.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/.excludes-prism/TestM17N.rb b/test/.excludes-prism/TestM17N.rb index f10c9632d96dda..0367ffa9f2da88 100644 --- a/test/.excludes-prism/TestM17N.rb +++ b/test/.excludes-prism/TestM17N.rb @@ -1,2 +1 @@ exclude(:test_regexp_usascii, "x80 should raise syntax error") -exclude(:test_string_mixed_unicode, "should raise mixed encoding error") From 012a80d768affcfb4e747a358f4941647381776b Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 13:28:27 -0400 Subject: [PATCH 143/151] [PRISM] Enable TestISeq#test_syntax_error_message --- test/.excludes-prism/TestISeq.rb | 2 -- test/ruby/test_iseq.rb | 16 +++++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/test/.excludes-prism/TestISeq.rb b/test/.excludes-prism/TestISeq.rb index ee3d92494e440e..499ae2e53dbe33 100644 --- a/test/.excludes-prism/TestISeq.rb +++ b/test/.excludes-prism/TestISeq.rb @@ -1,4 +1,2 @@ -exclude(:test_syntax_error_message, "error message format") - exclude(:test_each_child, "https://bugs.ruby-lang.org/issues/20479") exclude(:test_trace_points, "https://bugs.ruby-lang.org/issues/20479") diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb index d2a39e673f3ae6..df4b6651b0216e 100644 --- a/test/ruby/test_iseq.rb +++ b/test/ruby/test_iseq.rb @@ -347,11 +347,17 @@ def y@;end end end assert_equal([m1, e1.message], [m2, e2.message], feature11951) - message = e1.message.each_line - message.with_index(1) do |line, i| - next if /^ / =~ line - assert_send([line, :start_with?, __FILE__], - proc {message.map {|l, j| (i == j ? ">" : " ") + l}.join("")}) + + if e1.message.lines[0] == "#{__FILE__}:#{line}: syntax errors found\n" + # Prism lays out the error messages in line with the source, so the + # following assertions do not make sense in that context. + else + message = e1.message.each_line + message.with_index(1) do |line, i| + next if /^ / =~ line + assert_send([line, :start_with?, __FILE__], + proc {message.map {|l, j| (i == j ? ">" : " ") + l}.join("")}) + end end end From 98e1e610f6df95aa89481fd92a31a75a808ce2d1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 14:28:48 -0400 Subject: [PATCH 144/151] [ruby/prism] Update more escape error messages to match CRuby https://github.com/ruby/prism/commit/ab43b3ab66 --- prism/prism.c | 37 +++++++++++++++++++++------- prism/templates/src/diagnostic.c.erb | 6 ++--- test/prism/errors_test.rb | 5 ++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index be6b52f5b1bc26..75f143216122b5 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -9658,7 +9658,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE_LONG); } else if (hexadecimal_length == 0) { // there are not hexadecimal characters - pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE); + pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE); + pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM); return; } @@ -9707,10 +9708,6 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre } } - if (flags & (PM_ESCAPE_FLAG_CONTROL | PM_ESCAPE_FLAG_META)) { - pm_parser_err(parser, start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); - } - return; } case 'c': { @@ -9733,6 +9730,12 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); + return; + } + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_CONTROL); return; case ' ': @@ -9760,7 +9763,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre case 'C': { parser->current.end++; if (peek(parser) != '-') { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_CONTROL); return; } @@ -9783,6 +9787,12 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); + return; + } + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_CONTROL); return; case ' ': @@ -9797,7 +9807,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; default: { if (!char_is_ascii_printable(peeked)) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_CONTROL); return; } @@ -9810,7 +9821,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre case 'M': { parser->current.end++; if (peek(parser) != '-') { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META); return; } @@ -9828,6 +9840,12 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; } parser->current.end++; + + if (match(parser, 'u') || match(parser, 'U')) { + pm_parser_err(parser, parser->current.start, parser->current.end, PM_ERR_INVALID_ESCAPE_CHARACTER); + return; + } + escape_read(parser, buffer, regular_expression_buffer, flags | PM_ESCAPE_FLAG_META); return; case ' ': @@ -9842,7 +9860,8 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre return; default: if (!char_is_ascii_printable(peeked)) { - pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META); + size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end); + pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META); return; } diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb index eab3dd26bff00c..d9e195e08f3f0e 100644 --- a/prism/templates/src/diagnostic.c.erb +++ b/prism/templates/src/diagnostic.c.erb @@ -167,7 +167,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "invalid Unicode escape sequence; needs closing `}`", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "unterminated Unicode escape", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "unexpected %s, expecting end-of-input", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_LEVEL_SYNTAX }, @@ -330,12 +330,12 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = { [PM_ERR_STATEMENT_PREEXE_BEGIN] = { "unexpected a `BEGIN` at a non-statement position", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STATEMENT_UNDEF] = { "unexpected an `undef` at a non-statement position", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_CONCATENATION] = { "expected a string for concatenation", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_STRING_INTERPOLATED_TERM] = { "expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_STRING_INTERPOLATED_TERM] = { "unterminated string; expected a closing delimiter for the interpolated string", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_EOF] = { "unterminated string meets end of file", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_STRING_LITERAL_TERM] = { "unexpected %s, expected a string literal terminator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_SYMBOL_INVALID] = { "invalid symbol", PM_ERROR_LEVEL_SYNTAX }, // TODO expected symbol? prism.c ~9719 [PM_ERR_SYMBOL_TERM_DYNAMIC] = { "unterminated quoted string; expected a closing delimiter for the dynamic symbol", PM_ERROR_LEVEL_SYNTAX }, - [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX }, + [PM_ERR_SYMBOL_TERM_INTERPOLATED] = { "unterminated symbol; expected a closing delimiter for the interpolated symbol", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_LEVEL_SYNTAX }, [PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_SYNTAX }, diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb index 1357c97cf97ee5..3670b90dd76e16 100644 --- a/test/prism/errors_test.rb +++ b/test/prism/errors_test.rb @@ -216,7 +216,7 @@ def test_unterminated_argument_expression def test_unterminated_interpolated_symbol assert_error_messages ":\"#", [ - "expected a closing delimiter for the interpolated symbol" + "unterminated symbol; expected a closing delimiter for the interpolated symbol" ] end @@ -715,12 +715,13 @@ def test_do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_charact assert_errors expected, '"\u{000z}"', [ ["invalid Unicode escape sequence", 7..7], + ["unterminated Unicode escape", 7..7] ] end def test_unterminated_unicode_brackets_should_be_a_syntax_error assert_errors expression('?\\u{3'), '?\\u{3', [ - ["invalid Unicode escape sequence; needs closing `}`", 1..5], + ["unterminated Unicode escape", 1..5], ] end From 92af7054989e6bb605482178f97cee5e59ec9326 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 15:07:03 -0400 Subject: [PATCH 145/151] [ruby/prism] Truncate source lines in errors messages when too long https://github.com/ruby/prism/commit/72518f5716 --- prism/prism.c | 48 +++++++++++++++++++++++++++----- test/prism/format_errors_test.rb | 42 +++++++++++++++++++++++++--- test/prism/newline_test.rb | 1 + 3 files changed, 80 insertions(+), 11 deletions(-) diff --git a/prism/prism.c b/prism/prism.c index 75f143216122b5..d203b4b7202065 100644 --- a/prism/prism.c +++ b/prism/prism.c @@ -21592,6 +21592,7 @@ typedef struct { #define PM_COLOR_GRAY "\033[38;5;102m" #define PM_COLOR_RED "\033[1;31m" #define PM_COLOR_RESET "\033[m" +#define PM_ERROR_TRUNCATE 30 static inline pm_error_t * pm_parser_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_list, const pm_newline_list_t *newline_list) { @@ -21646,7 +21647,7 @@ pm_parser_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_l } static inline void -pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, int32_t line, pm_buffer_t *buffer) { +pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, int32_t line, uint32_t column_start, uint32_t column_end, pm_buffer_t *buffer) { int32_t line_delta = line - parser->start_line; assert(line_delta >= 0); @@ -21663,9 +21664,25 @@ pm_parser_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t } pm_buffer_append_format(buffer, number_prefix, line); + + // Here we determine if we should truncate the end of the line. + bool truncate_end = false; + if ((column_end != 0) && ((end - (start + column_end)) >= PM_ERROR_TRUNCATE)) { + end = start + column_end + PM_ERROR_TRUNCATE; + truncate_end = true; + } + + // Here we determine if we should truncate the start of the line. + if (column_start >= PM_ERROR_TRUNCATE) { + pm_buffer_append_string(buffer, "... ", 4); + start += column_start; + } + pm_buffer_append_string(buffer, (const char *) start, (size_t) (end - start)); - if (end == parser->end && end[-1] != '\n') { + if (truncate_end) { + pm_buffer_append_string(buffer, " ...\n", 5); + } else if (end == parser->end && end[-1] != '\n') { pm_buffer_append_string(buffer, "\n", 1); } } @@ -21780,6 +21797,7 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, // display the same line twice in case the errors are close enough in the // source. int32_t last_line = parser->start_line - 1; + uint32_t last_column_start = 0; const pm_encoding_t *encoding = parser->encoding; for (size_t index = 0; index < error_list->size; index++) { @@ -21794,11 +21812,11 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, } pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 2, buffer); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 2, 0, 0, buffer); } pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 1, buffer); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line - 1, 0, 0, buffer); } // If this is the first error or we're on a new line, then we'll display @@ -21809,7 +21827,17 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, } else { pm_buffer_append_string(buffer, "> ", 2); } - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line, buffer); + + last_column_start = error->column_start; + + // Find the maximum column end of all the errors on this line. + uint32_t column_end = error->column_end; + for (size_t next_index = index + 1; next_index < error_list->size; next_index++) { + if (errors[next_index].line != error->line) break; + if (errors[next_index].column_end > column_end) column_end = errors[next_index].column_end; + } + + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, error->line, error->column_start, column_end, buffer); } const uint8_t *start = &parser->start[newline_list->offsets[error->line - start_line]]; @@ -21828,6 +21856,11 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_append_string(buffer, error_format.blank_prefix, error_format.blank_prefix_length); size_t column = 0; + if (last_column_start >= PM_ERROR_TRUNCATE) { + pm_buffer_append_string(buffer, " ", 4); + column = last_column_start; + } + while (column < error->column_start) { pm_buffer_append_byte(buffer, ' '); @@ -21867,12 +21900,12 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, if (next_line - last_line > 1) { pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, 0, 0, buffer); } if (next_line - last_line > 1) { pm_buffer_append_string(buffer, " ", 2); - pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, buffer); + pm_parser_errors_format_line(parser, newline_list, error_format.number_prefix, ++last_line, 0, 0, buffer); } } @@ -21880,6 +21913,7 @@ pm_parser_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, xfree(errors); } +#undef PM_ERROR_TRUNCATE #undef PM_COLOR_GRAY #undef PM_COLOR_RED #undef PM_COLOR_RESET diff --git a/test/prism/format_errors_test.rb b/test/prism/format_errors_test.rb index a1edbef2e86bd1..63206d5765c775 100644 --- a/test/prism/format_errors_test.rb +++ b/test/prism/format_errors_test.rb @@ -6,19 +6,53 @@ module Prism class FormatErrorsTest < TestCase - def test_format_errors - assert_equal <<~ERROR, Debug.format_errors("<>", false) + def test_basic + expected = <<~ERROR > 1 | <> | ^ unexpected '<', ignoring it | ^ unexpected '>', ignoring it ERROR - assert_equal <<~'ERROR', Debug.format_errors('"%W"\u"', false) - > 1 | "%W"\u" + assert_equal expected, Debug.format_errors("<>", false) + end + + def test_multiple + expected = <<~ERROR + > 1 | "%W"\\u" | ^ unexpected backslash, ignoring it | ^ unexpected local variable or method, expecting end-of-input | ^ unterminated string meets end of file ERROR + + assert_equal expected, Debug.format_errors('"%W"\u"', false) + end + + def test_truncate_start + expected = <<~ERROR + > 1 | ... <> + | ^ unexpected '<', ignoring it + | ^ unexpected '>', ignoring it + ERROR + + assert_equal expected, Debug.format_errors("#{" " * 30}<>", false) + end + + def test_truncate_end + expected = <<~ERROR + > 1 | <#{" " * 30} ... + | ^ unexpected '<', ignoring it + ERROR + + assert_equal expected, Debug.format_errors("<#{" " * 30}a", false) + end + + def test_truncate_both + expected = <<~ERROR + > 1 | ... <#{" " * 30} ... + | ^ unexpected '<', ignoring it + ERROR + + assert_equal expected, Debug.format_errors("#{" " * 30}<#{" " * 30}a", false) end end end diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb index d31fb89bc6f1c4..f7511f665cdfea 100644 --- a/test/prism/newline_test.rb +++ b/test/prism/newline_test.rb @@ -10,6 +10,7 @@ class NewlineTest < TestCase filepaths = Dir["*.rb", base: base] - %w[ encoding_test.rb errors_test.rb + format_errors_test.rb parser_test.rb regexp_test.rb static_literals_test.rb From 854cbbd5a9f031c74f9185c2cd8f3dd72784e2d1 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 14:41:11 -0400 Subject: [PATCH 146/151] [PRISM] Enable TestParse#test_string --- test/.excludes-prism/TestParse.rb | 1 - test/ruby/test_parse.rb | 54 ++++++++++++++++++------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/test/.excludes-prism/TestParse.rb b/test/.excludes-prism/TestParse.rb index ba718d063c0800..513a7ed9429a8f 100644 --- a/test/.excludes-prism/TestParse.rb +++ b/test/.excludes-prism/TestParse.rb @@ -1,3 +1,2 @@ -exclude(:test_string, "error message format") exclude(:test_truncated_source_line, "truncate error message") exclude(:test_void_value_in_rhs, "missing raising error for some void value expressions") diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index 63539270fc0793..aa484b5e0b31e7 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -555,34 +555,42 @@ def test_string mesg = 'from the backslash through the invalid char' e = assert_syntax_error('"\xg1"', /hex escape/) - assert_equal(' ^~'"\n", e.message.lines.last, mesg) + assert_match(/(^|\| ) \^~(?!~)/, e.message.lines.last, mesg) e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape') - assert_equal(' ^'"\n", e.message.lines.last, mesg) + assert_match(/(^|\| ) \^(?!~)/, e.message.lines.last, mesg) e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape') - assert_equal(' ^'"\n", e.message.lines.last, mesg) + assert_match(/(^|\| ) \^(?!~)/, e.message.lines.last, mesg) e = assert_syntax_error('"\u{xxxx', 'Unicode escape') - assert_pattern_list([ - /.*: invalid Unicode escape\n.*\n/, - / \^/, - /\n/, - /.*: unterminated Unicode escape\n.*\n/, - / \^/, - /\n/, - /.*: unterminated string.*\n.*\n/, - / \^\n/, - ], e.message) + if e.message.lines.first == "#{__FILE__}:#{__LINE__ - 1}: syntax errors found\n" + assert_pattern_list([ + /\s+\| \^ unterminated string;.+\n/, + /\s+\| \^ unterminated Unicode escape\n/, + /\s+\| \^ invalid Unicode escape sequence\n/, + ], e.message.lines[2..-1].join) + else + assert_pattern_list([ + /.*: invalid Unicode escape\n.*\n/, + / \^/, + /\n/, + /.*: unterminated Unicode escape\n.*\n/, + / \^/, + /\n/, + /.*: unterminated string.*\n.*\n/, + / \^\n/, + ], e.message) + end e = assert_syntax_error('"\M1"', /escape character syntax/) - assert_equal(' ^~~'"\n", e.message.lines.last, mesg) + assert_match(/(^|\| ) \^~~(?!~)/, e.message.lines.last, mesg) e = assert_syntax_error('"\C1"', /escape character syntax/) - assert_equal(' ^~~'"\n", e.message.lines.last, mesg) + assert_match(/(^|\| ) \^~~(?!~)/, e.message.lines.last, mesg) src = '"\xD0\u{90'"\n""000000000000000000000000" - assert_syntax_error(src, /:#{__LINE__}: unterminated/o) + assert_syntax_error(src, /(:#{__LINE__}:|> #{__LINE__} \|.+) unterminated/om) assert_syntax_error('"\u{100000000}"', /invalid Unicode escape/) assert_equal("", eval('"\u{}"')) @@ -605,22 +613,22 @@ def test_string assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax') e = assert_syntax_error('"\c\u0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~(?!~)/, e.message.lines.last) e = assert_syntax_error('"\c\U0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~(?!~)/, e.message.lines.last) e = assert_syntax_error('"\C-\u0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last) e = assert_syntax_error('"\C-\U0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last) e = assert_syntax_error('"\M-\u0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last) e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax') - assert_equal(' ^~~~~'"\n", e.message.lines.last) + assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last) e = assert_syntax_error(%["\\C-\u3042"], 'Invalid escape character syntax') - assert_match(/^\s \^(?# \\ ) ~(?# C ) ~(?# - ) ~+(?# U+3042 )$/x, e.message.lines.last) + assert_match(/(^|\|\s)\s \^(?# \\ ) ~(?# C ) ~(?# - ) ~+(?# U+3042 )($|\s)/x, e.message.lines.last) assert_not_include(e.message, "invalid multibyte char") end From b90ea8ae52d0213900cd5b8b2a47ff6a2a9442df Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Thu, 16 May 2024 07:56:58 +0200 Subject: [PATCH 147/151] [ruby/find] find.gemspec: Drop executables dir config This gem contains no executables. https://github.com/ruby/find/commit/7bd452155e --- lib/find.gemspec | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/find.gemspec b/lib/find.gemspec index cb845e940985e2..aef24a502844ca 100644 --- a/lib/find.gemspec +++ b/lib/find.gemspec @@ -25,7 +25,5 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] end From 761b90702492cd18f6746b59e77826e0302ca547 Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 15:36:04 -0400 Subject: [PATCH 148/151] [PRISM] Enable TestParse#test_truncated_source_line --- test/ruby/test_parse.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb index aa484b5e0b31e7..3857f3cc172b2c 100644 --- a/test/ruby/test_parse.rb +++ b/test/ruby/test_parse.rb @@ -1353,9 +1353,13 @@ def test_unexpected_token_after_numeric end def test_truncated_source_line - e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 0123456789012345678901234567890123456789", + lineno = __LINE__ + 1 + e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 123456789012345678901234567890123456789", /unexpected local variable or method/) + line = e.message.lines[1] + line.delete_prefix!("> #{lineno} | ") if line.start_with?(">") + assert_operator(line, :start_with?, "...") assert_operator(line, :end_with?, "...\n") end From 84d2bacb424094f1b57cff0f2dd4381e9f8bd9ed Mon Sep 17 00:00:00 2001 From: Kevin Newton Date: Thu, 16 May 2024 22:44:52 -0400 Subject: [PATCH 149/151] [ruby/irb] Reorder ruby lex clauses for unrecoverable first (https://github.com/ruby/irb/pull/956) When a syntax error includes multiple error messages, we want to check for unrecoverable messages first so that we do not accidentally match a recoverable error later in the message. https://github.com/ruby/irb/commit/2f42b2360d --- lib/irb/ruby-lex.rb | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb index 86e340eb05e568..f6ac7f0f5f51f6 100644 --- a/lib/irb/ruby-lex.rb +++ b/lib/irb/ruby-lex.rb @@ -219,27 +219,6 @@ def check_code_syntax(code, local_variables:) :unrecoverable_error rescue SyntaxError => e case e.message - when /unterminated (?:string|regexp) meets end of file/ - # "unterminated regexp meets end of file" - # - # example: - # / - # - # "unterminated string meets end of file" - # - # example: - # ' - return :recoverable_error - when /unexpected end-of-input/ - # "syntax error, unexpected end-of-input, expecting keyword_end" - # - # example: - # if true - # hoge - # if false - # fuga - # end - return :recoverable_error when /unexpected keyword_end/ # "syntax error, unexpected keyword_end" # @@ -262,6 +241,27 @@ def check_code_syntax(code, local_variables:) # example: # method / f / return :unrecoverable_error + when /unterminated (?:string|regexp) meets end of file/ + # "unterminated regexp meets end of file" + # + # example: + # / + # + # "unterminated string meets end of file" + # + # example: + # ' + return :recoverable_error + when /unexpected end-of-input/ + # "syntax error, unexpected end-of-input, expecting keyword_end" + # + # example: + # if true + # hoge + # if false + # fuga + # end + return :recoverable_error else return :other_error end From 0f8f0386a8c32812cc5738bdf9c8e74eec34440b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 02:18:31 +0000 Subject: [PATCH 150/151] Bump actions/checkout from 4.1.5 to 4.1.6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...a5ac7e51b41094c92402da3b24376905380afc29) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/annocheck.yml | 2 +- .github/workflows/baseruby.yml | 2 +- .github/workflows/bundled_gems.yml | 2 +- .github/workflows/check_dependencies.yml | 2 +- .github/workflows/check_misc.yml | 2 +- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/compilers.yml | 2 +- .github/workflows/macos.yml | 2 +- .github/workflows/mingw.yml | 2 +- .github/workflows/prism.yml | 2 +- .github/workflows/rjit-bindgen.yml | 2 +- .github/workflows/rjit.yml | 2 +- .github/workflows/scorecards.yml | 2 +- .github/workflows/spec_guards.yml | 2 +- .github/workflows/ubuntu.yml | 2 +- .github/workflows/wasm.yml | 2 +- .github/workflows/windows.yml | 2 +- .github/workflows/yjit-macos.yml | 4 ++-- .github/workflows/yjit-ubuntu.yml | 6 +++--- 19 files changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index 0590d8c75e1d7d..6c03f52289199f 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -63,7 +63,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 4876251b82b4fd..ce979c9e7a8c1a 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -56,7 +56,7 @@ jobs: ruby-version: ${{ matrix.ruby }} bundler: none - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - uses: ./.github/actions/setup/ubuntu diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index c509967c351845..6f06451a99e7c2 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index fbad01a8f47a4d..8ecae4f2236443 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -45,7 +45,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index c9a182c57b163d..f26319f4480196 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 5fa6da51700ef7..d6a2e297be3d59 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -63,7 +63,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - name: Install libraries if: ${{ contains(matrix.os, 'macos') }} diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index d4b047b4e93c85..8937a5b15f28c2 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -233,7 +233,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 9d0ff5ae373bf1..e71706b186070d 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -52,7 +52,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index f4d399751a6574..4170369def04de 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -97,7 +97,7 @@ jobs: $result working-directory: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml index 7d4cdcb47ac147..78b6469db19a54 100644 --- a/.github/workflows/prism.yml +++ b/.github/workflows/prism.yml @@ -55,7 +55,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml index 799be7a847f4df..c4cfe9ed83c0de 100644 --- a/.github/workflows/rjit-bindgen.yml +++ b/.github/workflows/rjit-bindgen.yml @@ -51,7 +51,7 @@ jobs: with: ruby-version: '3.1' - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/rjit.yml b/.github/workflows/rjit.yml index f1cd70afa4210f..509088db7d54ff 100644 --- a/.github/workflows/rjit.yml +++ b/.github/workflows/rjit.yml @@ -55,7 +55,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index bfc7b958635227..85ee3e2a48c007 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -32,7 +32,7 @@ jobs: steps: - name: 'Checkout code' - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: persist-credentials: false diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 2dc4a7b39a6392..14669a13b3c848 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -45,7 +45,7 @@ jobs: - ruby-3.3 steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - uses: ruby/setup-ruby@cacc9f1c0b3f4eb8a16a6bb0ed10897b43b9de49 # v1.176.0 with: diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index b808ac5e9e2baa..697056df604751 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -58,7 +58,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 09f8e4bbccdff4..764ca2d21ce8f3 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -61,7 +61,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index d4b9bd644aaf96..fcf600263bb84c 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -123,7 +123,7 @@ jobs: Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH shell: pwsh - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml index c6acd3c614b2d0..bd17b302ae72a1 100644 --- a/.github/workflows/yjit-macos.yml +++ b/.github/workflows/yjit-macos.yml @@ -37,7 +37,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 - run: RUST_BACKTRACE=1 cargo test working-directory: yjit @@ -81,7 +81,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 2b0c79db28436d..bd7e25a9cd62a2 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -36,7 +36,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 # For now we can't run cargo test --offline because it complains about the # capstone dependency, even though the dependency is optional @@ -68,7 +68,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 # Check that we don't have linting errors in release mode, too - run: cargo clippy --all-targets --all-features @@ -127,7 +127,7 @@ jobs: )}} steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: sparse-checkout-cone-mode: false sparse-checkout: /.github From 534f1c37e3d7527080921fcc0dd3a42a83ac311d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 02:24:44 +0000 Subject: [PATCH 151/151] Bump actions/checkout in /.github/actions/setup/directories Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...a5ac7e51b41094c92402da3b24376905380afc29) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/actions/setup/directories/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index db1ae87fffefc5..5264e0e9692b75 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -88,7 +88,7 @@ runs: git config --global init.defaultBranch garbage - if: inputs.checkout - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 + uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 with: path: ${{ inputs.srcdir }} fetch-depth: ${{ inputs.fetch-depth }}