Skip to content

Make String conform to ExpressibleAs protocols #335

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
16 changes: 16 additions & 0 deletions Sources/SwiftSyntaxBuilder/Buildables.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,20 @@ extension ExpressibleAs${protocol} {
}

% end
% if 'TypeAnnotation' in conformances:
extension ExpressibleAs${protocol} {
public func createTypeAnnotation() -> TypeAnnotation {
TypeAnnotation(type: self)
}
}

% end
% if 'TypeExpr' in conformances:
extension ExpressibleAs${protocol} {
public func createTypeExpr() -> TypeExpr {
TypeExpr(type: self)
}
}

% end
% end
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import Foundation

extension FunctionCallExpr {
public init(
_ calledExpression: IdentifierExpr,
_ calledExpression: ExpressibleAsIdentifierExpr,
leftParen: ExpressibleAsTokenSyntax? = nil,
rightParen: ExpressibleAsTokenSyntax? = nil,
trailingClosure: ExpressibleAsClosureExpr? = nil,
@TupleExprElementListBuilder argumentListBuilder: () -> TupleExprElementList = { .empty },
@MultipleTrailingClosureElementListBuilder additionalTrailingClosuresBuilder: () -> MultipleTrailingClosureElementList? = { nil }
) {
self.init(
calledExpression: calledExpression,
calledExpression: calledExpression.createIdentifierExpr(),
leftParen: leftParen,
argumentList: argumentListBuilder(),
rightParen: rightParen,
Expand Down
49 changes: 49 additions & 0 deletions Sources/SwiftSyntaxBuilder/StringConvenienceInitializers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 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
//
//===----------------------------------------------------------------------===//

extension String: ExpressibleAsSimpleTypeIdentifier {
public func createSimpleTypeIdentifier() -> SimpleTypeIdentifier {
SimpleTypeIdentifier(self)
}
}

extension String: ExpressibleAsIdentifierPattern {
public func createIdentifierPattern() -> IdentifierPattern {
IdentifierPattern(self)
}
}

extension String: ExpressibleAsIdentifierExpr {
public func createIdentifierExpr() -> IdentifierExpr {
IdentifierExpr(self)
}
}

extension String: ExpressibleAsStringLiteralExpr {
public func createStringLiteralExpr() -> StringLiteralExpr {
StringLiteralExpr(self)
}
}

/// Default conformance to `ExpressibleByTypeBuildable`
extension String {
public func createTypeBuildable() -> TypeBuildable {
SimpleTypeIdentifier(self)
}
}

/// Default conformance to `ExpressibleByPatternBuildable`
extension String {
public func createPatternBuildable() -> PatternBuildable {
IdentifierPattern(self)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
import SwiftSyntax

extension VariableDecl {
public init(_ letOrVarKeyword: TokenSyntax, name: String, type: String) {
public init(_ letOrVarKeyword: TokenSyntax,
name: ExpressibleAsIdentifierPattern,
type: ExpressibleAsTypeAnnotation) {
self.init(letOrVarKeyword: letOrVarKeyword, bindingsBuilder: {
PatternBinding(pattern: IdentifierPattern(name),
typeAnnotation: TypeAnnotation(type))
PatternBinding(pattern: name.createIdentifierPattern(),
typeAnnotation: type.createTypeAnnotation())
})
}
}
16 changes: 14 additions & 2 deletions Sources/SwiftSyntaxBuilder/gyb_generated/Buildables.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9548,7 +9548,7 @@ public struct SimpleTypeIdentifier: TypeBuildable {
}
}

public protocol ExpressibleAsSimpleTypeIdentifier {
public protocol ExpressibleAsSimpleTypeIdentifier: ExpressibleAsTypeAnnotation, ExpressibleAsTypeBuildable, ExpressibleAsTypeExpr {
func createSimpleTypeIdentifier() -> SimpleTypeIdentifier
}

Expand Down Expand Up @@ -10624,7 +10624,7 @@ public struct IdentifierPattern: PatternBuildable {
}
}

public protocol ExpressibleAsIdentifierPattern {
public protocol ExpressibleAsIdentifierPattern: ExpressibleAsPatternBuildable {
func createIdentifierPattern() -> IdentifierPattern
}

Expand Down Expand Up @@ -11450,3 +11450,15 @@ extension ExpressibleAsExprList {
}
}

extension ExpressibleAsSimpleTypeIdentifier {
public func createTypeAnnotation() -> TypeAnnotation {
TypeAnnotation(type: self)
}
}

extension ExpressibleAsSimpleTypeIdentifier {
public func createTypeExpr() -> TypeExpr {
TypeExpr(type: self)
}
}

2 changes: 1 addition & 1 deletion Tests/SwiftSyntaxBuilderTest/EnumCaseElementTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class EnumCaseElementTests: XCTestCase {

let initializerClause = InitializerClause(value: stringLiteralExpr)

let enumCase = EnumCaseElement(identifier: SyntaxFactory.makeIdentifier("TestEnum"),
let enumCase = EnumCaseElement(identifier: "TestEnum",
rawValue: initializerClause)

let test = enumCase.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ final class ExpressibleBuildablesTests: XCTestCase {

// We use `MemberDeclListItem` to ensure and show we can combine it with `ExpressibleAsMemberDeclListItem`
MemberDeclListItem(decl: VariableDecl(letOrVarKeyword: TokenSyntax.let, bindingsBuilder: {
PatternBinding(pattern: IdentifierPattern(identifier: TokenSyntax.identifier("myOtherLet")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("String")))
PatternBinding(pattern: "myOtherLet", typeAnnotation: "String")
})
)

Expand Down Expand Up @@ -48,7 +47,7 @@ final class ExpressibleBuildablesTests: XCTestCase {

func testExpressibleAsSwitchStmt() {
let versions = [("version_1", "1.0.0"), ("version_2", "2.0.0"), ("version_3", "3.0.0"), ("version_3_1", "3.1.0")]
let expression = IdentifierExpr(identifier: SyntaxFactory.makeIdentifier("version"))
let expression = IdentifierExpr("version")

let switchStmt = SwitchStmt(labelName: nil,
expression: expression,
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftSyntaxBuilderTest/FunctionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ final class FunctionTests: XCTestCase {
let leadingTrivia = Trivia.garbageText("")

let input = ParameterClause(parameterListBuilder: {
FunctionParameter(firstName: TokenSyntax.wildcard, secondName: TokenSyntax.identifier("n"), colon: TokenSyntax.colon, type: SimpleTypeIdentifier("Int"), attributesBuilder: {})
FunctionParameter(firstName: TokenSyntax.wildcard, secondName: TokenSyntax.identifier("n"), colon: TokenSyntax.colon, type: "Int", attributesBuilder: {})
})

let ifCodeBlock = CodeBlock(statementsBuilder: {
ReturnStmt(expression: IntegerLiteralExpr(digits: "n"))
})

let signature = FunctionSignature(input: input, output: ReturnClause(returnType: SimpleTypeIdentifier("Int")))
let signature = FunctionSignature(input: input, output: ReturnClause(returnType: "Int"))


let codeBlock = CodeBlock(statementsBuilder: {
Expand Down
5 changes: 3 additions & 2 deletions Tests/SwiftSyntaxBuilderTest/IdentifierExprTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final class IdentifierExprTests: XCTestCase {
func testStringLiteral() {
let leadingTrivia = Trivia.garbageText("␣")

let testCases: [UInt: (IdentifierExpr, String)] = [
let testCases: [UInt: (ExpressibleAsIdentifierExpr, String)] = [
#line: (IdentifierExpr(identifier: .identifier("Test")), "␣Test"),
#line: (IdentifierExpr(stringLiteral: "Test"), "␣Test"),
#line: (IdentifierExpr("Test"), "␣Test"),
Expand All @@ -15,7 +15,8 @@ final class IdentifierExprTests: XCTestCase {

for (line, testCase) in testCases {
let (builder, expected) = testCase
let syntax = builder.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
let identifierExpr = builder.createIdentifierExpr()
let syntax = identifierExpr.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)

var text = ""
syntax.write(to: &text)
Expand Down
5 changes: 3 additions & 2 deletions Tests/SwiftSyntaxBuilderTest/IdentifierPatternTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final class IdentifierPatternTests: XCTestCase {
func testStringLiteral() {
let leadingTrivia = Trivia.garbageText("␣")

let testCases: [UInt: (IdentifierPattern, String)] = [
let testCases: [UInt: (ExpressibleAsIdentifierPattern, String)] = [
#line: (IdentifierPattern(identifier: .identifier("Test")), "␣Test"),
#line: (IdentifierPattern(stringLiteral: "Test"), "␣Test"),
#line: (IdentifierPattern("Test"), "␣Test"),
Expand All @@ -15,7 +15,8 @@ final class IdentifierPatternTests: XCTestCase {

for (line, testCase) in testCases {
let (builder, expected) = testCase
let syntax = builder.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
let identifierPattern = builder.createIdentifierPattern()
let syntax = identifierPattern.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)

var text = ""
syntax.write(to: &text)
Expand Down
26 changes: 26 additions & 0 deletions Tests/SwiftSyntaxBuilderTest/SimpleTypeIdentifierTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import XCTest
import SwiftSyntax
import SwiftSyntaxBuilder

final class SimpleTypeIdentifierTests: XCTestCase {
func testExpressibleAsSimpleTypeIdentifier() {
let leadingTrivia = Trivia.garbageText("␣")

let testCases: [UInt: (ExpressibleAsSimpleTypeIdentifier, String)] = [
#line: (SimpleTypeIdentifier(name: SyntaxFactory.makeIdentifier("Foo")), "␣Foo"),
#line: (SimpleTypeIdentifier("Foo"), "␣Foo"),
#line: ("Foo", "␣Foo")
]

for (line, testCase) in testCases {
let (builder, expected) = testCase
let identifier = builder.createSimpleTypeIdentifier()
let syntax = identifier.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)

var text = ""
syntax.write(to: &text)

XCTAssertEqual(text, expected, line: line)
}
}
}
6 changes: 3 additions & 3 deletions Tests/SwiftSyntaxBuilderTest/StringLiteralTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ final class StringLiteralTests: XCTestCase {

func testStringLiteralConvenienceInitializers() {
let leadingTrivia = Trivia.garbageText("␣")
let testCases: [UInt: (StringLiteralExpr, String)] = [
let testCases: [UInt: (ExpressibleAsStringLiteralExpr, String)] = [
#line: (StringLiteralExpr(""), #"␣"""#),
#line: (StringLiteralExpr("asdf"), #"␣"asdf""#),
#line: ("", #"␣"""#),
Expand All @@ -37,8 +37,8 @@ final class StringLiteralTests: XCTestCase {

for (line, testCase) in testCases {
let (builder, expected) = testCase

let syntax = builder.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
let stringLiteralExpr = builder.createStringLiteralExpr()
let syntax = stringLiteralExpr.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)

var text = ""
syntax.write(to: &text)
Expand Down
4 changes: 2 additions & 2 deletions Tests/SwiftSyntaxBuilderTest/StructTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ final class StructTests: XCTestCase {
if i.isMultiple(of: 2) {
MemberDeclListItem(decl: VariableDecl(letOrVarKeyword: TokenSyntax.let, bindingsBuilder: {
PatternBinding(
pattern: IdentifierPattern(identifier: TokenSyntax.identifier("var\(i)")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("String"))
pattern: IdentifierPattern("var\(i)"),
typeAnnotation: "String"
)
}))
}
Expand Down
7 changes: 5 additions & 2 deletions Tests/SwiftSyntaxBuilderTest/TypeAnnotationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ final class TypeAnnotationTests: XCTestCase {
func testStringLiteral() {
let leadingTrivia = Trivia.garbageText("␣")

let testCases: [UInt: (TypeAnnotation, String)] = [
let testCases: [UInt: (ExpressibleAsTypeAnnotation, String)] = [
#line: (TypeAnnotation(type: "Test"), "␣: Test"),
#line: (TypeAnnotation(type: SimpleTypeIdentifier("Test")), "␣: Test"),
#line: (TypeAnnotation(stringLiteral: "Test"), "␣: Test"),
#line: (TypeAnnotation("Test"), "␣: Test"),
#line: (SimpleTypeIdentifier("Test"), "␣: Test"),
#line: ("Test", "␣: Test")
]

for (line, testCase) in testCases {
let (builder, expected) = testCase
let syntax = builder.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
let typeAnnotation = builder.createTypeAnnotation()
let syntax = typeAnnotation.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)

var text = ""
syntax.write(to: &text)
Expand Down
8 changes: 3 additions & 5 deletions Tests/SwiftSyntaxBuilderTest/VariableTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ final class VariableTests: XCTestCase {
let leadingTrivia = Trivia.garbageText("")

let buildable = VariableDecl(letOrVarKeyword: .let, bindingsBuilder: {
PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("color")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("UIColor")))
PatternBinding(pattern: "color", typeAnnotation: "UIColor")
})

let syntax = buildable.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
Expand All @@ -25,9 +24,8 @@ final class VariableTests: XCTestCase {
let leadingTrivia = Trivia.garbageText("")

let buildable = VariableDecl(letOrVarKeyword: TokenSyntax.var, bindingsBuilder: {
PatternBinding(pattern: IdentifierPattern(identifier: SyntaxFactory.makeIdentifier("number")),
typeAnnotation: TypeAnnotation(type: SimpleTypeIdentifier("Int")),
initializer: InitializerClause(value: IntegerLiteralExpr(digits: TokenSyntax.integerLiteral("123"))))
PatternBinding(pattern: "number", typeAnnotation: "Int",
initializer: InitializerClause(value: IntegerLiteralExpr(digits: "123")))
})

let syntax = buildable.buildSyntax(format: Format(), leadingTrivia: leadingTrivia)
Expand Down