<commit_before>part of lambda.transformer;

/// Turns a Lambda template to Dart code.
class TemplateCompiler {
  final String _componentClassName;
  final String _template;
  final _buf = new StringBuffer();

  XmlNode _templateRoot;
  final _bindings = <Binding>[];

  TemplateCompiler(this._componentClassName, this._template);

  String compile() {
    _parseTemplate();
    _emitComponentHeader();
    _emit(' return');
    _virtualizeNode(_templateRoot);
    _emit(' ;');
    _emitComponentFooter();
    return _buf.toString();
  }

  String compileBuildBodyForTesting() {
    _parseTemplate();
    _virtualizeNode(_templateRoot);
    return _buf.toString();
  }

  void _virtualizeNode(XmlNode node) {
    if (node is XmlElement) {
      XmlElement elem = node;
      _emit(" vElement('${elem.name.local}'");
      if (elem.attributes.isNotEmpty) {
        _emit(' , customAttrs: {');
        elem.attributes.forEach((XmlAttribute attr) {
          _emit(" '''${attr.name.local}''': '''${attr.value}'''");
        });
        _emit(' }');
      }
      _emit(' )');
      if (elem.children.isNotEmpty) {
        _emit(' (');
        _virtualizeNode(elem.children.first);
        elem.children.skip(1).forEach((XmlNode n) {
          _emit(' ,');
          _virtualizeNode(n);
        });
        _emit(' )');
      }
    } else if (node is XmlText) {
      int textBindingIndex = -1;
      int currentIndex = 0;
      final value = new StringBuffer();
      while((textBindingIndex = node.text.indexOf('{{', textBindingIndex + 1)) >= 0) {
        int indexOfClosingParens = node.text.indexOf('}}', textBindingIndex + 1);
        int bindingIndex = int.parse(node.text.substring(textBindingIndex + 2, indexOfClosingParens));
        value
            ..write(node.text.substring(currentIndex, textBindingIndex))
            ..write('\${context.')
            ..write((_bindings[bindingIndex] as TextBinding).expression)
            ..write('}');
        currentIndex = indexOfClosingParens + 2;
      }
      value.write(node.text.substring(currentIndex));
      _emit(" vText('''${value}''')");
    } else {
      throw 'Node type ${node.runtimeType} not yet supported.';
    }
  }<commit_msg>break _virtualizeNode into smaller methods<commit_after>part of lambda.transformer;

/// Turns a Lambda template to Dart code.
class TemplateCompiler {
  final String _componentClassName;
  final String _template;
  final _buf = new StringBuffer();

  XmlNode _templateRoot;
  final _bindings = <Binding>[];

  TemplateCompiler(this._componentClassName, this._template);

  String compile() {
    _parseTemplate();
    _emitComponentHeader();
    _emit(' return');
    _virtualizeNode(_templateRoot);
    _emit(' ;');
    _emitComponentFooter();
    return _buf.toString();
  }

  String compileBuildBodyForTesting() {
    _parseTemplate();
    _virtualizeNode(_templateRoot);
    return _buf.toString();
  }

  void _virtualizeNode(XmlNode node) {
    if (node is XmlElement) {
      _virtualizeElement(node);
    } else if (node is XmlText) {
      _virtualizeText(node);
    } else {
      throw 'Node type ${node.runtimeType} not yet supported.';
    }
  }

  void _virtualizeElement(XmlElement elem) {
    _emit(" vElement('${elem.name.local}'");
    if (elem.attributes.isNotEmpty) {
      _emit(' , customAttrs: {');
      elem.attributes.forEach((XmlAttribute attr) {
        _emit(" '''${attr.name.local}''': '''${attr.value}'''");
      });
      _emit(' }');
    }
    _emit(' )');
    if (elem.children.isNotEmpty) {
      _emit(' (');
      _virtualizeNode(elem.children.first);
      elem.children.skip(1).forEach((XmlNode n) {
        _emit(' ,');
        _virtualizeNode(n);
      });
      _emit(' )');
    }
  }

  void _virtualizeText(XmlText node) {
    int textBindingIndex = -1;
    int currentIndex = 0;
    final value = new StringBuffer();
    while((textBindingIndex = node.text.indexOf('{{', textBindingIndex + 1)) >= 0) {
      int indexOfClosingParens = node.text.indexOf('}}', textBindingIndex + 1);
      int bindingIndex = int.parse(node.text.substring(textBindingIndex + 2, indexOfClosingParens));
      value
          ..write(node.text.substring(currentIndex, textBindingIndex))
          ..write('\${context.')
          ..write((_bindings[bindingIndex] as TextBinding).expression)
          ..write('}');
      currentIndex = indexOfClosingParens + 2;
    }
    value.write(node.text.substring(currentIndex));
    _emit(" vText('''${value}''')");
  }
{'fraction_non_alphanumeric': 0.1502452073116362, 'fraction_numerical': 0.0035666518056174765, 'mean_word_length': 2.9602824360105915, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4810563', 'n_tokens_mistral': 1379, 'n_tokens_neox': 1346, 'n_words': 269}