Skip to content

Commit

Permalink
feat: valuesOptions for enums (#1358)
Browse files Browse the repository at this point in the history
* 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 <fenster@google.com>
Co-authored-by: Alexander Fenster <github@fenster.name>
  • Loading branch information
3 people committed Aug 17, 2022
1 parent d7f501c commit bb6b1d4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
31 changes: 24 additions & 7 deletions src/enum.js
Expand Up @@ -18,8 +18,9 @@ var Namespace = require("./namespace"),
* @param {Object.<string,*>} [options] Declared options
* @param {string} [comment] The comment for this enum
* @param {Object.<string,string>} [comments] The value comments for this enum
* @param {Object.<string,Object<string,*>>|undefined} [valuesOptions] The value options for this enum
*/
function Enum(name, values, options, comment, comments) {
function Enum(name, values, options, comment, comments, valuesOptions) {
ReflectionObject.call(this, name, options);

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

/**
* Values options, if any
* @type {Object<string, Object<string, *>>|undefined}
*/
this.valuesOptions = valuesOptions;

/**
* Reserved ranges, if any.
* @type {Array.<number[]|string>}
Expand Down Expand Up @@ -93,11 +100,12 @@ Enum.fromJSON = function fromJSON(name, json) {
Enum.prototype.toJSON = function toJSON(toJSONOptions) {
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
return util.toObject([
"options" , this.options,
"values" , this.values,
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
"comment" , keepComments ? this.comment : undefined,
"comments" , keepComments ? this.comments : undefined
"options" , this.options,
"valuesOptions" , this.valuesOptions,
"values" , this.values,
"reserved" , this.reserved && this.reserved.length ? this.reserved : undefined,
"comment" , keepComments ? this.comment : undefined,
"comments" , keepComments ? this.comments : undefined
]);
};

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

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

if (options) {
if (this.valuesOptions === undefined)
this.valuesOptions = {};
this.valuesOptions[name] = options || null;
}

this.comments[name] = comment || null;
return this;
};
Expand All @@ -158,6 +173,8 @@ Enum.prototype.remove = function remove(name) {
delete this.valuesById[val];
delete this.values[name];
delete this.comments[name];
if (this.valuesOptions)
delete this.valuesOptions[name];

return this;
};
Expand Down
11 changes: 9 additions & 2 deletions src/parse.js
Expand Up @@ -543,7 +543,14 @@ function parse(source, root, options) {

skip("=");
var value = parseId(next(), true),
dummy = {};
dummy = {
options: undefined
};
dummy.setOption = function(name, value) {
if (this.options === undefined)
this.options = {};
this.options[name] = value;
};
ifBlock(dummy, function parseEnumValue_block(token) {

/* istanbul ignore else */
Expand All @@ -556,7 +563,7 @@ function parse(source, root, options) {
}, function parseEnumValue_line() {
parseInlineOptions(dummy); // skip
});
parent.add(token, value, dummy.comment);
parent.add(token, value, dummy.comment, dummy.options);
}

function parseOption(parent, token) {
Expand Down
7 changes: 7 additions & 0 deletions tests/api_enum.js
Expand Up @@ -80,5 +80,12 @@ tape.test("reflected enums", function(test) {
b: 0
});

enm.add('e', 4, undefined, {'(test_option)': 'test_value'});
test.same( enm.valuesOptions, {
'e': {
'(test_option)': 'test_value'
}
});

test.end();
});
8 changes: 8 additions & 0 deletions tests/comp_options-textformat.js
Expand Up @@ -11,19 +11,27 @@ message MyOptions {\
extend google.protobuf.FieldOptions {\
MyOptions my_options = 50000;\
}\
extend google.protobuf.EnumValueOptions {\
MyOptions my_value_option = 50001;\
}\
message Test {\
string value = 1 [(my_options) = { a: \"foo\" b: \"bar\" }];\
string value2 = 2 [(my_options) = { a: \"foo\" b { c: \"bar\" } }];\
string value3 = 3 [(my_options) = { a: \"foo\", b: \"bar\" }];\
string value4 = 4 [(my_options) = { a: \"foo\"; b: \"bar\" }];\
}\
enum TestEnum {\
TEST_ITEM = 0 [(my_value_option) = { a: \"foo\", b: \"bar\" }];\
}";

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

0 comments on commit bb6b1d4

Please sign in to comment.