diff --git a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift index f8ada42f463..6c5af908494 100644 --- a/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/AttributeNodes.swift @@ -49,6 +49,14 @@ public let ATTRIBUTE_NODES: [Node] = [ nameForDiagnostics: "attribute", documentation: "An `@` attribute.", parserFunction: "parseAttribute", + rules: [ + ConvenienceInitRule( + nonOptionalChildName: "arguments", + defaults: [ + "leftParen": .leftParen, + "rightParen": .rightParen + ]) + ], children: [ Child( name: "atSign", diff --git a/CodeGeneration/Sources/SyntaxSupport/ConvenienceInitRule.swift b/CodeGeneration/Sources/SyntaxSupport/ConvenienceInitRule.swift new file mode 100644 index 00000000000..7929e078d86 --- /dev/null +++ b/CodeGeneration/Sources/SyntaxSupport/ConvenienceInitRule.swift @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2023 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 +// +//===----------------------------------------------------------------------===// + +import Foundation +import SwiftSyntax + +/// A rule that describes convenienve initialization rules for a ``Node``. +/// +/// When generating syntax nodes, SwiftSyntax will make additional +/// convenience initializer for each rule that a Node has. +/// +/// The convenience initializer will take a non-optional parameter +/// `nonOptionalChildName`, and when a non-optional value is passed, it'll call +/// the full memberwise initializer with the provided `defaults`. +/// +/// For example, when initializing an `EnumCaseParameterSyntax`, the convenience +/// initializer will take a non-optional `firstName` parameter, and when it's +/// passed, it'll call the full memberwise initializer with +/// `colon = .colonToken()`. +public struct ConvenienceInitRule { + /// The name of the parameter that is required to be present for + /// this conveniece initializer rule to apply. + public let nonOptionalChildName: String + + /// A dicrionary of parameter names to their respective default values + /// to apply when the `nonOptionalChildName` is passed as concrete value. + public let defaults: [String: Token] +} diff --git a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift index 511ca84c3a3..ee8a7d7b3fb 100644 --- a/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift @@ -639,6 +639,14 @@ public let DECL_NODES: [Node] = [ nameForDiagnostics: "parameter", parserFunction: "parseEnumCaseParameter", traits: ["WithTrailingComma", "WithModifiers"], + rules: [ + ConvenienceInitRule( + nonOptionalChildName: "firstName", + defaults: [ + "colon": .colon + ] + ) + ], children: [ Child( name: "modifiers", diff --git a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift index b79ced0bf07..dfe56e9296c 100644 --- a/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift +++ b/CodeGeneration/Sources/SyntaxSupport/ExprNodes.swift @@ -314,6 +314,14 @@ public let EXPR_NODES: [Node] = [ traits: [ "WithTrailingComma" ], + rules: [ + ConvenienceInitRule( + nonOptionalChildName: "name", + defaults: [ + "equal": .equal + ] + ) + ], children: [ Child( name: "specifier", @@ -794,6 +802,15 @@ public let EXPR_NODES: [Node] = [ kind: .functionCallExpr, base: .expr, nameForDiagnostics: "function call", + rules: [ + ConvenienceInitRule( + nonOptionalChildName: "arguments", + defaults: [ + "leftParen": .leftParen, + "rightParen": .rightParen + ] + ) + ], children: [ Child( name: "calledExpression", diff --git a/CodeGeneration/Sources/SyntaxSupport/Node.swift b/CodeGeneration/Sources/SyntaxSupport/Node.swift index 36bd7830db6..07ead68b2ba 100644 --- a/CodeGeneration/Sources/SyntaxSupport/Node.swift +++ b/CodeGeneration/Sources/SyntaxSupport/Node.swift @@ -63,6 +63,10 @@ public class Node { return kind.varOrCaseName } + /// List of convenience initializer rules for this node. CodeGeneration will + /// generate a convenience initializer for each rule. + public let rules: [ConvenienceInitRule] + /// If this is a layout node, return a view of the node that provides access /// to the layout-node specific properties. public var layoutNode: LayoutNode? { @@ -112,6 +116,7 @@ public class Node { documentation: String? = nil, parserFunction: TokenSyntax? = nil, traits: [String] = [], + rules: [ConvenienceInitRule] = [], children: [Child] = [] ) { precondition(base != .syntaxCollection) @@ -123,6 +128,7 @@ public class Node { self.nameForDiagnostics = nameForDiagnostics self.documentation = docCommentTrivia(from: documentation) self.parserFunction = parserFunction + self.rules = rules let childrenWithUnexpected: [Child] if children.isEmpty { @@ -229,6 +235,7 @@ public class Node { isExperimental: Bool = false, nameForDiagnostics: String?, documentation: String? = nil, + rules: [ConvenienceInitRule] = [], parserFunction: TokenSyntax? = nil, elementChoices: [SyntaxNodeKind] ) { @@ -239,6 +246,7 @@ public class Node { self.nameForDiagnostics = nameForDiagnostics self.documentation = docCommentTrivia(from: documentation) self.parserFunction = parserFunction + self.rules = rules assert(!elementChoices.isEmpty) self.data = .collection(choices: elementChoices) diff --git a/CodeGeneration/Sources/generate-swift-syntax/LayoutNode+Extensions.swift b/CodeGeneration/Sources/generate-swift-syntax/LayoutNode+Extensions.swift index 495cbf89bf5..d2c51f59762 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/LayoutNode+Extensions.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/LayoutNode+Extensions.swift @@ -16,52 +16,156 @@ import SyntaxSupport import Utils extension LayoutNode { - func generateInitializerDeclHeader(useDeprecatedChildName: Bool = false) -> SyntaxNodeString { + + /// Returns Child parameter type as a ``TypeSyntax``. + func generateChildParameterType(for child: Child, isOptional: Bool = false) -> TypeSyntax { + var paramType: TypeSyntax + + if !child.kind.isNodeChoicesEmpty { + paramType = "\(child.syntaxChoicesType)" + } else if child.hasBaseType { + paramType = "some \(child.syntaxNodeKind.protocolType)" + } else { + paramType = child.syntaxNodeKind.syntaxType + } + + if isOptional { + if paramType.is(SomeOrAnyTypeSyntax.self) { + paramType = "(\(paramType))?" + } else { + paramType = "\(paramType)?" + } + } + + return paramType + } + + /// Generates a convenience memberwise SyntaxNode initializer based on a + /// given ``ConvenienceInitRule``. + /// + /// - parameters: + /// - rule: The ``ConvenienceInitRule`` to use for generating the initializer. Applying a rule will make some children non-optional, and set default values for other children. + /// - useDeprecatedChildName: Whether to use the deprecated child name for the initializer parameter. + /// - returns: + /// - ``SyntaxNodeString``: The generated initializer. + func generateInitializerDeclHeader(for rule: ConvenienceInitRule? = nil, useDeprecatedChildName: Bool = false) -> SyntaxNodeString { if children.isEmpty { return "public init()" } - func createFunctionParameterSyntax(for child: Child) -> FunctionParameterSyntax { - var paramType: TypeSyntax - if !child.kind.isNodeChoicesEmpty { - paramType = "\(child.syntaxChoicesType)" - } else if child.hasBaseType { - paramType = "some \(child.syntaxNodeKind.protocolType)" + /// Returns the child paramter name. + func generateChildParameterName(for child: Child) -> TokenSyntax { + let parameterName: TokenSyntax + + if useDeprecatedChildName, let deprecatedVarName = child.deprecatedVarName { + parameterName = deprecatedVarName } else { - paramType = child.syntaxNodeKind.syntaxType + parameterName = child.varOrCaseName } + return parameterName + } - if child.isOptional { - if paramType.is(SomeOrAnyTypeSyntax.self) { - paramType = "(\(paramType))?" + /// Returns whether a given child should be optional in the initializer, + /// based on a provided ``ConvenienceInitRule``. + /// + /// If the rule is `nil`, this func will return `nil` as well, which means + /// that you should fall back to whether child is optional in the ``Node`` + /// definition. + /// + func ruleBasedChildIsOptional(for child: Child, with rule: ConvenienceInitRule?) -> Bool { + if let rule = rule { + if rule.nonOptionalChildName == child.name { + return false } else { - paramType = "\(paramType)?" + return child.isOptional } + } else { + return child.isOptional } + } - let parameterName: TokenSyntax + /// Returns a default value for a given child, based on a provided + /// ``ConvenienceInitRule``. + /// + /// If the rule should not affect this child, the + /// `child.defualtInitialization` will be returned. + func ruleBasedChildDefaultValue(for child: Child, with rule: ConvenienceInitRule?) -> InitializerClauseSyntax? { + if ruleBasedShouldOverrideDefault(for: child, with: rule) { + if let rule, let defaultValue = rule.defaults[child.name] { + return InitializerClauseSyntax( + equal: .equalToken(leadingTrivia: .space, trailingTrivia: .space), + value: ExprSyntax(".\(defaultValue.spec.varOrCaseName)Token()") + ) + } else { + return nil + } + } else { + return child.defaultInitialization + } - if useDeprecatedChildName, let deprecatedVarName = child.deprecatedVarName { - parameterName = deprecatedVarName + } + + /// Should the convenience initializer override the default value of a given + /// child? + /// + /// Returns `true` if there is a default value in the rule, or if the rule + /// requires this parameter to be non-optional. + /// If the rule is `nil`, it will return false. + func ruleBasedShouldOverrideDefault(for child: Child, with rule: ConvenienceInitRule?) -> Bool { + if let rule { + // If the rule provides a default for this child, override it and set the rule-based default. + if rule.defaults[child.name] != nil { + return true + } + + // For the non-optional rule-based parameter, strip the default value (override, but there will be no default) + return rule.nonOptionalChildName == child.name } else { - parameterName = child.varOrCaseName + return false } + } + + + /// Generates a ``FunctionParameterSyntax`` for a given ``Child`` of this node. + /// + /// - parameters: + /// - child: The ``Child`` to generate the parameter for. + /// - isOptional: Is the parameter optional? + /// + func generateInitFunctionParameterSyntax( + for child: Child, + isOptional: Bool, + defaultValue: InitializerClauseSyntax? = nil + ) -> FunctionParameterSyntax { + let parameterName = generateChildParameterName(for: child) return FunctionParameterSyntax( leadingTrivia: .newline, firstName: child.isUnexpectedNodes ? .wildcardToken(trailingTrivia: .space) : parameterName, secondName: child.isUnexpectedNodes ? parameterName : nil, colon: .colonToken(), - type: paramType, - defaultValue: child.defaultInitialization + type: generateChildParameterType(for: child, isOptional: isOptional), + defaultValue: defaultValue ) } + // Iterate over all children including unexpected, or only over expected children of the Node. + // + // For convenience initializers, we don't need unexpected tokens in the arguments list + // because convenience initializers are meant to be used bo developers manually + // hence there should be no unexpected tokens. + let childrenToIterate = rule != nil ? nonUnexpectedChildren : children + + // Iterate over the selected children, and make FunctionParameterSyntax for each of them. let params = FunctionParameterListSyntax { FunctionParameterSyntax("leadingTrivia: Trivia? = nil") - for child in children { - createFunctionParameterSyntax(for: child) + for child in childrenToIterate { + generateInitFunctionParameterSyntax( + for: child, + isOptional: ruleBasedChildIsOptional(for: child, with: rule), + defaultValue: ruleBasedChildDefaultValue(for: child, with: rule) + ) } FunctionParameterSyntax("trailingTrivia: Trivia? = nil") @@ -75,6 +179,18 @@ extension LayoutNode { """ } + /// Returns a DccC comment for the parameters that get a default value, + /// with their corresponding default values, for a rule-based convenience initializer + /// for a node. + func generateRuleBasedInitParamsDocComment(for rule: ConvenienceInitRule) -> SwiftSyntax.Trivia { + var params = "" + for (childName, defaultValue) in rule.defaults { + params += " - `\(childName)`: `TokenSyntax.\(defaultValue.spec.varOrCaseName)Token()`\n" + } + return docCommentTrivia(from: params) + } + + /// Returns a DocC comment for the full memberwise initializer for this node. func generateInitializerDocComment() -> SwiftSyntax.Trivia { func generateParamDocComment(for child: Child) -> String? { if child.documentationAbstract.isEmpty { diff --git a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift index 7cd8fc4ec43..530595e6390 100644 --- a/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift +++ b/CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift @@ -78,6 +78,57 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax { """ ) + for rule in node.rules { + try! InitializerDeclSyntax( + """ + /// A convenience initializer for ``\(node.kind.syntaxType)`` + /// that takes a non-optional value for `\(raw: rule.nonOptionalChildName)` parameter, + /// and adds the following default values: + \(node.generateRuleBasedInitParamsDocComment(for: rule)) + \(node.generateInitializerDeclHeader(for: rule)) + """ + ) { + // Convenience initializer just calls the full initializer + // with certain child parameters specified as optional types + // and providing the rule-based default value for the affected + // parameters. + FunctionCallExprSyntax( + calledExpression: ExprSyntax("self.init"), + leftParen: .leftParenToken(), + arguments: LabeledExprListSyntax { + LabeledExprSyntax( + label: TokenSyntax("leadingTrivia"), + colon: .colonToken(), + expression: ExprSyntax("leadingTrivia"), + trailingComma: .commaToken() + ) + + for child in node.nonUnexpectedChildren { + LabeledExprSyntax( + label: child.varOrCaseName, + colon: .colonToken(), + expression: rule.nonOptionalChildName == child.name ? + ExprSyntax("\(child.varOrCaseName.backtickedIfNeeded) as \(node.generateChildParameterType(for: child, isOptional: true))") : + ExprSyntax("\(child.varOrCaseName.backtickedIfNeeded)"), + trailingComma: .commaToken() + ) + } + + LabeledExprSyntax( + label: TokenSyntax("trailingTrivia"), + colon: .colonToken(), + expression: ExprSyntax("trailingTrivia") + ) + }, + rightParen: .rightParenToken() + ) + } + } + + // The main member-wise initializer + // generateInitializerDocComment renders DocC comment + // generateInitializerDeclHeader renders the actual init declaration + // and lists out all it's parameters and their default values try! InitializerDeclSyntax( """ \(node.generateInitializerDocComment()) @@ -100,6 +151,7 @@ func syntaxNode(nodesStartingWith: [Character]) -> SourceFileSyntax { ) ) ) + let layoutList = ArrayExprSyntax { for child in node.children { ArrayElementSyntax( diff --git a/Sources/SwiftSyntax/Convenience.swift b/Sources/SwiftSyntax/Convenience.swift index 6521bd0e569..177915f49fe 100644 --- a/Sources/SwiftSyntax/Convenience.swift +++ b/Sources/SwiftSyntax/Convenience.swift @@ -10,64 +10,6 @@ // //===----------------------------------------------------------------------===// -extension ClosureCaptureSyntax { - - /// Creates a ``ClosureCaptureSyntax`` with a `name`, and automatically adds an `equal` token to it since the name is non-optional. - /// - /// - SeeAlso: ``ClosureCaptureSyntax/init(leadingTrivia:_:specifier:_:name:_:equal:_:expression:_:trailingComma:_:trailingTrivia:)``. - /// - public init( - leadingTrivia: Trivia? = nil, - specifier: ClosureCaptureSpecifierSyntax? = nil, - name: TokenSyntax, - equal: TokenSyntax = TokenSyntax.equalToken(), - expression: some ExprSyntaxProtocol, - trailingComma: TokenSyntax? = nil, - trailingTrivia: Trivia? = nil - ) { - self.init( - leadingTrivia: leadingTrivia, - specifier: specifier, - name: name as TokenSyntax?, - equal: equal, - expression: expression, - trailingComma: trailingComma, - trailingTrivia: trailingTrivia - ) - } -} - -extension EnumCaseParameterSyntax { - - /// Creates an ``EnumCaseParameterSyntax`` with a `firstName`, and automatically adds a `colon` to it. - /// - /// - SeeAlso: For more information on the arguments, see ``EnumCaseParameterSyntax/init(leadingTrivia:_:modifiers:_:firstName:_:secondName:_:colon:_:type:_:defaultArgument:_:trailingComma:_:trailingTrivia:)`` - /// - public init( - leadingTrivia: Trivia? = nil, - modifiers: DeclModifierListSyntax = [], - firstName: TokenSyntax, - secondName: TokenSyntax? = nil, - colon: TokenSyntax = TokenSyntax.colonToken(), - type: some TypeSyntaxProtocol, - defaultValue: InitializerClauseSyntax? = nil, - trailingComma: TokenSyntax? = nil, - trailingTrivia: Trivia? = nil - ) { - self.init( - leadingTrivia: leadingTrivia, - modifiers: modifiers, - firstName: firstName as TokenSyntax?, - secondName: secondName, - colon: colon, - type: type, - defaultValue: defaultValue, - trailingComma: trailingComma, - trailingTrivia: trailingTrivia - ) - } -} - extension MemberAccessExprSyntax { /// Creates a new ``MemberAccessExprSyntax`` where the accessed member is represented by /// an identifier without specifying argument labels. diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift index e9e13445221..8d1ccb1b660 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesAB.swift @@ -2575,6 +2575,33 @@ public struct AttributeSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxNodePr self._syntaxNode = Syntax(data) } + /// A convenience initializer for ``AttributeSyntax`` + /// that takes a non-optional value for `arguments` parameter, + /// and adds the following default values: + /// - `leftParen`: `TokenSyntax.leftParenToken()` + /// - `rightParen`: `TokenSyntax.rightParenToken()` + /// + public init( + leadingTrivia: Trivia? = nil, + atSign: TokenSyntax = .atSignToken(), + attributeName: some TypeSyntaxProtocol, + leftParen: TokenSyntax? = .leftParenToken(), + arguments: Arguments, + rightParen: TokenSyntax? = .rightParenToken(), + trailingTrivia: Trivia? = nil + + ) { + self.init( + leadingTrivia: leadingTrivia, + atSign: atSign, + attributeName: attributeName, + leftParen: leftParen, + arguments: arguments as Arguments?, + rightParen: rightParen, + trailingTrivia: trailingTrivia + ) + } + /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - atSign: The `@` sign. diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesC.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesC.swift index 388feb8c1f7..b2a1af0786d 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesC.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesC.swift @@ -1585,6 +1585,32 @@ public struct ClosureCaptureSyntax: SyntaxProtocol, SyntaxHashable, _LeafSyntaxN self._syntaxNode = Syntax(data) } + /// A convenience initializer for ``ClosureCaptureSyntax`` + /// that takes a non-optional value for `name` parameter, + /// and adds the following default values: + /// - `equal`: `TokenSyntax.equalToken()` + /// + public init( + leadingTrivia: Trivia? = nil, + specifier: ClosureCaptureSpecifierSyntax? = nil, + name: TokenSyntax, + equal: TokenSyntax? = .equalToken(), + expression: some ExprSyntaxProtocol, + trailingComma: TokenSyntax? = nil, + trailingTrivia: Trivia? = nil + + ) { + self.init( + leadingTrivia: leadingTrivia, + specifier: specifier, + name: name as TokenSyntax?, + equal: equal, + expression: expression, + trailingComma: trailingComma, + trailingTrivia: trailingTrivia + ) + } + /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. diff --git a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift index cd0e5a5c089..90d6a36e8ce 100644 --- a/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift +++ b/Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesEF.swift @@ -982,6 +982,36 @@ public struct EnumCaseParameterSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt self._syntaxNode = Syntax(data) } + /// A convenience initializer for ``EnumCaseParameterSyntax`` + /// that takes a non-optional value for `firstName` parameter, + /// and adds the following default values: + /// - `colon`: `TokenSyntax.colonToken()` + /// + public init( + leadingTrivia: Trivia? = nil, + modifiers: DeclModifierListSyntax = [], + firstName: TokenSyntax, + secondName: TokenSyntax? = nil, + colon: TokenSyntax? = .colonToken(), + type: some TypeSyntaxProtocol, + defaultValue: InitializerClauseSyntax? = nil, + trailingComma: TokenSyntax? = nil, + trailingTrivia: Trivia? = nil + + ) { + self.init( + leadingTrivia: leadingTrivia, + modifiers: modifiers, + firstName: firstName as TokenSyntax?, + secondName: secondName, + colon: colon, + type: type, + defaultValue: defaultValue, + trailingComma: trailingComma, + trailingTrivia: trailingTrivia + ) + } + /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - colon: If the parameter has a label, the colon separating the label from the type. @@ -3128,6 +3158,35 @@ public struct FunctionCallExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafE self._syntaxNode = Syntax(data) } + /// A convenience initializer for ``FunctionCallExprSyntax`` + /// that takes a non-optional value for `arguments` parameter, + /// and adds the following default values: + /// - `rightParen`: `TokenSyntax.rightParenToken()` + /// - `leftParen`: `TokenSyntax.leftParenToken()` + /// + public init( + leadingTrivia: Trivia? = nil, + calledExpression: some ExprSyntaxProtocol, + leftParen: TokenSyntax? = .leftParenToken(), + arguments: LabeledExprListSyntax, + rightParen: TokenSyntax? = .rightParenToken(), + trailingClosure: ClosureExprSyntax? = nil, + additionalTrailingClosures: MultipleTrailingClosureElementListSyntax = [], + trailingTrivia: Trivia? = nil + + ) { + self.init( + leadingTrivia: leadingTrivia, + calledExpression: calledExpression, + leftParen: leftParen, + arguments: arguments as LabeledExprListSyntax?, + rightParen: rightParen, + trailingClosure: trailingClosure, + additionalTrailingClosures: additionalTrailingClosures, + trailingTrivia: trailingTrivia + ) + } + /// - Parameters: /// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored. /// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored.