%{ # -*- mode: Swift -*- from gyb_syntax_support import * from gyb_syntax_support.Traits import TRAITS NODE_MAP = create_node_map() # Ignore the following admonition it applies to the resulting .swift file only }% //// Automatically Generated From SyntaxNodes.swift.gyb. //// Do Not Edit Directly! //===------------ SyntaxNodes.swift - Syntax Node definitions -------------===// // // 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 // //===----------------------------------------------------------------------===// %{ """ Each Syntax node implements the protocol of a more generic node. For example, StructDeclSyntax implements DeclSyntax and can be used in contexts where DeclSyntax is expected. Each node will have: - An accessor for each child that will lazily instantiate it. - A `withX(_ x: XSyntax)` method for each child that will return a new Syntax node with the existing X child replaced with the passed-in version. This is a way to incrementally transform nodes in the tree. - An `addX(_ x: XSyntax)` method for children that are collections. This will append the provided node to the collection and return a new node with that collection replaced. - (in DEBUG mode) a `validate()` method that's called in the initializer. This only validates that all the children are the right kind/token, and does not raise an error if, say, a non-optional child is missing. """ }% /// A wrapper around a raw Syntax layout. public struct UnknownSyntax: _SyntaxBase { let _root: SyntaxData unowned let _data: SyntaxData /// Creates an `UnknownSyntax` node from the provided root and data. internal init(root: SyntaxData, data: SyntaxData) { self._root = root self._data = data #if DEBUG validate() #endif } } % for node in SYNTAX_NODES: % base_type = node.base_type % if node.is_base(): % for line in dedented_lines(node.description): /// ${line} % end public protocol ${node.name}: Syntax {} % elif node.collection_element: % pass % else: % for line in dedented_lines(node.description): /// ${line} % end public struct ${node.name}: ${base_type}, _SyntaxBase, Hashable { % if node.children: enum Cursor: Int { % for child in node.children: case ${child.swift_name} % end } % end let _root: SyntaxData unowned let _data: SyntaxData /// Creates a `${node.name}` node from the provided root and data. internal init(root: SyntaxData, data: SyntaxData) { self._root = root self._data = data #if DEBUG validate() #endif } % if node.requires_validation(): #if DEBUG func validate() { if isMissing { return } precondition(raw.layout.count == ${len(node.children)}) % for child in node.children: % child_var = '_' + child.swift_name let ${child_var} = raw[Cursor.${child.swift_syntax_kind}] % if child.token_choices: % choices = ["." + choice.swift_kind() for choice in child.token_choices] % choice_array = "[%s]" % ', '.join(choices) guard let ${child_var}TokenKind = ${child_var}.tokenKind else { fatalError("expected token child, got \(${child_var}.kind)") } precondition(${choice_array}.contains(${child_var}TokenKind), "expected one of ${choice_array} for '${child.swift_name}' " + "in node of kind ${node.swift_syntax_kind}") % elif child.text_choices: % choices = ", ".join("\"%s\"" % choice % for choice in child.text_choices) guard let ${child_var}TokenKind = ${child_var}.tokenKind else { fatalError("expected token child, got \(${child_var}.kind)") } precondition([${choices}].contains(${child_var}TokenKind.text), "expected one of '[${', '.join(child.text_choices)}]', got " + "'\(${child_var}TokenKind.text)'") % else: precondition(${child_var}.kind == .${child.swift_syntax_kind}, "expected child of kind .${child.swift_syntax_kind}, " + "got \(${child_var}.kind)") % end % end } #endif % end % for child in node.children: % ret_type = child.type_name % cast_symbol = 'as!' % if child.is_optional: % ret_type += '?' % cast_symbol = 'as?' % end % cast = '' if child.type_name == 'Syntax' \ % else '%s %s' % (cast_symbol, child.type_name) % for line in dedented_lines(child.description): /// ${line} % end public var ${child.swift_name}: ${ret_type} { let child = data.cachedChild(at: Cursor.${child.swift_name}) % if child.is_optional: if child == nil { return nil } % end return makeSyntax(root: _root, data: child!) ${cast} } % child_node = NODE_MAP.get(child.syntax_kind) % if child_node and child_node.is_syntax_collection(): % child_elt = child_node.collection_element_name % child_elt_type = child_node.collection_element_type /// Adds the provided `${child_elt}` to the node's `${child.swift_name}` /// collection. /// - param element: The new `${child_elt}` to add to the node's /// `${child.swift_name}` collection. /// - returns: A copy of the receiver with the provided `${child_elt}` /// appended to its `${child.swift_name}` collection. public func add${child_elt}(_ element: ${child_elt_type}) -> ${node.name} { var collection: RawSyntax if let col = raw[Cursor.${child.swift_name}] { collection = col.appending(element.raw) } else { collection = RawSyntax.node(SyntaxKind.${child_node.swift_syntax_kind}, [element.raw], .present) } let (root, newData) = data.replacingChild(collection, at: Cursor.${child.swift_name}) return ${node.name}(root: root, data: newData) } % end /// Returns a copy of the receiver with its `${child.swift_name}` replaced. /// - param newChild: The new `${child.swift_name}` to replace the node's /// current `${child.swift_name}`, if present. public func with${child.name}( _ newChild: ${child.type_name}?) -> ${node.name} { let raw = newChild?.raw ?? ${make_missing_swift_child(child)} let (root, newData) = data.replacingChild(raw, at: Cursor.${child.swift_name}) return ${node.name}(root: root, data: newData) } % end /// Determines if two `${node.name}` nodes are equal to each other. public static func ==(lhs: ${node.name}, rhs: ${node.name}) -> Bool { return lhs._data === rhs._data } /// A unique hash value for this node. public var hashValue: Int { return ObjectIdentifier(_data).hashValue } } % end % end % for trait in TRAITS: public protocol ${trait.trait_name}Syntax: Syntax { % for child in trait.children: % ret_type = child.type_name % if child.is_optional: % ret_type += '?' % end var ${child.swift_name}: ${ret_type} { get } func with${child.name}(_ newChild: ${child.type_name}?) -> Self % end } % end % for node in SYNTAX_NODES: % base_type = node.base_type % if node.is_base(): % pass % elif node.collection_element: % pass % elif node.traits: % traits_list = ", ".join(trait + 'Syntax' for trait in node.traits) extension ${node.name}: ${traits_list} {} % end % end /// MARK: Convenience methods extension StructDeclSyntax { /// Creates a new StructDeclSyntax with the provided name as its identifier. /// - param name: The new struct's name. /// - returns: A new StructDeclSyntax with the same fields as the receiver, /// but with the provided identifier. func withIdentifier(_ name: String) -> StructDeclSyntax { let newToken = SyntaxFactory.makeIdentifier(name, leadingTrivia: identifier.leadingTrivia, trailingTrivia: identifier.trailingTrivia) return withIdentifier(newToken) } }