%{
  from gyb_syntax_support import *
  # -*- mode: Swift -*-
  # Ignore the following admonition it applies to the resulting .swift file only
}%
//// Automatically Generated From SyntaxFactory.swift.gyb.
//// Do Not Edit Directly!
//===------- SyntaxFactory.swift - Syntax Factory implementations ---------===//
//
// This source file is part of the Swift.org open source project
//
// 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 file defines the SyntaxFactory, one of the most important client-facing
// types in lib/Syntax and likely to be very commonly used.
//
// Effectively a namespace, SyntaxFactory is never instantiated, but is *the*
// one-stop shop for making new Syntax nodes. Putting all of these into a
// collection of static methods provides a single point of API lookup for
// clients' convenience.
//
//===----------------------------------------------------------------------===//

public enum SyntaxFactory {
  public static func makeToken(_ kind: TokenKind, presence: SourcePresence,
                 leadingTrivia: Trivia = [],
                 trailingTrivia: Trivia = []) -> TokenSyntax {
    let data = SyntaxData(raw: .token(kind, leadingTrivia,
                                      trailingTrivia, presence))
    return TokenSyntax(root: data, data: data)
  }

  public static func makeUnknownSyntax(tokens: [TokenSyntax]) -> Syntax {
    let data = SyntaxData(raw: .node(.unknown, 
                                     tokens.map { $0.data.raw },
                                     .present))
    return Syntax(root: data, data: data)
  }

/// MARK: Syntax Node Creation APIs

% for node in SYNTAX_NODES:
%   if node.children:
%     child_params = []
%     for child in node.children:
%         param_type = child.type_name
%         if child.is_optional:
%            param_type = param_type + "?"
%         child_params.append("%s: %s" % (child.swift_name, param_type))
%     child_params = ', '.join(child_params)
  public static func make${node.syntax_kind}(${child_params}) -> ${node.name} {
    let data = SyntaxData(raw: .node(.${node.swift_syntax_kind}, [
%     for child in node.children:
%       if child.is_optional:
      ${child.swift_name}?.data.raw ?? ${make_missing_swift_child(child)},
%       else:
      ${child.swift_name}.data.raw,
%       end
%     end
    ], .present))
    return ${node.name}(root: data, data: data)
  }
%   elif node.is_syntax_collection():
  public static func make${node.syntax_kind}(
    _ elements: [${node.collection_element_type}]) -> ${node.name} {
    let data = SyntaxData(raw: .node(.${node.swift_syntax_kind},
                                     elements.map { $0.data.raw }, .present))
    return ${node.name}(root: data, data: data)
  }
%   end

  public static func makeBlank${node.syntax_kind}() -> ${node.name} {
    let data = SyntaxData(raw: .node(.${node.swift_syntax_kind}, [
%   for child in node.children:
      ${make_missing_swift_child(child)},
%   end
    ], .present))
    return ${node.name}(root: data, data: data)
  }
% end

/// MARK: Token Creation APIs

% for token in SYNTAX_TOKENS:
%   if token.is_keyword:
  public static func make${token.name}Keyword(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeToken(.${token.swift_kind()}, presence: .present,
                     leadingTrivia: leadingTrivia,
                     trailingTrivia: trailingTrivia)
  }
%   elif token.text:
  public static func make${token.name}Token(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeToken(.${token.swift_kind()}, presence: .present,
                     leadingTrivia: leadingTrivia,
                     trailingTrivia: trailingTrivia)
  }
%   else:
  public static func make${token.name}(_ text: String,
    leadingTrivia: Trivia = [], trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeToken(.${token.swift_kind()}(text), presence: .present,
                     leadingTrivia: leadingTrivia,
                     trailingTrivia: trailingTrivia)
  }
%   end
% end

/// MARK: Convenience APIs

  public static func makeVoidTupleType() -> TupleTypeSyntax {
    return makeTupleType(leftParen: makeLeftParenToken(),
                         elements: makeBlankTupleTypeElementList(),
                         rightParen: makeRightParenToken())
  }

  public static func makeTupleTypeElement(label: TokenSyntax?,
    colon: TokenSyntax?, type: TypeSyntax,
    comma: TokenSyntax?) -> TupleTypeElementSyntax {
    let annotation = makeTypeAnnotation(attributes: makeBlankAttributeList(),
                                        inOutKeyword: nil,
                                        type: type)
    return makeTupleTypeElement(label: label, colon: colon, 
                                typeAnnotation: annotation,
                                comma: comma)
  }

  public static func makeTupleTypeElement(type: TypeSyntax,
    comma: TokenSyntax?) -> TupleTypeElementSyntax  {
    return makeTupleTypeElement(label: nil, colon: nil, 
                                type: type, comma: comma)
  }

  public static func makeGenericParameter(type: TypeIdentifierSyntax,
      trailingComma: TokenSyntax) -> GenericParameterSyntax {
    return makeGenericParameter(typeIdentifier: type, colon: nil,
                                inheritedType: nil,
                                trailingComma: trailingComma)
  }

  public static func makeTypeIdentifier(_ typeName: String,
    leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
    let identifier = makeIdentifier(typeName, leadingTrivia: leadingTrivia, 
                                    trailingTrivia: trailingTrivia)
    return makeTypeIdentifier(typeName:identifier, genericArgumentClause: nil,
                              period: nil, typeIdentifier: nil)
  }

  public static func makeAnyTypeIdentifier(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
    return makeTypeIdentifier("Any", leadingTrivia: leadingTrivia, 
                              trailingTrivia: trailingTrivia)
  }

  public static func makeSelfTypeIdentifier(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TypeIdentifierSyntax {
    return makeTypeIdentifier("Self", leadingTrivia: leadingTrivia, 
                              trailingTrivia: trailingTrivia)
  }

  public static func makeTypeToken(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeIdentifier("Type", leadingTrivia: leadingTrivia, 
                          trailingTrivia: trailingTrivia)
  }

  public static func makeProtocolToken(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeIdentifier("Protocol", leadingTrivia: leadingTrivia,
                          trailingTrivia: trailingTrivia)
  }

  public static func makeEqualityOperator(leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> TokenSyntax {
    return makeToken(.spacedBinaryOperator("=="),
                     presence: .present,
                     leadingTrivia: leadingTrivia,
                     trailingTrivia: trailingTrivia)
  }

  public static func makeStringLiteralExpr(_ text: String,
    leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> StringLiteralExprSyntax {
    let literal = makeStringLiteral("\"\(text)\"", 
                                    leadingTrivia: leadingTrivia,
                                    trailingTrivia: trailingTrivia)
    return makeStringLiteralExpr(stringLiteral: literal)
  }

  public static func makeVariableExpr(_ text: String,
    leadingTrivia: Trivia = [],
    trailingTrivia: Trivia = []) -> SymbolicReferenceExprSyntax {
    let string = makeIdentifier(text,
      leadingTrivia: leadingTrivia, trailingTrivia: trailingTrivia)
    return makeSymbolicReferenceExpr(identifier: string,
                                     genericArgumentClause: nil)
  }
}
