[ruby/prism] Fix warning when `#!` ends with carriage return

https://github.com/ruby/prism/commit/5753fb6260
This commit is contained in:
Alexander Momchilov 2024-08-22 18:30:59 -04:00 коммит произвёл git
Родитель 83e72fde83
Коммит 2fbaff5351
2 изменённых файлов: 57 добавлений и 10 удалений

Просмотреть файл

@ -21767,7 +21767,7 @@ pm_strnstr(const char *big, const char *little, size_t big_length) {
*/
static void
pm_parser_warn_shebang_carriage_return(pm_parser_t *parser, const uint8_t *start, size_t length) {
if (length > 2 && start[length - 1] == '\n' && start[length - 2] == '\r') {
if (length > 2 && start[length - 2] == '\r' && start[length - 1] == '\n') {
pm_parser_warn(parser, start, start + length, PM_WARN_SHEBANG_CARRIAGE_RETURN);
}
}
@ -21960,11 +21960,17 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
const char *engine;
if ((engine = pm_strnstr((const char *) parser->start, "ruby", length)) != NULL) {
pm_parser_warn_shebang_carriage_return(parser, parser->start, length);
if (newline != NULL) parser->encoding_comment_start = newline + 1;
if (newline != NULL) {
size_t length_including_newline = length + 1;
pm_parser_warn_shebang_carriage_return(parser, parser->start, length_including_newline);
parser->encoding_comment_start = newline + 1;
}
if (options != NULL && options->shebang_callback != NULL) {
pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) parser->start)));
}
search_shebang = false;
} else if (!parser->parsing_eval) {
search_shebang = true;
@ -21994,17 +22000,20 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
size_t length = (size_t) ((newline != NULL ? newline : parser->end) - cursor);
if (length > 2 && cursor[0] == '#' && cursor[1] == '!') {
if (parser->newline_list.size == 1) {
pm_parser_warn_shebang_carriage_return(parser, cursor, length);
}
const char *engine;
if ((engine = pm_strnstr((const char *) cursor, "ruby", length)) != NULL) {
found_shebang = true;
if (newline != NULL) parser->encoding_comment_start = newline + 1;
if (newline != NULL) {
size_t length_including_newline = length + 1;
pm_parser_warn_shebang_carriage_return(parser, cursor, length_including_newline);
parser->encoding_comment_start = newline + 1;
}
if (options != NULL && options->shebang_callback != NULL) {
pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) cursor)));
}
break;
}
}

Просмотреть файл

@ -321,6 +321,44 @@ module Prism
assert_warning("tap { redo; foo }", "statement not reached")
end
def test_shebang_ending_with_carriage_return
msg = "shebang line ending with \\r may cause problems"
assert_warning(<<~RUBY, msg, compare: false)
#!ruby\r
p(123)
RUBY
assert_warning(<<~RUBY, msg, compare: false)
#!ruby \r
p(123)
RUBY
assert_warning(<<~RUBY, msg, compare: false)
#!ruby -Eutf-8\r
p(123)
RUBY
# Used with the `-x` object, to ignore the script up until the first shebang that mentioned "ruby".
assert_warning(<<~SCRIPT, msg, compare: false)
#!/usr/bin/env bash
# Some initial shell script or other content
# that Ruby should ignore
echo "This is shell script part"
exit 0
#! /usr/bin/env ruby -Eutf-8\r
# Ruby script starts here
puts "Hello from Ruby!"
SCRIPT
refute_warning("#ruby not_a_shebang\r\n", compare: false)
# CRuby doesn't emit the warning if a malformed file only has `\r` and not `\n`.
# https://bugs.ruby-lang.org/issues/20700
refute_warning("#!ruby\r", compare: false)
end
def test_warnings_verbosity
warning = Prism.parse("def foo; END { }; end").warnings.first
assert_equal "END in method; use at_exit", warning.message
@ -333,7 +371,7 @@ module Prism
private
def assert_warning(source, *messages)
def assert_warning(source, *messages, compare: true)
warnings = Prism.parse(source).warnings
assert_equal messages.length, warnings.length, "Expected #{messages.length} warning(s) in #{source.inspect}, got #{warnings.map(&:message).inspect}"
@ -341,7 +379,7 @@ module Prism
assert_include warning.message, message
end
if defined?(RubyVM::AbstractSyntaxTree)
if compare && defined?(RubyVM::AbstractSyntaxTree)
stderr = capture_stderr { RubyVM::AbstractSyntaxTree.parse(source) }
messages.each { |message| assert_include stderr, message }
end