public String genObjToPass(CallNode callNode) {
    TranslateToPyExprVisitor translator =
        new TranslateToPyExprVisitor(localVarStack, pluginValueFactory, errorReporter);

    // Generate the expression for the original data to pass.
    String dataToPass;
    if (callNode.isPassingAllData()) {
      dataToPass = "data";
    } else if (callNode.isPassingData()) {
      dataToPass = translator.exec(callNode.getDataExpr()).getText();
    } else {
      dataToPass = "{}";
    }

    // Build an object literal containing the additional params.
    Map<PyExpr, PyExpr> additionalParams = new LinkedHashMap<>();

    for (CallParamNode child : callNode.getChildren()) {
      PyExpr key = new PyStringExpr("'" + child.getKey().identifier() + "'");

      if (child instanceof CallParamValueNode) {
        CallParamValueNode cpvn = (CallParamValueNode) child;
        additionalParams.put(key, translator.exec(cpvn.getExpr()));
      } else {
        CallParamContentNode cpcn = (CallParamContentNode) child;
        PyExpr valuePyExpr;
        if (isComputableAsPyExprVisitor.exec(cpcn)) {
          valuePyExpr =
              PyExprUtils.concatPyExprs(
                  genPyExprsVisitorFactory.create(localVarStack, errorReporter).exec(cpcn));
        } else {
          // This is a param with content that cannot be represented as Python expressions, so we
          // assume that code has been generated to define the temporary variable 'param<n>'.
          String paramExpr = "param" + cpcn.getId();
          // The param can be assumed to be a list at this point since it was created as an output
          // variable.
          valuePyExpr = new PyListExpr(paramExpr, Integer.MAX_VALUE);
        }

        // Param content nodes require a content kind in strict autoescaping, so the content must be
        // wrapped as SanitizedContent.
        valuePyExpr =
            InternalPyExprUtils.wrapAsSanitizedContent(
                cpcn.getContentKind(), valuePyExpr.toPyString());

        additionalParams.put(key, valuePyExpr);
      }
    }

    Map<PyExpr, PyExpr> defaultParams = new LinkedHashMap<>();
    for (TemplateParam param : callNode.getNearestAncestor(TemplateNode.class).getParams()) {
      if (param.hasDefault()) {
        defaultParams.put(
            new PyStringExpr("'" + param.name() + "'"), translator.exec(param.defaultValue()));
      }
    }

    PyExpr additionalParamsExpr = PyExprUtils.convertMapToPyExpr(additionalParams);

    // Cases 2 and 3: Additional params with and without original data to pass.
    if (callNode.isPassingData()) {
      if (callNode.numChildren() > 0) {
        // make a shallow copy so we don't accidentally modify the param
        dataToPass = "dict(" + dataToPass + ")";
        dataToPass =
            "runtime.merge_into_dict(" + dataToPass + ", " + additionalParamsExpr.getText() + ")";
      }

      if (!defaultParams.isEmpty()) {
        // If there are default parameters, merge the data we have so far into a dict of the default
        // parameters. This will override the parameter defaults with actual values (if there are
        // actual values).
        PyExpr defaultParamsExpr = PyExprUtils.convertMapToPyExpr(defaultParams);
        dataToPass =
            "runtime.merge_into_dict(" + defaultParamsExpr.getText() + ", " + dataToPass + ")";
      }

      return dataToPass;
    } else {
      return additionalParamsExpr.getText();
    }
  }
public String genObjToPass ( CallNode callNode ) { TranslateToPyExprVisitor translator = new TranslateToPyExprVisitor ( localVarStack , pluginValueFactory , errorReporter ) ; String dataToPass ; if ( callNode . isPassingAllData ( ) ) { dataToPass = "data" ; } else if ( callNode . isPassingData ( ) ) { dataToPass = translator . exec ( callNode . getDataExpr ( ) ) . getText ( ) ; } else { dataToPass = "{}" ; } Map < PyExpr , PyExpr > additionalParams = new LinkedHashMap < > ( ) ; for ( CallParamNode child : callNode . getChildren ( ) ) { PyExpr key = new PyStringExpr ( "'" + child . getKey ( ) . identifier ( ) + "'" ) ; if ( child instanceof CallParamValueNode ) { CallParamValueNode cpvn = ( CallParamValueNode ) child ; additionalParams . put ( key , translator . exec ( cpvn . getExpr ( ) ) ) ; } else { CallParamContentNode cpcn = ( CallParamContentNode ) child ; PyExpr valuePyExpr ; if ( isComputableAsPyExprVisitor . exec ( cpcn ) ) { valuePyExpr = PyExprUtils . concatPyExprs ( genPyExprsVisitorFactory . create ( localVarStack , errorReporter ) . exec ( cpcn ) ) ; } else { String paramExpr = "param" + cpcn . getId ( ) ; valuePyExpr = new PyListExpr ( paramExpr , Integer . MAX_VALUE ) ; } valuePyExpr = InternalPyExprUtils . wrapAsSanitizedContent ( cpcn . getContentKind ( ) , valuePyExpr . toPyString ( ) ) ; additionalParams . put ( key , valuePyExpr ) ; } } Map < PyExpr , PyExpr > defaultParams = new LinkedHashMap < > ( ) ; for ( TemplateParam param : callNode . getNearestAncestor ( TemplateNode . class ) . getParams ( ) ) { if ( param . hasDefault ( ) ) { defaultParams . put ( new PyStringExpr ( "'" + param . name ( ) + "'" ) , translator . exec ( param . defaultValue ( ) ) ) ; } } PyExpr additionalParamsExpr = PyExprUtils . convertMapToPyExpr ( additionalParams ) ; if ( callNode . isPassingData ( ) ) { if ( callNode . numChildren ( ) > 0 ) { dataToPass = "dict(" + dataToPass + ")" ; dataToPass = "runtime.merge_into_dict(" + dataToPass + ", " + additionalParamsExpr . getText ( ) + ")" ; } if ( ! defaultParams . isEmpty ( ) ) { PyExpr defaultParamsExpr = PyExprUtils . convertMapToPyExpr ( defaultParams ) ; dataToPass = "runtime.merge_into_dict(" + defaultParamsExpr . getText ( ) + ", " + dataToPass + ")" ; } return dataToPass ; } else { return additionalParamsExpr . getText ( ) ; } }
Generates the Python expression for the object to pass in a given call. This expression will be
a combination of passed data and additional content params. If both are passed, they'll be
combined into one dictionary.

@param callNode The call to generate code for.
@return The Python expression for the object to pass in the call.