Skip to content

Remove expressible as syntax token #343

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import SwiftSyntax

extension BooleanLiteralExpr {
public init(_ value: Bool) {
self.init(booleanLiteral: value ? TokenSyntax.true : .false)
self.init(booleanLiteral: value ? .true : .false)
}
}

Expand Down
61 changes: 37 additions & 24 deletions Sources/SwiftSyntaxBuilder/Buildables.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
NODE_MAP = create_node_map()
# -*- mode: Swift -*-
# Ignore the following admonition it applies to the resulting .swift file only

# Use [:] to make sure we copy the conformances so that we don't modify
# `SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES` when adding elements to `expressible_as_protocols` below.
def get_expressible_as_conformances(conforming_type):
expressible_as_protocols = (SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES.get(conforming_type) or [])[:]
expressible_as_protocols += (SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.get(conforming_type) or [])[:]
return map(lambda x : 'ExpressibleAs' + x, expressible_as_protocols)
}%
//// Automatically Generated From DeclBuildables.swift.gyb.
//// Do Not Edit Directly!
Expand Down Expand Up @@ -44,9 +51,7 @@ public protocol ${kind}ListBuildable: SyntaxListBuildable {

% buildable_type = kind + 'Buildable'
% expressible_as_type = 'ExpressibleAs' + buildable_type
% expressible_as_protocols = SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES.get(buildable_type) or []
% expressible_as_protocols += SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.get(buildable_type) or []
% expressible_as_protocols = map(lambda x : 'ExpressibleAs' + x, expressible_as_protocols)
% expressible_as_protocols = get_expressible_as_conformances(buildable_type)
% if expressible_as_protocols:
public protocol ${expressible_as_type}: ${', '.join(expressible_as_protocols)} {
% else:
Expand Down Expand Up @@ -140,15 +145,20 @@ public struct ${node.syntax_kind}: ${node.base_kind}Buildable {
% child_token = SYNTAX_TOKEN_MAP.get(child.syntax_kind)
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token(), child.is_optional)
% default_value = syntax_buildable_default_init_value(child, child_token)
% init_parameters.append("%s: ExpressibleAs%s%s" % (child.swift_name, param_type, default_value))
% param_type = param_type if child.is_token() else "ExpressibleAs" + param_type
% init_parameters.append("%s: %s%s" % (child.swift_name, param_type, default_value))
% end
${',\n '.join(init_parameters)}
) {
% for child in node.children:
% create_method_dot = '?.' if child.is_optional else '.'
% child_token = SYNTAX_TOKEN_MAP.get(child.syntax_kind)
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token())
% if param_type is 'TokenSyntax':
self.${child.swift_name} = ${child.swift_name}
% else:
self.${child.swift_name} = ${child.swift_name}${create_method_dot}create${param_type}()
% end
% end
}

Expand Down Expand Up @@ -204,11 +214,16 @@ public struct ${node.syntax_kind}: ${node.base_kind}Buildable {
public struct ${node.syntax_kind}: SyntaxBuildable {
let elements: [${element_type}]

% param_type = element_type if node.is_token() else 'ExpressibleAs' + element_type
/// Creates a `${node.syntax_kind}` with the provided list of elements.
/// - Parameters:
/// - elements: A list of `ExpressibleAs${element_type}`
public init(_ elements: [ExpressibleAs${element_type}]) {
public init(_ elements: [${param_type}]) {
% if node.is_token():
self.elements = elements
% else:
self.elements = elements.map { $0.create${element_type}() }
% end
}

public func build${node.syntax_kind}(format: Format) -> ${node.syntax_kind}Syntax {
Expand Down Expand Up @@ -239,9 +254,7 @@ public struct ${node.syntax_kind}: SyntaxBuildable {
% end
% if node.is_buildable() or node.is_syntax_collection():
% expressible_as_type = 'ExpressibleAs' + node.syntax_kind
% expressible_as_protocols = SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES.get(node.syntax_kind) or []
% expressible_as_protocols += SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.get(node.syntax_kind) or []
% expressible_as_protocols = map(lambda x : 'ExpressibleAs' + x, expressible_as_protocols)
% expressible_as_protocols = get_expressible_as_conformances(node.syntax_kind)
% if expressible_as_protocols:
public protocol ${expressible_as_type}: ${', '.join(expressible_as_protocols)} {
% else:
Expand All @@ -258,36 +271,36 @@ extension ${node.syntax_kind}: ${expressible_as_type} {

% end
% end
public protocol ExpressibleAsTokenSyntax {
func createTokenSyntax() -> TokenSyntax
% expressible_as_protocols = get_expressible_as_conformances('TokenSyntax')
% if expressible_as_protocols:
extension TokenSyntax: ${', '.join(expressible_as_protocols)} {
}
% end

extension TokenSyntax: ExpressibleAsTokenSyntax {
public func createTokenSyntax() -> TokenSyntax {
self
// MARK: - Syntax Collection buildable expressible as conformances

% for protocol, conformances in SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES.items():
% for conformance in conformances:
% extension_protocol = protocol if protocol is 'TokenSyntax' else 'ExpressibleAs' + protocol
extension ${extension_protocol} {
public func create${conformance}() -> ${conformance} {
${conformance}([self])
}
}

% end
% end
// MARK: - Syntax buildable expressible as conformances

% for protocol, conformances in SYNTAX_COLLECTION_EXPRESSIBLE_AS_CONFORMANCES.items():
% for conformance in conformances:
extension ExpressibleAs${protocol} {
public func create${conformance}() -> ${conformance} {
${conformance}([self])
}
}

% end
% end
% for protocol, conformances in SYNTAX_BUILDABLE_EXPRESSIBLE_AS_CONFORMANCES.items():
% for conformance in conformances:
% node = NODE_MAP.get(conformance)
% if node and node.children:
% non_defaulted_params = filter(lambda child : syntax_buildable_default_init_value(child, SYNTAX_TOKEN_MAP.get(child.syntax_kind)) == "", node.children)
% assert len(non_defaulted_params) == 1, "ExpressibleAs conformances expects the conforming type to have an initializer with a single non-optional child"
% param = non_defaulted_params[0].swift_name
extension ExpressibleAs${protocol} {
% extension_protocol = protocol if protocol is 'TokenSyntax' else 'ExpressibleAs' + protocol
extension ${extension_protocol} {
public func create${conformance}() -> ${conformance} {
${conformance}(${param}: self)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ extension ${node.syntax_kind} {
% else:
% # When type is not handled above, use default value
% param_type = syntax_buildable_child_type(child.type_name, child.syntax_kind, child.is_token(), child.is_optional)
% param_type = param_type if child.is_token() else "ExpressibleAs" + param_type
% default_value = syntax_buildable_default_init_value(child, child_token)
% init_parameters.append("%s: ExpressibleAs%s%s" % (child.swift_name, param_type, default_value))
% init_parameters.append("%s: %s%s" % (child.swift_name, param_type, default_value))
% end
% end
${',\n '.join(init_parameters + init_result_builder_parameters)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
//===----------------------------------------------------------------------===//


import Foundation
import SwiftSyntax

extension FunctionCallExpr {
public init(
_ calledExpression: ExpressibleAsIdentifierExpr,
leftParen: ExpressibleAsTokenSyntax? = nil,
rightParen: ExpressibleAsTokenSyntax? = nil,
leftParen: TokenSyntax? = nil,
rightParen: TokenSyntax? = nil,
trailingClosure: ExpressibleAsClosureExpr? = nil,
@TupleExprElementListBuilder argumentListBuilder: () -> TupleExprElementList = { .empty },
@MultipleTrailingClosureElementListBuilder additionalTrailingClosuresBuilder: () -> MultipleTrailingClosureElementList? = { nil }
Expand Down
11 changes: 8 additions & 3 deletions Sources/SwiftSyntaxBuilder/ResultBuilders.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ import SwiftSyntax
@resultBuilder
public struct ${node.syntax_kind}Builder {
% element_type = syntax_buildable_child_type(node.collection_element_type, node.collection_element, node.is_token())

% component_type = element_type if node.is_token() else 'ExpressibleAs' + element_type

/// The type of individual statement expressions in the transformed function,
/// which defaults to Component if buildExpression() is not provided.
public typealias Expression = ExpressibleAs${element_type}
public typealias Expression = ${component_type}

/// The type of a partial result, which will be carried through all of the
/// build methods.
public typealias Component = [ExpressibleAs${element_type}]
public typealias Component = [${component_type}]

/// The type of the final returned result, which defaults to Component if
/// buildFinalResult() is not provided.
Expand Down Expand Up @@ -84,7 +85,11 @@ public struct ${node.syntax_kind}Builder {
/// If declared, this will be called on the partial result from the outermost
/// block statement to produce the final returned result.
public static func buildFinalResult(_ component: Component) -> FinalResult {
% if node.is_token():
.init(component)
% else:
.init(component.map { $0.create${element_type}() })
% end
}
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftSyntaxBuilder/Tokens.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import SwiftSyntax

/// Namespace for commonly used tokens with default trivia.
public extension ExpressibleAsTokenSyntax where Self == TokenSyntax {
public extension TokenSyntax {
% for token in SYNTAX_TOKENS:
% if token.is_keyword:
/// The `${token.text.encode('utf-8').decode('unicode_escape')}` keyword
Expand Down
Loading