Переглянути джерело

Add no-lonely-if lint rule

Lutz Roeder 3 роки тому
батько
коміт
d69aeac388
10 змінених файлів з 277 додано та 308 видалено
  1. 1 0
      package.json
  2. 2 4
      source/coreml.js
  3. 38 40
      source/onnx.js
  4. 10 14
      source/protobuf.js
  5. 2 4
      source/python.js
  6. 91 93
      source/pytorch.js
  7. 72 76
      source/tf.js
  8. 4 8
      source/xml.js
  9. 49 57
      tools/flatc.js
  10. 8 12
      tools/protoc.js

+ 1 - 0
package.json

@@ -54,6 +54,7 @@
             "no-iterator": "error",
             "no-labels": "error",
             "no-lone-blocks": "error",
+            "no-lonely-if": "error",
             "no-promise-executor-return": "error",
             "no-self-compare": "error",
             "no-template-curly-in-string": "error",

+ 2 - 4
source/coreml.js

@@ -1644,10 +1644,8 @@ coreml.Metadata = class {
                     }
                 }
             }
-            else {
-                if (index == 0) {
-                    name = 'input';
-                }
+            else if (index == 0) {
+                name = 'input';
             }
             result.name = name ? name : '(' + index.toString() + ')';
             const array = inputs.slice(index, index + count);

+ 38 - 40
source/onnx.js

@@ -2111,51 +2111,49 @@ onnx.Text.Reader = class {
                 this._throw("Unexpected value '" + JSON.stringify(list) + "'.");
             }
         }
-        else {
-            if ((this._char >= 'a' && this._char <= 'z') || (this._char >= 'A' && this._char <= 'Z') || this._char === '_') {
-                const identifier = this._identifier();
-                if (this._dataTypes.has(identifier)) {
-                    attribute.type = onnx.AttributeType.TENSOR;
-                    if (!this._dataTypes.has(identifier)) {
-                        this._throw("Unexpected type '" + identifier + "'.");
-                    }
-                    const type = this._type(this._dataTypes.get(identifier));
-                    if (!type.tensor_type.elem_type) {
-                        this._throw('Expected tensor data type.');
-                    }
-                    if (!type.tensor_type.shape || !type.tensor_type.shape.dim) {
-                        this._throw('Expected tensor shape.');
-                    }
-                    attribute.t = this._tensor(type);
+        else if ((this._char >= 'a' && this._char <= 'z') || (this._char >= 'A' && this._char <= 'Z') || this._char === '_') {
+            const identifier = this._identifier();
+            if (this._dataTypes.has(identifier)) {
+                attribute.type = onnx.AttributeType.TENSOR;
+                if (!this._dataTypes.has(identifier)) {
+                    this._throw("Unexpected type '" + identifier + "'.");
                 }
-                else {
-                    attribute.type = onnx.AttributeType.GRAPH;
-                    attribute.g = this._graph();
+                const type = this._type(this._dataTypes.get(identifier));
+                if (!type.tensor_type.elem_type) {
+                    this._throw('Expected tensor data type.');
                 }
-            }
-            else if (this._match('@')) {
-                attribute.ref_attr_name = this._identifier();
+                if (!type.tensor_type.shape || !type.tensor_type.shape.dim) {
+                    this._throw('Expected tensor shape.');
+                }
+                attribute.t = this._tensor(type);
             }
             else {
-                const value = this._literal();
-                switch (typeof value) {
-                    case 'number':
-                        if (Number.isInteger(value)) {
-                            attribute.type = onnx.AttributeType.INT;
-                            attribute.i = value;
-                        }
-                        else {
-                            attribute.type = onnx.AttributeType.FLOAT;
-                            attribute.f = value;
-                        }
-                        break;
-                    case 'string':
-                        attribute.type = onnx.AttributeType.STRING;
-                        attribute.s = value;
-                        break;
-                    default: {
-                        this._throw("Unexpected value '" + JSON.stringify(value) + "'.");
+                attribute.type = onnx.AttributeType.GRAPH;
+                attribute.g = this._graph();
+            }
+        }
+        else if (this._match('@')) {
+            attribute.ref_attr_name = this._identifier();
+        }
+        else {
+            const value = this._literal();
+            switch (typeof value) {
+                case 'number':
+                    if (Number.isInteger(value)) {
+                        attribute.type = onnx.AttributeType.INT;
+                        attribute.i = value;
                     }
+                    else {
+                        attribute.type = onnx.AttributeType.FLOAT;
+                        attribute.f = value;
+                    }
+                    break;
+                case 'string':
+                    attribute.type = onnx.AttributeType.STRING;
+                    attribute.s = value;
+                    break;
+                default: {
+                    this._throw("Unexpected value '" + JSON.stringify(value) + "'.");
                 }
             }
         }

+ 10 - 14
source/protobuf.js

@@ -342,14 +342,12 @@ protobuf.BinaryReader = class {
             }
             this._position = end;
         }
+        else if (obj !== undefined && obj.length < 1000000) {
+            obj.push(this.float());
+        }
         else {
-            if (obj !== undefined && obj.length < 1000000) {
-                obj.push(this.float());
-            }
-            else {
-                obj = undefined;
-                this.float();
-            }
+            obj = undefined;
+            this.float();
         }
         return obj;
     }
@@ -373,14 +371,12 @@ protobuf.BinaryReader = class {
             }
             this._position = end;
         }
+        else if (obj !== undefined && obj.length < 1000000) {
+            obj.push(this.double());
+        }
         else {
-            if (obj !== undefined && obj.length < 1000000) {
-                obj.push(this.double());
-            }
-            else {
-                obj = undefined;
-                this.double();
-            }
+            obj = undefined;
+            this.double();
         }
         return obj;
     }

+ 2 - 4
source/python.js

@@ -2061,10 +2061,8 @@ python.Execution = class {
                         throw new python.Error('Invalid string array data size.');
                     }
                 }
-                else {
-                    if (this.data.length != size) {
-                        // throw new pytorch.Error('Invalid array data size.');
-                    }
+                else if (this.data.length != size) {
+                    // throw new pytorch.Error('Invalid array data size.');
                 }
                 return this;
             }

+ 91 - 93
source/pytorch.js

@@ -2560,107 +2560,105 @@ pytorch.Container.Zip = class {
                 const buffer = stream.peek();
                 this._data = this._unpickle(buffer, this._storage('data'));
             }
-            else {
-                if (this._model) {
-                    this._producer = this._model.producerName + (this._model.producerVersion ? ' v' + this._model.producerVersion : '');
-                    this._data = this._model.mainModule || {};
-                    this._name = this._data.name || '';
-                    if (this._data.torchscriptArena) {
-                        this._torchscriptArena = this._data.torchscriptArena.key;
+            else if (this._model) {
+                this._producer = this._model.producerName + (this._model.producerVersion ? ' v' + this._model.producerVersion : '');
+                this._data = this._model.mainModule || {};
+                this._name = this._data.name || '';
+                if (this._data.torchscriptArena) {
+                    this._torchscriptArena = this._data.torchscriptArena.key;
+                }
+                const queue = [ this._data ];
+                const entries = new Map();
+                for (const entry of this._entries) {
+                    const name = entry[0];
+                    const stream = entry[1];
+                    const buffer = stream.peek();
+                    entries.set(name, buffer);
+                }
+                const tensorTypeMap = new Map([
+                    [ 'FLOAT', 'Float' ],
+                    [ 'FLOAT16', 'Half' ],
+                    [ 'DOUBLE', 'Double' ],
+                    [ 'INT8', 'Char' ],
+                    [ 'INT32', 'Int' ],
+                    [ 'INT64', 'Long' ]
+                ]);
+                const constants = this._model.tensors || [];
+                this._constants = constants.map((constant) => {
+                    const key = this._prefix + constant.data.key;
+                    if (!tensorTypeMap.has(constant.dataType)) {
+                        throw new pytorch.Error("Unsupported tensor data type '" + constant.dataType + "'.");
                     }
-                    const queue = [ this._data ];
-                    const entries = new Map();
-                    for (const entry of this._entries) {
-                        const name = entry[0];
-                        const stream = entry[1];
-                        const buffer = stream.peek();
-                        entries.set(name, buffer);
+                    const type = tensorTypeMap.get(constant.dataType);
+                    const shape = constant.dims ? constant.dims.map((dim) => parseInt(dim, 10)) : null;
+                    const storage_type = this.execution.type('torch.' + type + 'Storage');
+                    const size = (shape || []).reduce((a, b) => a * b, 1);
+                    const offset = parseInt(constant.offset, 10) || 0;
+                    const storage = new storage_type([ size ]);
+                    const itemsize = storage.dtype.itemsize();
+                    const buffer = entries.get(key);
+                    const length = size * itemsize;
+                    const data = buffer.slice(offset, offset + length);
+                    storage._set_cdata(data);
+                    const tensor = this.execution.invoke('torch._utils._rebuild_tensor', [ storage, 0, shape, 0 ]);
+                    tensor.name = constant.data.key;
+                    return tensor;
+                });
+                this._attributes = [];
+                const stream = this._entry('attributes.pkl');
+                if (stream) {
+                    const buffer = stream.peek();
+                    const unpickler = python.Unpickler.open(buffer);
+                    this._attributes.push(...unpickler.load((name, args) => this.execution.invoke(name, args)));
+                }
+                while (queue.length > 0) {
+                    const module = queue.shift();
+                    if (!module.__class__) {
+                        module.__class__ = {
+                            __module__: 'torch.nn.modules.module',
+                            __name__: 'Module'
+                        };
+                    }
+                    if (module.name) {
+                        module.__id__ = module.name;
                     }
-                    const tensorTypeMap = new Map([
-                        [ 'FLOAT', 'Float' ],
-                        [ 'FLOAT16', 'Half' ],
-                        [ 'DOUBLE', 'Double' ],
-                        [ 'INT8', 'Char' ],
-                        [ 'INT32', 'Int' ],
-                        [ 'INT64', 'Long' ]
-                    ]);
-                    const constants = this._model.tensors || [];
-                    this._constants = constants.map((constant) => {
-                        const key = this._prefix + constant.data.key;
-                        if (!tensorTypeMap.has(constant.dataType)) {
-                            throw new pytorch.Error("Unsupported tensor data type '" + constant.dataType + "'.");
+                    if (module.submodules) {
+                        for (const submodule of module.submodules) {
+                            module[submodule.name] = submodule;
+                            submodule.__parent__ = module;
+                            queue.push(submodule);
                         }
-                        const type = tensorTypeMap.get(constant.dataType);
-                        const shape = constant.dims ? constant.dims.map((dim) => parseInt(dim, 10)) : null;
-                        const storage_type = this.execution.type('torch.' + type + 'Storage');
-                        const size = (shape || []).reduce((a, b) => a * b, 1);
-                        const offset = parseInt(constant.offset, 10) || 0;
-                        const storage = new storage_type([ size ]);
-                        const itemsize = storage.dtype.itemsize();
-                        const buffer = entries.get(key);
-                        const length = size * itemsize;
-                        const data = buffer.slice(offset, offset + length);
-                        storage._set_cdata(data);
-                        const tensor = this.execution.invoke('torch._utils._rebuild_tensor', [ storage, 0, shape, 0 ]);
-                        tensor.name = constant.data.key;
-                        return tensor;
-                    });
-                    this._attributes = [];
-                    const stream = this._entry('attributes.pkl');
-                    if (stream) {
-                        const buffer = stream.peek();
-                        const unpickler = python.Unpickler.open(buffer);
-                        this._attributes.push(...unpickler.load((name, args) => this.execution.invoke(name, args)));
+                        delete module.submodules;
                     }
-                    while (queue.length > 0) {
-                        const module = queue.shift();
-                        if (!module.__class__) {
-                            module.__class__ = {
-                                __module__: 'torch.nn.modules.module',
-                                __name__: 'Module'
+                    const attributes = [];
+                    if (module.attributes) {
+                        attributes.push(...module.attributes);
+                        delete module.attributes;
+                    }
+                    const parameters = [];
+                    if (module.parameters) {
+                        parameters.push(...module.parameters);
+                        delete module.parameters;
+                    }
+                    if (module.arguments) {
+                        parameters.push(...module.arguments);
+                        delete module.arguments;
+                    }
+                    for (const parameter of parameters) {
+                        const tensor = this._constants[parameter.tensorId];
+                        module[parameter.name] = tensor;
+                        if (!parameter.__class__) {
+                            parameter.__class__ = {
+                                __module__: 'torch',
+                                __name__: 'Tensor'
                             };
                         }
-                        if (module.name) {
-                            module.__id__ = module.name;
-                        }
-                        if (module.submodules) {
-                            for (const submodule of module.submodules) {
-                                module[submodule.name] = submodule;
-                                submodule.__parent__ = module;
-                                queue.push(submodule);
-                            }
-                            delete module.submodules;
-                        }
-                        const attributes = [];
-                        if (module.attributes) {
-                            attributes.push(...module.attributes);
-                            delete module.attributes;
-                        }
-                        const parameters = [];
-                        if (module.parameters) {
-                            parameters.push(...module.parameters);
-                            delete module.parameters;
-                        }
-                        if (module.arguments) {
-                            parameters.push(...module.arguments);
-                            delete module.arguments;
-                        }
-                        for (const parameter of parameters) {
-                            const tensor = this._constants[parameter.tensorId];
-                            module[parameter.name] = tensor;
-                            if (!parameter.__class__) {
-                                parameter.__class__ = {
-                                    __module__: 'torch',
-                                    __name__: 'Tensor'
-                                };
-                            }
-                        }
-                        for (const attribute of attributes) {
-                            module[attribute.name] = this._attributes[attribute.id];
-                        }
                     }
-                    delete this._model;
+                    for (const attribute of attributes) {
+                        module[attribute.name] = this._attributes[attribute.id];
+                    }
                 }
+                delete this._model;
             }
             if (this.format.startsWith('TorchScript ') && (this._torchscriptArena || this._data.forward)) {
                 this._type = 'script';

+ 72 - 76
source/tf.js

@@ -1192,10 +1192,8 @@ tf.Attribute = class {
                         this._visible = false;
                     }
                 }
-                else {
-                    if (equals(value, defaultValue)) {
-                        this._visible = false;
-                    }
+                else if (equals(value, defaultValue)) {
+                    this._visible = false;
                 }
             }
         }
@@ -1443,78 +1441,76 @@ tf.Tensor = class {
                     results.push((this._tensor.dtype == tf.proto.tensorflow.DataType.DT_STRING) ? tf.Utility.decodeText(value) : value);
                     context.count++;
                 }
-                else {
-                    if (context.rawData) {
-                        switch (this._tensor.dtype) {
-                            case tf.proto.tensorflow.DataType.DT_HALF:
-                                results.push(context.rawData.getFloat16(context.index, true));
-                                context.index += 2;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_BFLOAT16:
-                            case tf.proto.tensorflow.DataType.DT_FLOAT:
-                                results.push(context.rawData.getFloat32(context.index, true));
-                                context.index += 4;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_DOUBLE:
-                                results.push(context.rawData.getFloat64(context.index, true));
-                                context.index += 8;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_INT8:
-                                results.push(context.rawData.getInt8(context.index));
-                                context.index += 1;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_UINT8:
-                                results.push(context.rawData.getUint8(context.index));
-                                context.index += 1;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_INT16:
-                                results.push(context.rawData.getInt16(context.index));
-                                context.index += 2;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_UINT16:
-                                results.push(context.rawData.getUint16(context.index));
-                                context.index += 2;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_INT32:
-                                results.push(context.rawData.getInt32(context.index, true));
-                                context.index += 4;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_UINT32:
-                                results.push(context.rawData.getUint32(context.index, true));
-                                context.index += 4;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_INT64:
-                                results.push(context.rawData.getInt64(context.index, true));
-                                context.index += 8;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_UINT64:
-                                results.push(context.rawData.getUint64(context.index, true));
-                                context.index += 8;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_QINT8:
-                                results.push(context.rawData.getInt8(context.index, true));
-                                context.index += 1;
-                                context.count++;
-                                break;
-                            case tf.proto.tensorflow.DataType.DT_QUINT8:
-                                results.push(context.rawData.getUint8(context.index, true));
-                                context.index += 1;
-                                context.count++;
-                                break;
-                            default:
-                                throw new tf.Error("Unsupported data type '" + this._tensor.dtype + "'.");
-                        }
+                else if (context.rawData) {
+                    switch (this._tensor.dtype) {
+                        case tf.proto.tensorflow.DataType.DT_HALF:
+                            results.push(context.rawData.getFloat16(context.index, true));
+                            context.index += 2;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_BFLOAT16:
+                        case tf.proto.tensorflow.DataType.DT_FLOAT:
+                            results.push(context.rawData.getFloat32(context.index, true));
+                            context.index += 4;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_DOUBLE:
+                            results.push(context.rawData.getFloat64(context.index, true));
+                            context.index += 8;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_INT8:
+                            results.push(context.rawData.getInt8(context.index));
+                            context.index += 1;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_UINT8:
+                            results.push(context.rawData.getUint8(context.index));
+                            context.index += 1;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_INT16:
+                            results.push(context.rawData.getInt16(context.index));
+                            context.index += 2;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_UINT16:
+                            results.push(context.rawData.getUint16(context.index));
+                            context.index += 2;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_INT32:
+                            results.push(context.rawData.getInt32(context.index, true));
+                            context.index += 4;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_UINT32:
+                            results.push(context.rawData.getUint32(context.index, true));
+                            context.index += 4;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_INT64:
+                            results.push(context.rawData.getInt64(context.index, true));
+                            context.index += 8;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_UINT64:
+                            results.push(context.rawData.getUint64(context.index, true));
+                            context.index += 8;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_QINT8:
+                            results.push(context.rawData.getInt8(context.index, true));
+                            context.index += 1;
+                            context.count++;
+                            break;
+                        case tf.proto.tensorflow.DataType.DT_QUINT8:
+                            results.push(context.rawData.getUint8(context.index, true));
+                            context.index += 1;
+                            context.count++;
+                            break;
+                        default:
+                            throw new tf.Error("Unsupported data type '" + this._tensor.dtype + "'.");
                     }
                 }
             }

+ 4 - 8
source/xml.js

@@ -204,10 +204,8 @@ xml.TextReader = class {
                                         namespaces.set(entry.localName, value);
                                     }
                                 }
-                                else {
-                                    if (entry.localName === 'xmlns') {
-                                        namespaces.set('', value);
-                                    }
+                                else if (entry.localName === 'xmlns') {
+                                    namespaces.set('', value);
                                 }
                             }
                             const pair = xml.Utility.split(name);
@@ -925,10 +923,8 @@ xml.TextReader = class {
                 this._pushString(entity.value, name, true);
             }
         }
-        else {
-            if (this._context.length !== 0 || !documentType || documentType.parameterEntities.length === 0) {
-                this._error("Undefined ENTITY '" + name + "'", position);
-            }
+        else if (this._context.length !== 0 || !documentType || documentType.parameterEntities.length === 0) {
+            this._error("Undefined ENTITY '" + name + "'", position);
         }
         return undefined;
     }

+ 49 - 57
tools/flatc.js

@@ -968,22 +968,20 @@ flatc.Generator = class {
                             this._builder.add('$.' + field.name + ' = reader.tableArray(position, ' + field.offset + ', ' + fieldType + '.decode);');
                         }
                     }
+                    else if (fieldType instanceof flatc.PrimitiveType) {
+                        this._builder.add('$.' + field.name + ' = reader.' + fieldType.name + '_(position, ' + field.offset + ', ' + field.defaultValue + ');');
+                    }
+                    else if (fieldType instanceof flatc.Union) {
+                        const unionType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                        this._builder.add('$.' + field.name + ' = reader.union(position, ' + field.offset + ', ' + unionType + '.decode);');
+                    }
+                    else if (fieldType instanceof flatc.Struct) {
+                        const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                        this._builder.add('$.' + field.name + ' = reader.struct(position, ' + field.offset + ', ' + fieldType + '.decode);');
+                    }
                     else {
-                        if (fieldType instanceof flatc.PrimitiveType) {
-                            this._builder.add('$.' + field.name + ' = reader.' + fieldType.name + '_(position, ' + field.offset + ', ' + field.defaultValue + ');');
-                        }
-                        else if (fieldType instanceof flatc.Union) {
-                            const unionType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                            this._builder.add('$.' + field.name + ' = reader.union(position, ' + field.offset + ', ' + unionType + '.decode);');
-                        }
-                        else if (fieldType instanceof flatc.Struct) {
-                            const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                            this._builder.add('$.' + field.name + ' = reader.struct(position, ' + field.offset + ', ' + fieldType + '.decode);');
-                        }
-                        else {
-                            const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                            this._builder.add('$.' + field.name + ' = reader.table(position, ' + field.offset + ', ' + fieldType + '.decode);');
-                        }
+                        const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                        this._builder.add('$.' + field.name + ' = reader.table(position, ' + field.offset + ', ' + fieldType + '.decode);');
                     }
                 }
                 this._builder.add('return $;');
@@ -1025,22 +1023,20 @@ flatc.Generator = class {
                                 this._builder.add('$.' + field.name + ' = reader.objectArray(json.' + field.name + ', ' + fieldType + '.decodeText);');
                             }
                         }
-                        else {
-                            if (field.type instanceof flatc.PrimitiveType) {
-                                this._builder.add('$.' + field.name + ' = reader.value(json.' + field.name + ', ' + field.defaultValue + ');');
-                            }
-                            else if (field.type instanceof flatc.Enum) {
-                                const enumName = '$root.' + field.type.parent.name + '.' + field.type.name;
-                                this._builder.add('$.' + field.name + ' = ' + enumName + '[json.' + field.name + '];');
-                            }
-                            else if (field.type instanceof flatc.Union) {
-                                const unionType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                                this._builder.add('$.' + field.name + ' = ' + unionType + '.decodeText(reader, json.' + field.name + ', json.' + field.name + '_type' + ');');
-                            }
-                            else { // struct | table
-                                const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                                this._builder.add('$.' + field.name + ' = reader.object(json.' + field.name + ', ' + fieldType + '.decodeText);');
-                            }
+                        else if (field.type instanceof flatc.PrimitiveType) {
+                            this._builder.add('$.' + field.name + ' = reader.value(json.' + field.name + ', ' + field.defaultValue + ');');
+                        }
+                        else if (field.type instanceof flatc.Enum) {
+                            const enumName = '$root.' + field.type.parent.name + '.' + field.type.name;
+                            this._builder.add('$.' + field.name + ' = ' + enumName + '[json.' + field.name + '];');
+                        }
+                        else if (field.type instanceof flatc.Union) {
+                            const unionType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                            this._builder.add('$.' + field.name + ' = ' + unionType + '.decodeText(reader, json.' + field.name + ', json.' + field.name + '_type' + ');');
+                        }
+                        else { // struct | table
+                            const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                            this._builder.add('$.' + field.name + ' = reader.object(json.' + field.name + ', ' + fieldType + '.decodeText);');
                         }
                     }
                     this._builder.add('return $;');
@@ -1071,20 +1067,18 @@ flatc.Generator = class {
                     if (field.repeated) {
                         throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
                     }
+                    else if (field.type instanceof flatc.PrimitiveType) {
+                        this._builder.add('$.' + field.name + ' = reader.' + field.type.name + '(position + ' + field.offset + ');');
+                    }
+                    else if (field.type instanceof flatc.Enum) {
+                        throw new flatc.Error('Not implemented.');
+                    }
+                    else if (field.type instanceof flatc.Struct) {
+                        const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                        this._builder.add('$.' + field.name + ' = ' + fieldType + '.decode(reader, position + ' + field.offset + ');');
+                    }
                     else {
-                        if (field.type instanceof flatc.PrimitiveType) {
-                            this._builder.add('$.' + field.name + ' = reader.' + field.type.name + '(position + ' + field.offset + ');');
-                        }
-                        else if (field.type instanceof flatc.Enum) {
-                            throw new flatc.Error('Not implemented.');
-                        }
-                        else if (field.type instanceof flatc.Struct) {
-                            const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                            this._builder.add('$.' + field.name + ' = ' + fieldType + '.decode(reader, position + ' + field.offset + ');');
-                        }
-                        else {
-                            throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
-                        }
+                        throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
                     }
                 }
                 this._builder.add('return $;');
@@ -1100,20 +1094,18 @@ flatc.Generator = class {
                         if (field.repeated) {
                             throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
                         }
+                        else if (field.type instanceof flatc.PrimitiveType) {
+                            this._builder.add('$.' + field.name + ' = json.' + field.name + ';');
+                        }
+                        else if (field.type instanceof flatc.Enum) {
+                            throw new flatc.Error('Not implemented.');
+                        }
+                        else if (field.type instanceof flatc.Struct) {
+                            const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
+                            this._builder.add('$.' + field.name + ' = ' + fieldType + '.decodeText(reader, json.' + field.name + ');');
+                        }
                         else {
-                            if (field.type instanceof flatc.PrimitiveType) {
-                                this._builder.add('$.' + field.name + ' = json.' + field.name + ';');
-                            }
-                            else if (field.type instanceof flatc.Enum) {
-                                throw new flatc.Error('Not implemented.');
-                            }
-                            else if (field.type instanceof flatc.Struct) {
-                                const fieldType = '$root.' + field.type.parent.name + '.' + field.type.name;
-                                this._builder.add('$.' + field.name + ' = ' + fieldType + '.decodeText(reader, json.' + field.name + ');');
-                            }
-                            else {
-                                throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
-                            }
+                            throw new flatc.Error("Struct '" + typeName + "' may contain only scalar or struct fields.");
                         }
                     }
                     this._builder.add('return $;');

+ 8 - 12
tools/protoc.js

@@ -1300,13 +1300,11 @@ protoc.Generator = class {
                                 else if (field.type instanceof protoc.PrimitiveType) {
                                     this._builder.add(variable + '.push(reader.' + field.type.name + '());');
                                 }
+                                else if (field.type.group) {
+                                    this._builder.add(variable + '.push(' + fieldTypeName(field) + '.decode(reader));');
+                                }
                                 else {
-                                    if (field.type.group) {
-                                        this._builder.add(variable + '.push(' + fieldTypeName(field) + '.decode(reader));');
-                                    }
-                                    else {
-                                        this._builder.add(variable + '.push(' + fieldTypeName(field) + '.decode(reader, reader.uint32()));');
-                                    }
+                                    this._builder.add(variable + '.push(' + fieldTypeName(field) + '.decode(reader, reader.uint32()));');
                                 }
                             }
                             else if (field.type instanceof protoc.Enum) {
@@ -1315,13 +1313,11 @@ protoc.Generator = class {
                             else if (field.type instanceof protoc.PrimitiveType) {
                                 this._builder.add(variable + ' = reader.' + field.type.name + '();');
                             }
+                            else if (field.type.group) {
+                                this._builder.add(variable + ' = ' + fieldTypeName(field) + '.decode(reader);');
+                            }
                             else {
-                                if (field.type.group) {
-                                    this._builder.add(variable + ' = ' + fieldTypeName(field) + '.decode(reader);');
-                                }
-                                else {
-                                    this._builder.add(variable + ' = ' + fieldTypeName(field) + '.decode(reader, reader.uint32());');
-                                }
+                                this._builder.add(variable + ' = ' + fieldTypeName(field) + '.decode(reader, reader.uint32());');
                             }
                             this._builder.add('break;');
                         this._builder.outdent();