eachSubModel()

in lib/generator.js [1014:1346]


  eachSubModel(ast, level) {
    assert.equal(ast.type, 'model');
    const modelName = _name(ast.modelName);
    this.visitAnnotation(ast.annotation, level);
    this.emit(`public static class ${_subModelName(modelName, this.conflictModelNameMap, this.allModleNameMap, this.enableMinimizeModelName)} extends TeaModel {\n`, level);
    this.visitModelBody(ast.modelBody, level + 1, modelName);
    this.visitBuildMethod(ast, level + 1);
    this.createGetSetMethod(ast.modelBody, level + 1, modelName);
    this.emit('}\n\n', level);
  }

  visitObjectFieldValue(ast, level) {
    this.visitExpr(ast, level);
  }

  visitObjectField(ast, level) {
    let comments = DSL.comment.getFrontComments(this.comments, ast.tokenRange[0]);
    this.visitComments(comments, level);
    if (ast.type === 'objectField') {
      var key = _escape(_name(ast.fieldName) || _string(ast.fieldName));
      this.emit(`new TeaPair("${key}", `, level);
      this.visitObjectFieldValue(ast.expr, level);
    } else {
      throw new Error('unimpelemented');
    }
    this.emit(')');
  }

  visitObject(ast, level) {
    assert.equal(ast.type, 'object');
    if (ast.fields.length === 0) {
      this.emit('new java.util.HashMap<>()');
      return;
    }
    var hasExpandField = false;
    var hasNotExpandField = false;
    for (let i = 0; i < ast.fields.length; i++) {
      const field = ast.fields[i];
      if (field.type === 'expandField') {
        hasExpandField = true;
        break;
      } else {
        hasNotExpandField = true;
      }
    }

    if (!hasExpandField) {
      this.emit('TeaConverter.buildMap(\n');
      for (let i = 0; i < ast.fields.length; i++) {
        this.visitObjectField(ast.fields[i], level + 1);
        if (i < ast.fields.length - 1) {
          this.emit(',');
        }
        this.emit('\n');
      }
      this.emit(')', level);
      return;
    }

    var all = [];
    // 分段
    var current = [];
    for (let i = 0; i < ast.fields.length; i++) {
      const field = ast.fields[i];
      if (field.type === 'objectField') {
        current.push(field);
      } else {
        if (current.length > 0) {
          all.push(current);
        }
        all.push(field);
        current = [];
      }
    }

    if (current.length > 0) {
      all.push(current);
    }

    this.emit('TeaConverter.merge(');
    if (ast.inferred && ast.inferred.valueType.name === 'string') {
      this.emit('String.class');
    } else {
      this.emit('Object.class');
    }
    var hasExpandFieldBuildMap = false;
    if (hasExpandField && hasNotExpandField) {
      hasExpandFieldBuildMap = true;
      this.emit(',\n');
      this.emit('TeaConverter.buildMap(\n', level + 1);
    } else {
      this.emit(',\n');
    }

    for (let i = 0; i < all.length; i++) {
      const item = all[i];
      if (Array.isArray(item)) {
        for (var j = 0; j < item.length; j++) {
          this.visitObjectField(item[j], level + 2);
          if (item[j + 1]) {
            this.emit(',\n');
          } else {
            this.emit('\n');
          }
        }
      } else {
        this.emit('', level + 1);
        this.visitExpr(item.expr, level);
        if (all[i + 1]) {
          this.emit(',');
        }
        this.emit('\n');
      }
      if (hasExpandFieldBuildMap) {
        this.emit(')', level + 1);
        if (all[i + 1]) {
          this.emit(',\n');
        } else {
          this.emit('\n');
        }
        hasExpandFieldBuildMap = false;
      }
    }
    this.emit(')', level);
  }

  visitCall(ast, level) {
    assert.equal(ast.type, 'call');
    if (ast.left.type === 'method_call') {
      this.visitMethodCall(ast, level);
    } else if (ast.left.type === 'instance_call') {
      this.visitInstanceCall(ast, level);
    } else if (ast.left.type === 'static_call') {
      this.visitStaticCall(ast, level);
    } else {
      throw new Error('unimplemented');
    }
  }

  visitStaticCall(ast, level) {
    assert.equal(ast.left.type, 'static_call');
    var className = this.imports[ast.left.id.lexeme].className || 'Client';
    this.emit(`${this.imports[ast.left.id.lexeme].package}.${className}.${_name(ast.left.propertyPath[0])}(`);
    for (let i = 0; i < ast.args.length; i++) {
      const expr = ast.args[i];
      if (expr.needCast) {
        this.emit('TeaModel.buildMap(');
      }
      this.visitExpr(expr, level);
      if (expr.needCast) {
        this.emit(')');
      }
      if (i !== ast.args.length - 1) {
        this.emit(', ');
      }
    }
    this.emit(')');
  }

  visitInstanceCall(ast, level) {
    assert.equal(ast.left.type, 'instance_call');
    const method = ast.left.propertyPath[0];
    var id = _name(ast.left.id);
    if (id.indexOf('@') > -1) {
      id = `_${_lowerFirst(id.substr(1))}`;
    }
    this.emit(`${id}.${_name(method)}(`);
    for (let i = 0; i < ast.args.length; i++) {
      const expr = ast.args[i];
      this.visitExpr(expr, level);
      if (i !== ast.args.length - 1) {
        this.emit(', ');
      }
    }
    this.emit(')');
  }

  visitMethodCall(ast, level) {
    assert.equal(ast.left.type, 'method_call');
    if (ast.isStatic) {
      var className = this.className || 'Client';
      this.emit(`${className}.${_name(ast.left.id)}(`);
    } else {
      this.emit(`this.${_name(ast.left.id)}(`);
    }
    for (let i = 0; i < ast.args.length; i++) {
      const expr = ast.args[i];
      if (expr.needCast) {
        this.emit('TeaModel.buildMap(');
      }
      this.visitExpr(expr, level);
      if (expr.needCast) {
        this.emit(')');
      }
      if (i !== ast.args.length - 1) {
        this.emit(', ');
      }
    }
    this.emit(')');
  }

  visitPropertyAccess(ast) {
    assert.equal(ast.type, 'property_access');

    var id = _name(ast.id);
    var expr = '';
    if (id === '__response') {
      expr += RESPONSE;
    } else if (id === '__request') {
      expr += REQUEST;
    } else {
      expr += avoidReserveName(id);
    }
    var current = ast.id.inferred;
    for (var i = 0; i < ast.propertyPath.length; i++) {
      var name = _name(ast.propertyPath[i]);
      if (current.type === 'model') {
        expr += `.${name}`;
      } else {
        expr += `.get("${name}")`;
      }
      current = ast.propertyPathTypes[i];
    }

    this.emit(expr);
  }
  emitNumber(ast, level) {
    this.emit(ast.value.value, level);
    if (ast.value.type === 'long') {
      this.emit('L');
    }
    if (ast.value.type === 'double') {
      this.emit('D');
    }
    if (ast.value.type === 'float') {
      this.emit('F');
    }
  }

  visitExpr(ast, level) {
    if (ast.type === 'boolean') {
      this.emit(`${ast.value}`);
    } else if (ast.type === 'property_access') {
      this.visitPropertyAccess(ast, level);
    } else if (ast.type === 'string') {
      this.emit(`"${ast.value.string.replace(new RegExp('"', 'g'), '\\"')}"`);
    } else if (ast.type === 'null') {
      this.emit('null');
    } else if (ast.type === 'number') {
      this.emitNumber(ast);
    } else if (ast.type === 'object') {
      this.visitObject(ast, level);
    } else if (ast.type === 'variable') {
      var id = _name(ast.id);
      if (id === '__response') {
        this.emit(RESPONSE);
      } else if (id === '__request') {
        this.emit(REQUEST);
      } else if (ast.inferred && ast.inferred.name === 'class') {
        this.emit(avoidReserveName(id) + '.class');
      } else {
        this.emit(avoidReserveName(id));
      }
    } else if (ast.type === 'virtualVariable') {
      const vid = `_${_lowerFirst(_name(ast.vid).substr(1))}`;
      this.emit(`${vid}`);
    } else if (ast.type === 'template_string') {
      for (let i = 0; i < ast.elements.length; i++) {
        var item = ast.elements[i];
        if (item.type === 'element') {
          this.emit('"');
          this.emit(item.value.string);
          this.emit('"');
        } else if (item.type === 'expr') {
          if (item.expr.type === 'property_access' && _name(item.expr.id) === '__module') {
            var value = this.__module;
            for (let i = 0; i < item.expr.propertyPath.length; i++) {
              value = value[_name(item.expr.propertyPath[i])];
            }
            this.emit('"');
            this.emit(value);
            this.emit('"');
          } else {
            this.visitExpr(item.expr, level);
          }
        } else {
          throw new Error('unimpelemented');
        }

        if (i < ast.elements.length - 1) {
          this.emit(' + ');
        }
      }
    } else if (ast.type === 'call') {
      this.visitCall(ast, level);
    } else if (ast.type === 'construct') {
      this.visitConstruct(ast, level);
    } else if (ast.type === 'array') {
      this.visitArray(ast, level);
    } else if (ast.type === 'and') {
      this.visitExpr(ast.left, level);
      this.emit(' && ');
      this.visitExpr(ast.right, level);
    } else if (ast.type === 'or') {
      this.visitExpr(ast.left, level);
      this.emit(' || ');
      this.visitExpr(ast.right, level);
    } else if (ast.type === 'null') {
      this.emit('null');
    } else if (ast.type === 'not') {
      this.emit('!');
      this.visitExpr(ast.expr, level);
    } else if (ast.type === 'construct_model') {
      this.visitConstructModel(ast, level);
    } else if (ast.type === 'super') {
      this.emit('super(');
      if (ast.args) {
        for (let i = 0; i < ast.args.length; i++) {
          if (i > 0) {
            this.emit(', ');
          }
          this.visitExpr(ast.args[i], level);
        }
      }
      this.emit(')');
    } else if (ast.type === 'map_access') {
      this.visitMapAccess(ast, true);
    } else if (ast.type === 'array_access') {
      this.visitArrayAccess(ast, true);
    } else {
      throw new Error('unimpelemented');
    }
  }