//// Automatically Generated From SyntaxNodes.cpp.gyb.
//// Do Not Edit Directly!
//===----------------------------------------------------------------------===//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
// This source file is part of the polarphp.org open source project
//
// Copyright (c) 2017 - 2019 polarphp software foundation
// Copyright (c) 2017 - 2019 zzu_softboy <zzu_softboy@163.com>
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://polarphp.org/LICENSE.txt for license information
// See https://polarphp.org/CONTRIBUTORS.txt for the list of polarphp project authors
//
// Created by polarboy on 2019/11/06.

#include "polarphp/syntax/SyntaxNodes.h"

namespace polar::syntax {

<?php
use function Gyb\Utils\check_child_condition_raw;
use function Gyb\Utils\make_missing_child;
$syntaxNodeMap = $SYNTAX_NODE_MAP;
foreach ($SYNTAX_NODES as $node) {
   $nodeName = $node->getName();
   $children = $node->getChildren();
   $childrenCount = count($children);
   if ($node->requireValidation()) {
?>
void <?= $nodeName ?>::validate() const 
{
#ifdef POLAR_DEBUG_BUILD
   auto raw = m_data->getRaw();
   if (isMissing()) {
      return;
   }
   assert(raw->getLayout().size() == <?= $childrenCount ?>);
<?php
      foreach ($children as $child) {
         $tokenChoices = $child->getTokenChoices();
         $textChoices = $child->getTextChoices();
         $nodeChoices = $child->getNodeChoices();
         $mainToken = $child->getMainToken();
         $childName = $child->getName();
         $choices = [];
         if (!empty($tokenChoices)) {
            foreach ($tokenChoices as $tokenChoice) {
               $choices[] = 'TokenKindType::'.$tokenChoice->getKind();
            }
            $choices = implode(', ', $choices);
?>
   syntax_assert_child_token(raw, <?= $childName ?>, <?= $choices ?>);
<?php
         }
?>
<?php
         if ($mainToken && !empty($textChoices)) {
            $tokenKind = $mainToken->getKind();
            $choices = [];
            foreach ($textChoices as $textChoice) {
               $choices[] = sprintf('"%s"', $textChoice);
            }
            $choices = implode(', ', $choices);
?>
   syntax_assert_child_token_text(raw, <?= $childName ?>, TokenKindType::<?= $tokenKind ?>, <?= $choices ?>);     
<?php
         }
?>
<?php
         if (!empty($nodeChoices)) {
?>
   if (auto &child = raw->getChild(Cursor::<?= $childName ?>)) {
      assert(<?= check_child_condition_raw($child); ?>(child));
   }
<?php
         }
      }
?>
#endif
}

<?php
   }
?>
<?php
   // children get method
   foreach ($children as $child) {
      $childName = $child->getName();
      $childTypeName = $child->getTypeName();
      $childSyntaxKind = $child->getSyntaxKind();
      if ($child->isOptional()) {
?>
std::optional<<?= $childTypeName ?>> <?= $nodeName ?>::get<?= $childName ?>()
{
   auto childData = m_data->getChild(Cursor::<?= $childName ?>);
   if (!childData) {
      return std::nullopt;
   }
   return <?= $childTypeName ?>{m_root, childData.get()};
}

<?php
      } else {
?>
<?= $childTypeName ?> <?= $nodeName ?>::get<?= $childName ?>() 
{
   return <?= $childTypeName ?> {m_root, m_data->getChild(Cursor::<?= $childName ?>).get()};
}

<?php
      }
      $childNode = isset($syntaxNodeMap[$childSyntaxKind]) ? $syntaxNodeMap[$childSyntaxKind] : null;
      if ($childNode && $childNode->isSyntaxCollection()) {
         $elementName = $child->getCollectionElementName();
         $elementType = $childNode->getCollectionElementType();
         if (strlen($elementName) == 0) {
            throw new \RuntimeException(sprintf("'collectionElementName' should be set for '%s' of '%s'", 
               $childName, $nodeName));
         }
?>
<?= $nodeName ?> <?= $nodeName ?>::add<?= $elementName ?>(<?= $elementType ?> <?= lcfirst($elementName) ?>) 
{
   RefCountPtr<RawSyntax> raw = getRaw()->getChild(Cursor::<?= $childName ?>);
   if (raw) {
      raw = raw->append(<?= lcfirst($elementName) ?>.getRaw());
   } else {
      raw = RawSyntax::make(SyntaxKind::<?= $childSyntaxKind ?>, {<?= lcfirst($elementName) ?>.getRaw()}, SourcePresence::Present);
   }
   return m_data->replaceChild<<?= $nodeName ?>>(raw, Cursor::<?= $childName ?>);
}

<?php
      }
?>
<?= $nodeName ?> <?= $nodeName ?>::with<?= $childName ?>(std::optional<<?= $childTypeName ?>> new<?= $childTypeName ?>)
{
   RefCountPtr<RawSyntax> raw;
   if (new<?= $childTypeName ?>.has_value()) {
      raw = new<?= $childTypeName ?>->getRaw();
   } else {
<?php
      if ($child->isOptional()) {
?>
      raw = nullptr;
<?php
      } else {
?>
      raw = <?= make_missing_child($child); ?>;
<?php
      }
?>
   }
   return m_data->replaceChild<<?= $nodeName ?>>(raw, Cursor::<?= $childName ?>);
}

<?php
   }
}
?>
const char* get_syntax_structure_versioning_identifier()
{
   return nullptr;
}

} // polar::syntax
