From a60573383784d331a6c1ed9f77aea06cc6ec881a Mon Sep 17 00:00:00 2001 From: yehonatanz Date: Sat, 27 Jan 2024 17:55:01 +0200 Subject: [PATCH] Support optional fields using IDL question mark syntax (#446) --- lib/specs.js | 4 ++++ test/test_specs.js | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/lib/specs.js b/lib/specs.js index 88c75189..07321ad9 100644 --- a/lib/specs.js +++ b/lib/specs.js @@ -427,11 +427,15 @@ class Reader { if (javadoc !== undefined && schema.doc === undefined) { schema.doc = javadoc; } + const isOptional = tk.next({id: 'operator', val: '?', silent: true}); this._readAnnotations(schema); schema.name = tk.next({id: 'name'}).val; if (tk.next({val: '=', silent: true})) { schema['default'] = tk.next({id: 'json'}).val; } + if (isOptional) { + schema.type = 'default' in schema && schema.default !== null ? [schema.type, 'null'] : ['null', schema.type]; + } return schema; } diff --git a/test/test_specs.js b/test/test_specs.js index 1ee95708..2895f2ee 100644 --- a/test/test_specs.js +++ b/test/test_specs.js @@ -737,6 +737,30 @@ suite('specs', () => { ); }); + test('optional field no default value', () => { + const usingQuestionMark = readSchema('record { int? optionalInt; }'); + const usingUnion = readSchema('record { union{null,int} optionalInt; }'); + assert.deepEqual(usingQuestionMark, usingUnion); + }); + + test('optional field null default value', () => { + const usingQuestionMark = readSchema('record { int? optionalInt = null; }'); + const usingUnion = readSchema('record { union{null,int} optionalInt = null; }'); + assert.deepEqual(usingQuestionMark, usingUnion); + }); + + test('optional field non-null default value', () => { + const usingQuestionMark = readSchema('record { int? optionalInt = 0; }'); + const usingUnion = readSchema('record { union{int,null} optionalInt = 0; }'); + assert.deepEqual(usingQuestionMark, usingUnion); + }); + + test('optional field with annotations', () => { + const usingQuestionMark = readSchema('record { int? @order("ascending") optionalInt = 0; }'); + const usingUnion = readSchema('record { union{int,null} @order("ascending") optionalInt = 0; }'); + assert.deepEqual(usingQuestionMark, usingUnion); + }); + }); suite('readProtocol', () => {