Skip to content

Commit a02f5eb

Browse files
authored
YARP resync (#8059)
1 parent 47cb789 commit a02f5eb

File tree

5 files changed

+141
-26
lines changed

5 files changed

+141
-26
lines changed

lib/yarp/node.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4427,7 +4427,7 @@ def deconstruct_keys(keys)
44274427
end
44284428
end
44294429

4430-
# Represents a parentesized expression
4430+
# Represents a parenthesized expression
44314431
#
44324432
# (10 + 34)
44334433
# ^^^^^^^^^

test/yarp/errors_test.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,9 +426,14 @@ def test_bad_arguments
426426
expected = DefNode(
427427
Location(),
428428
nil,
429-
ParametersNode([], [], [], nil, [], nil, nil),
430-
nil,
431-
[],
429+
ParametersNode([
430+
RequiredParameterNode(:A),
431+
RequiredParameterNode(:@a),
432+
RequiredParameterNode(:$A),
433+
RequiredParameterNode(:@@a),
434+
], [], [], nil, [], nil, nil),
435+
nil,
436+
[:A, :@a, :$A, :@@a],
432437
Location(),
433438
nil,
434439
Location(),

test/yarp/library_symbols_test.rb

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# frozen_string_literal: true
2+
3+
require "yarp_test_helper"
4+
5+
if RUBY_PLATFORM =~ /linux/
6+
#
7+
# examine a yarp dll or static archive for expected external symbols.
8+
# these tests only work on a linux system right now.
9+
#
10+
class LibrarySymbolsTest < Test::Unit::TestCase
11+
def setup
12+
super
13+
14+
@librubyparser_a = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.a"))
15+
@librubyparser_so = File.expand_path(File.join(__dir__, "..", "build", "librubyparser.so"))
16+
@yarp_so = File.expand_path(File.join(__dir__, "..", "lib", "yarp.so"))
17+
end
18+
19+
# objdump runner and helpers
20+
def objdump(path)
21+
assert_path_exist(path)
22+
%x(objdump --section=.text --syms #{path}).split("\n")
23+
end
24+
25+
def global_objdump_symbols(path)
26+
objdump(path).select { |line| line[17] == "g" }
27+
end
28+
29+
def hidden_global_objdump_symbols(path)
30+
global_objdump_symbols(path).select { |line| line =~ / \.hidden / }
31+
end
32+
33+
def visible_global_objdump_symbols(path)
34+
global_objdump_symbols(path).reject { |line| line =~ / \.hidden / }
35+
end
36+
37+
# nm runner and helpers
38+
def nm(path)
39+
assert_path_exist(path)
40+
%x(nm #{path}).split("\n")
41+
end
42+
43+
def global_nm_symbols(path)
44+
nm(path).select { |line| line[17] == "T" }
45+
end
46+
47+
def local_nm_symbols(path)
48+
nm(path).select { |line| line[17] == "t" }
49+
end
50+
51+
# dig the symbol name out of each line. works for both `objdump` and `nm` output.
52+
def names(symbol_lines)
53+
symbol_lines.map { |line| line.split(/\s+/).last }
54+
end
55+
56+
#
57+
# static archive - librubyparser.a
58+
#
59+
def test_librubyparser_a_contains_nothing_globally_visible
60+
omit("librubyparser.a is not built") unless File.exist?(@librubyparser_a)
61+
62+
assert_empty(names(visible_global_objdump_symbols(@librubyparser_a)))
63+
end
64+
65+
def test_librubyparser_a_contains_hidden_yp_symbols
66+
omit("librubyparser.a is not built") unless File.exist?(@librubyparser_a)
67+
68+
names(hidden_global_objdump_symbols(@librubyparser_a)).tap do |symbols|
69+
assert_includes(symbols, "yp_parse")
70+
assert_includes(symbols, "yp_version")
71+
end
72+
end
73+
74+
#
75+
# shared object - librubyparser.so
76+
#
77+
def test_librubyparser_so_exports_only_the_necessary_functions
78+
omit("librubyparser.so is not built") unless File.exist?(@librubyparser_so)
79+
80+
names(global_nm_symbols(@librubyparser_so)).tap do |symbols|
81+
assert_includes(symbols, "yp_parse")
82+
assert_includes(symbols, "yp_version")
83+
end
84+
names(local_nm_symbols(@librubyparser_so)).tap do |symbols|
85+
assert_includes(symbols, "yp_encoding_shift_jis_isupper_char")
86+
end
87+
# TODO: someone who uses this library needs to finish this test
88+
end
89+
90+
#
91+
# shared object - yarp.so
92+
#
93+
def test_yarp_so_exports_only_the_C_extension_init_function
94+
omit("yarp.so is not built") unless File.exist?(@yarp_so)
95+
96+
names(global_nm_symbols(@yarp_so)).tap do |symbols|
97+
assert_equal(["Init_yarp"], symbols)
98+
end
99+
end
100+
end
101+
end

yarp/defines.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@
1212
#include <string.h>
1313

1414
// YP_EXPORTED_FUNCTION
15-
#if defined(YP_STATIC)
16-
# define YP_EXPORTED_FUNCTION
17-
#elif defined(_WIN32)
15+
#if defined(_WIN32)
1816
# define YP_EXPORTED_FUNCTION __declspec(dllexport) extern
19-
#else
17+
#elif defined(YP_EXPORT_SYMBOLS)
2018
# ifndef YP_EXPORTED_FUNCTION
2119
# ifndef RUBY_FUNC_EXPORTED
2220
# define YP_EXPORTED_FUNCTION __attribute__((__visibility__("default"))) extern
2321
# else
2422
# define YP_EXPORTED_FUNCTION RUBY_FUNC_EXPORTED
2523
# endif
2624
# endif
25+
#else
26+
# define YP_EXPORTED_FUNCTION
2727
#endif
2828

2929
// YP_ATTRIBUTE_UNUSED

yarp/yarp.c

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3412,7 +3412,6 @@ yp_required_destructured_parameter_node_closing_set(yp_required_destructured_par
34123412
// Allocate a new RequiredParameterNode node.
34133413
static yp_required_parameter_node_t *
34143414
yp_required_parameter_node_create(yp_parser_t *parser, const yp_token_t *token) {
3415-
assert(token->type == YP_TOKEN_MISSING || token->type == YP_TOKEN_IDENTIFIER);
34163415
yp_required_parameter_node_t *node = YP_ALLOC_NODE(parser, yp_required_parameter_node_t);
34173416

34183417
*node = (yp_required_parameter_node_t) {
@@ -8244,8 +8243,27 @@ parse_parameters(
82448243
}
82458244
break;
82468245
}
8247-
case YP_TOKEN_IDENTIFIER: {
8246+
case YP_TOKEN_CLASS_VARIABLE:
8247+
case YP_TOKEN_IDENTIFIER:
8248+
case YP_TOKEN_CONSTANT:
8249+
case YP_TOKEN_INSTANCE_VARIABLE:
8250+
case YP_TOKEN_GLOBAL_VARIABLE: {
82488251
parser_lex(parser);
8252+
switch (parser->previous.type) {
8253+
case YP_TOKEN_CONSTANT:
8254+
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a constant");
8255+
break;
8256+
case YP_TOKEN_INSTANCE_VARIABLE:
8257+
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be an instance variable");
8258+
break;
8259+
case YP_TOKEN_GLOBAL_VARIABLE:
8260+
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a global variable");
8261+
break;
8262+
case YP_TOKEN_CLASS_VARIABLE:
8263+
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a class variable");
8264+
break;
8265+
default: break;
8266+
}
82498267

82508268
if (parser->current.type == YP_TOKEN_EQUAL) {
82518269
update_parameter_state(parser, &parser->current, &order);
@@ -8387,22 +8405,6 @@ parse_parameters(
83878405
yp_parameters_node_keyword_rest_set(params, param);
83888406
break;
83898407
}
8390-
case YP_TOKEN_CONSTANT:
8391-
parser_lex(parser);
8392-
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a constant");
8393-
break;
8394-
case YP_TOKEN_INSTANCE_VARIABLE:
8395-
parser_lex(parser);
8396-
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be an instance variable");
8397-
break;
8398-
case YP_TOKEN_GLOBAL_VARIABLE:
8399-
parser_lex(parser);
8400-
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a global variable");
8401-
break;
8402-
case YP_TOKEN_CLASS_VARIABLE:
8403-
parser_lex(parser);
8404-
yp_diagnostic_list_append(&parser->error_list, parser->previous.start, parser->previous.end, "Formal argument cannot be a class variable");
8405-
break;
84068408
default:
84078409
if (parser->previous.type == YP_TOKEN_COMMA) {
84088410
if (allows_trailing_comma) {
@@ -8427,6 +8429,13 @@ parse_parameters(
84278429
} while (looping && accept(parser, YP_TOKEN_COMMA));
84288430

84298431
yp_do_loop_stack_pop(parser);
8432+
8433+
// If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`.
8434+
if (params->base.location.start == params->base.location.end) {
8435+
yp_node_destroy(parser, (yp_node_t *) params);
8436+
return NULL;
8437+
}
8438+
84308439
return params;
84318440
}
84328441

0 commit comments

Comments
 (0)