Skip to content

Commit bb6b1d4

Browse files
feat: valuesOptions for enums (#1358)
* enum valuesOptions support * update tests a little, fix api docs * tests: reverting bad conflict resolution * test: put test.end() in its proper place Co-authored-by: Alexander Fenster <[email protected]> Co-authored-by: Alexander Fenster <[email protected]>
1 parent d7f501c commit bb6b1d4

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

src/enum.js

+24-7
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ var Namespace = require("./namespace"),
1818
* @param {Object.<string,*>} [options] Declared options
1919
* @param {string} [comment] The comment for this enum
2020
* @param {Object.<string,string>} [comments] The value comments for this enum
21+
* @param {Object.<string,Object<string,*>>|undefined} [valuesOptions] The value options for this enum
2122
*/
22-
function Enum(name, values, options, comment, comments) {
23+
function Enum(name, values, options, comment, comments, valuesOptions) {
2324
ReflectionObject.call(this, name, options);
2425

2526
if (values && typeof values !== "object")
@@ -49,6 +50,12 @@ function Enum(name, values, options, comment, comments) {
4950
*/
5051
this.comments = comments || {};
5152

53+
/**
54+
* Values options, if any
55+
* @type {Object<string, Object<string, *>>|undefined}
56+
*/
57+
this.valuesOptions = valuesOptions;
58+
5259
/**
5360
* Reserved ranges, if any.
5461
* @type {Array.<number[]|string>}
@@ -93,11 +100,12 @@ Enum.fromJSON = function fromJSON(name, json) {
93100
Enum.prototype.toJSON = function toJSON(toJSONOptions) {
94101
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
95102
return util.toObject([
96-
"options" , this.options,
97-
"values" , this.values,
98-
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
99-
"comment" , keepComments ? this.comment : undefined,
100-
"comments" , keepComments ? this.comments : undefined
103+
"options" , this.options,
104+
"valuesOptions" , this.valuesOptions,
105+
"values" , this.values,
106+
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
107+
"comment" , keepComments ? this.comment : undefined,
108+
"comments" , keepComments ? this.comments : undefined
101109
]);
102110
};
103111

@@ -106,11 +114,12 @@ Enum.prototype.toJSON = function toJSON(toJSONOptions) {
106114
* @param {string} name Value name
107115
* @param {number} id Value id
108116
* @param {string} [comment] Comment, if any
117+
* @param {Object.<string, *>|undefined} [options] Options, if any
109118
* @returns {Enum} `this`
110119
* @throws {TypeError} If arguments are invalid
111120
* @throws {Error} If there is already a value with this name or id
112121
*/
113-
Enum.prototype.add = function add(name, id, comment) {
122+
Enum.prototype.add = function add(name, id, comment, options) {
114123
// utilized by the parser but not by .fromJSON
115124

116125
if (!util.isString(name))
@@ -135,6 +144,12 @@ Enum.prototype.add = function add(name, id, comment) {
135144
} else
136145
this.valuesById[this.values[name] = id] = name;
137146

147+
if (options) {
148+
if (this.valuesOptions === undefined)
149+
this.valuesOptions = {};
150+
this.valuesOptions[name] = options || null;
151+
}
152+
138153
this.comments[name] = comment || null;
139154
return this;
140155
};
@@ -158,6 +173,8 @@ Enum.prototype.remove = function remove(name) {
158173
delete this.valuesById[val];
159174
delete this.values[name];
160175
delete this.comments[name];
176+
if (this.valuesOptions)
177+
delete this.valuesOptions[name];
161178

162179
return this;
163180
};

src/parse.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,14 @@ function parse(source, root, options) {
543543

544544
skip("=");
545545
var value = parseId(next(), true),
546-
dummy = {};
546+
dummy = {
547+
options: undefined
548+
};
549+
dummy.setOption = function(name, value) {
550+
if (this.options === undefined)
551+
this.options = {};
552+
this.options[name] = value;
553+
};
547554
ifBlock(dummy, function parseEnumValue_block(token) {
548555

549556
/* istanbul ignore else */
@@ -556,7 +563,7 @@ function parse(source, root, options) {
556563
}, function parseEnumValue_line() {
557564
parseInlineOptions(dummy); // skip
558565
});
559-
parent.add(token, value, dummy.comment);
566+
parent.add(token, value, dummy.comment, dummy.options);
560567
}
561568

562569
function parseOption(parent, token) {

tests/api_enum.js

+7
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,12 @@ tape.test("reflected enums", function(test) {
8080
b: 0
8181
});
8282

83+
enm.add('e', 4, undefined, {'(test_option)': 'test_value'});
84+
test.same( enm.valuesOptions, {
85+
'e': {
86+
'(test_option)': 'test_value'
87+
}
88+
});
89+
8390
test.end();
8491
});

tests/comp_options-textformat.js

+8
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,27 @@ message MyOptions {\
1111
extend google.protobuf.FieldOptions {\
1212
MyOptions my_options = 50000;\
1313
}\
14+
extend google.protobuf.EnumValueOptions {\
15+
MyOptions my_value_option = 50001;\
16+
}\
1417
message Test {\
1518
string value = 1 [(my_options) = { a: \"foo\" b: \"bar\" }];\
1619
string value2 = 2 [(my_options) = { a: \"foo\" b { c: \"bar\" } }];\
1720
string value3 = 3 [(my_options) = { a: \"foo\", b: \"bar\" }];\
1821
string value4 = 4 [(my_options) = { a: \"foo\"; b: \"bar\" }];\
22+
}\
23+
enum TestEnum {\
24+
TEST_ITEM = 0 [(my_value_option) = { a: \"foo\", b: \"bar\" }];\
1925
}";
2026

2127
tape.test("options in textformat", function(test) {
2228
var root = protobuf.parse(proto).root;
2329
var Test = root.lookup("Test");
30+
var TestEnum = root.lookup("TestEnum");
2431
test.same(Test.fields.value.options, { "(my_options).a": "foo", "(my_options).b": "bar" }, "should parse correctly");
2532
test.same(Test.fields.value2.options, { "(my_options).a": "foo", "(my_options).b.c": "bar" }, "should parse correctly when nested");
2633
test.same(Test.fields.value3.options, { "(my_options).a": "foo", "(my_options).b": "bar" }, "should parse correctly when comma-separated");
2734
test.same(Test.fields.value4.options, { "(my_options).a": "foo", "(my_options).b": "bar" }, "should parse correctly when semicolon-separated");
35+
test.same(TestEnum.valuesOptions["TEST_ITEM"], { "(my_value_option).a": "foo", "(my_value_option).b": "bar" }, "should parse correctly in enum");
2836
test.end();
2937
});

0 commit comments

Comments
 (0)