This commit is contained in:
Jemma Issroff 2023-07-12 12:46:38 -04:00 коммит произвёл GitHub
Родитель 47cb789332
Коммит a02f5eb56a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 140 добавлений и 25 удалений

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

@ -4427,7 +4427,7 @@ module YARP
end
end
# Represents a parentesized expression
# Represents a parenthesized expression
#
# (10 + 34)
# ^^^^^^^^^

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

@ -426,9 +426,14 @@ class ErrorsTest < Test::Unit::TestCase
expected = DefNode(
Location(),
nil,
ParametersNode([], [], [], nil, [], nil, nil),
ParametersNode([
RequiredParameterNode(:A),
RequiredParameterNode(:@a),
RequiredParameterNode(:$A),
RequiredParameterNode(:@@a),
], [], [], nil, [], nil, nil),
nil,
[],
[:A, :@a, :$A, :@@a],
Location(),
nil,
Location(),

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

@ -0,0 +1,101 @@
# frozen_string_literal: true
require "yarp_test_helper"
if RUBY_PLATFORM =~ /linux/
#
# examine a yarp dll or static archive for expected external symbols.
# these tests only work on a linux system right now.
#
class LibrarySymbolsTest < Test::Unit::TestCase
def setup
super
@librubyparser_a = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.a"))
@librubyparser_so = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.so"))
@yarp_so = File.expand_path(File.join(__dir__, "..", "lib", "yarp.so"))
end
# objdump runner and helpers
def objdump(path)
assert_path_exist(path)
%x(objdump --section=.text --syms #{path}).split("\n")
end
def global_objdump_symbols(path)
objdump(path).select { |line| line[17] == "g" }
end
def hidden_global_objdump_symbols(path)
global_objdump_symbols(path).select { |line| line =~ / \.hidden / }
end
def visible_global_objdump_symbols(path)
global_objdump_symbols(path).reject { |line| line =~ / \.hidden / }
end
# nm runner and helpers
def nm(path)
assert_path_exist(path)
%x(nm #{path}).split("\n")
end
def global_nm_symbols(path)
nm(path).select { |line| line[17] == "T" }
end
def local_nm_symbols(path)
nm(path).select { |line| line[17] == "t" }
end
# dig the symbol name out of each line. works for both `objdump` and `nm` output.
def names(symbol_lines)
symbol_lines.map { |line| line.split(/\s+/).last }
end
#
# static archive - librubyparser.a
#
def test_librubyparser_a_contains_nothing_globally_visible
omit("librubyparser.a is not built") unless File.exist?(@librubyparser_a)
assert_empty(names(visible_global_objdump_symbols(@librubyparser_a)))
end
def test_librubyparser_a_contains_hidden_yp_symbols
omit("librubyparser.a is not built") unless File.exist?(@librubyparser_a)
names(hidden_global_objdump_symbols(@librubyparser_a)).tap do |symbols|
assert_includes(symbols, "yp_parse")
assert_includes(symbols, "yp_version")
end
end
#
# shared object - librubyparser.so
#
def test_librubyparser_so_exports_only_the_necessary_functions
omit("librubyparser.so is not built") unless File.exist?(@librubyparser_so)
names(global_nm_symbols(@librubyparser_so)).tap do |symbols|
assert_includes(symbols, "yp_parse")
assert_includes(symbols, "yp_version")
end
names(local_nm_symbols(@librubyparser_so)).tap do |symbols|
assert_includes(symbols, "yp_encoding_shift_jis_isupper_char")
end
# TODO: someone who uses this library needs to finish this test
end
#
# shared object - yarp.so
#
def test_yarp_so_exports_only_the_C_extension_init_function
omit("yarp.so is not built") unless File.exist?(@yarp_so)
names(global_nm_symbols(@yarp_so)).tap do |symbols|
assert_equal(["Init_yarp"], symbols)
end
end
end
end

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

@ -12,11 +12,9 @@
#include <string.h>
// YP_EXPORTED_FUNCTION
#if defined(YP_STATIC)
# define YP_EXPORTED_FUNCTION
#elif defined(_WIN32)
#if defined(_WIN32)
# define YP_EXPORTED_FUNCTION __declspec(dllexport) extern
#else
#elif defined(YP_EXPORT_SYMBOLS)
# ifndef YP_EXPORTED_FUNCTION
# ifndef RUBY_FUNC_EXPORTED
# define YP_EXPORTED_FUNCTION __attribute__((__visibility__("default"))) extern
@ -24,6 +22,8 @@
# define YP_EXPORTED_FUNCTION RUBY_FUNC_EXPORTED
# endif
# endif
#else
# define YP_EXPORTED_FUNCTION
#endif
// YP_ATTRIBUTE_UNUSED

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

@ -3412,7 +3412,6 @@ yp_required_destructured_parameter_node_closing_set(yp_required_destructured_par
// Allocate a new RequiredParameterNode node.
static yp_required_parameter_node_t *
yp_required_parameter_node_create(yp_parser_t *parser, const yp_token_t *token) {
assert(token->type == YP_TOKEN_MISSING || token->type == YP_TOKEN_IDENTIFIER);
yp_required_parameter_node_t *node = YP_ALLOC_NODE(parser, yp_required_parameter_node_t);
*node = (yp_required_parameter_node_t) {
@ -8244,8 +8243,27 @@ parse_parameters(
}
break;
}
case YP_TOKEN_IDENTIFIER: {
case YP_TOKEN_CLASS_VARIABLE:
case YP_TOKEN_IDENTIFIER:
case YP_TOKEN_CONSTANT:
case YP_TOKEN_INSTANCE_VARIABLE:
case YP_TOKEN_GLOBAL_VARIABLE: {
parser_lex(parser);
switch (parser->previous.type) {
case YP_TOKEN_CONSTANT:
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a constant");
break;
case YP_TOKEN_INSTANCE_VARIABLE:
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be an instance variable");
break;
case YP_TOKEN_GLOBAL_VARIABLE:
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a global variable");
break;
case YP_TOKEN_CLASS_VARIABLE:
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a class variable");
break;
default: break;
}
if (parser->current.type == YP_TOKEN_EQUAL) {
update_parameter_state(parser, &parser->current, &order);
@ -8387,22 +8405,6 @@ parse_parameters(
yp_parameters_node_keyword_rest_set(params, param);
break;
}
case YP_TOKEN_CONSTANT:
parser_lex(parser);
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a constant");
break;
case YP_TOKEN_INSTANCE_VARIABLE:
parser_lex(parser);
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be an instance variable");
break;
case YP_TOKEN_GLOBAL_VARIABLE:
parser_lex(parser);
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a global variable");
break;
case YP_TOKEN_CLASS_VARIABLE:
parser_lex(parser);
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a class variable");
break;
default:
if (parser->previous.type == YP_TOKEN_COMMA) {
if (allows_trailing_comma) {
@ -8427,6 +8429,13 @@ parse_parameters(
} while (looping && accept(parser, YP_TOKEN_COMMA));
yp_do_loop_stack_pop(parser);
// If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`.
if (params->base.location.start == params->base.location.end) {
yp_node_destroy(parser, (yp_node_t *) params);
return NULL;
}
return params;
}