Last active
October 26, 2018 20:53
-
-
Save alanzeino/7570080089f11ea14a161e4d20c39cdf to your computer and use it in GitHub Desktop.
swiftsyntax simple class/struct gen example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct MockGenType { | |
let name: String | |
let isOptional: Bool | |
init(name: String, isOptional: Bool = false) { | |
self.name = name | |
self.isOptional = isOptional | |
} | |
func libRepresentation(hasDefault: Bool = false) -> OptionalTypeSyntax { | |
return OptionalTypeSyntax { builder in | |
builder.useWrappedType(SimpleTypeIdentifierSyntax { sBuilder in | |
sBuilder.useName(SyntaxFactory.makeIdentifier(name, leadingTrivia: .zero, trailingTrivia: hasDefault ? .spaces(1) : .zero)) | |
}) | |
if isOptional { | |
builder.useQuestionMark(SyntaxFactory.makePostfixQuestionMarkToken()) | |
} | |
} | |
} | |
} | |
struct MockGenFunctionArgument { | |
let name: String | |
let type: MockGenType | |
func libRepresentation(useTrailingComma: Bool) -> FunctionParameterSyntax { | |
return FunctionParameterSyntax { builder in | |
builder.useFirstName(SyntaxFactory.makeIdentifier(name)) | |
builder.useType(type.libRepresentation()) | |
builder.useColon(SyntaxFactory.makeColonToken(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
if useTrailingComma { | |
builder.useTrailingComma(SyntaxFactory.makeCommaToken(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
} | |
} | |
} | |
} | |
struct MockGenFunction { | |
let name: String | |
let arguments: [MockGenFunctionArgument]? | |
let returnType: MockGenType? | |
let hasBody: Bool | |
init(name: String, arguments: [MockGenFunctionArgument]?, returnType: MockGenType? = nil, hasBody: Bool = false) { | |
self.name = name | |
self.arguments = arguments | |
self.returnType = returnType | |
self.hasBody = hasBody | |
} | |
func libRepresentation() -> MemberDeclListItemSyntax { | |
let hasReturnType = returnType != nil | |
return MemberDeclListItemSyntax { builder in | |
builder.useDecl(FunctionDeclSyntax { fBuilder in | |
fBuilder.useIdentifier(SyntaxFactory.makeIdentifier(name)) | |
fBuilder.useFuncKeyword(SyntaxFactory.makeFuncKeyword(leadingTrivia: Trivia(pieces: [.newlines(1), .tabs(1)]), trailingTrivia: .spaces(1))) | |
fBuilder.useSignature(FunctionSignatureSyntax { sBuilder in | |
sBuilder.useInput(ParameterClauseSyntax { pBuilder in | |
if let arguments = arguments { | |
let lastIndex = arguments.count - 1 | |
for i in 0..<arguments.count { | |
let argument = arguments[i] | |
let isLastItem: Bool = i == lastIndex | |
pBuilder.addFunctionParameter(argument.libRepresentation(useTrailingComma: !isLastItem)) | |
} | |
} | |
pBuilder.useLeftParen(SyntaxFactory.makeLeftParenToken()) | |
pBuilder.useRightParen(SyntaxFactory.makeRightParenToken(leadingTrivia: .zero, trailingTrivia: hasReturnType ? .spaces(1) : .zero)) | |
}) | |
if let returnType = returnType { | |
sBuilder.useOutput(ReturnClauseSyntax { rcBuilder in | |
rcBuilder.useReturnType(returnType.libRepresentation()) | |
rcBuilder.useArrow(SyntaxFactory.makeArrowToken(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
}) | |
} | |
}) | |
}) | |
} | |
} | |
} | |
enum MockGenVariableLetOrVar { | |
case letVariable | |
case varVariable | |
func libRepresentation() -> TokenSyntax { | |
switch (self) { | |
case .letVariable: | |
return SyntaxFactory.makeLetKeyword(leadingTrivia: Trivia(pieces: [.newlines(1), .tabs(1)]), | |
trailingTrivia: .spaces(1)) | |
case .varVariable: | |
return SyntaxFactory.makeVarKeyword(leadingTrivia: Trivia(pieces: [.newlines(1), .tabs(1)]), | |
trailingTrivia: .spaces(1)) | |
} | |
} | |
} | |
struct MockGenVariableType { | |
let type: MockGenType | |
let optional: Bool | |
init(type: MockGenType, optional: Bool = false) { | |
self.type = type | |
self.optional = optional | |
} | |
func libRepresentation(hasDefault: Bool) -> TypeAnnotationSyntax { | |
let colon = SyntaxFactory.makeColonToken(leadingTrivia: .zero, | |
trailingTrivia: .spaces(1)) | |
var typeAnnotation: TypeSyntax? | |
if optional { | |
let questionMark = SyntaxFactory.makePostfixQuestionMarkToken(leadingTrivia: .zero, trailingTrivia: hasDefault ? .spaces(1) : .zero) | |
typeAnnotation = SyntaxFactory.makeOptionalType(wrappedType: type.libRepresentation(), | |
questionMark: questionMark) | |
} else { | |
typeAnnotation = type.libRepresentation(hasDefault: hasDefault) | |
} | |
return SyntaxFactory.makeTypeAnnotation(colon: colon, | |
type: typeAnnotation!) | |
} | |
} | |
struct MockGenVariableName { | |
let name: String | |
func libRepresentation() -> IdentifierPatternSyntax { | |
return SyntaxFactory.makeIdentifierPattern(identifier: SyntaxFactory.makeIdentifier(name)) | |
} | |
} | |
struct MockGenInitializedTo { | |
enum MockGenInitializedToType { | |
case variable | |
case function | |
} | |
let type: MockGenInitializedToType | |
let stringRepresentation: String | |
func libRepresentation() -> InitializerClauseSyntax { | |
return InitializerClauseSyntax { icBuilder in | |
icBuilder.useEqual(SyntaxFactory.makeEqualToken(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
switch type { | |
case .variable: | |
icBuilder.useValue(SyntaxFactory.makeIntegerLiteralExpr(digits: SyntaxFactory.makeUnknown(stringRepresentation))) | |
case .function: | |
icBuilder.useValue(FunctionCallExprSyntax { fceBuilder in | |
fceBuilder.useCalledExpression(SyntaxFactory.makeIdentifierExpr(identifier: SyntaxFactory.makeUnknown(stringRepresentation), declNameArguments: nil)) | |
fceBuilder.addFunctionCallArgument(SyntaxFactory.makeBlankFunctionCallArgument()) | |
fceBuilder.useLeftParen(SyntaxFactory.makeLeftParenToken()) | |
fceBuilder.useRightParen(SyntaxFactory.makeRightParenToken()) | |
}) | |
} | |
} | |
} | |
} | |
struct MockGenVariable { | |
let variableName: MockGenVariableName | |
let variableType: MockGenVariableType | |
let letOrVar: MockGenVariableLetOrVar | |
var initializedToDefault: MockGenInitializedTo? | |
init(name: MockGenVariableName, type: MockGenVariableType, letOrVar: MockGenVariableLetOrVar, initializedToDefault: MockGenInitializedTo? = nil) { | |
self.variableName = name | |
self.variableType = type | |
self.letOrVar = letOrVar | |
self.initializedToDefault = initializedToDefault | |
} | |
func libRepresentation() -> MemberDeclListItemSyntax { | |
return MemberDeclListItemSyntax { builder in | |
builder.useDecl(VariableDeclSyntax { vBuilder in | |
vBuilder.useLetOrVarKeyword(letOrVar.libRepresentation()) | |
vBuilder.addPatternBinding(PatternBindingSyntax { pbBuilder in | |
pbBuilder.usePattern(variableName.libRepresentation()) | |
pbBuilder.useTypeAnnotation(variableType.libRepresentation(hasDefault: initializedToDefault != nil)) | |
if let initializedToDefault = initializedToDefault { | |
pbBuilder.useInitializer(initializedToDefault.libRepresentation()) | |
} | |
}) | |
}) | |
} | |
} | |
} | |
struct MockGenStruct { | |
let name: String | |
var functions: [MockGenFunction]? | |
var variables: [MockGenVariable]? | |
var conformsToProtocol: MockGenProtocolConformance? | |
init(name: String, functions: [MockGenFunction]?, variables: [MockGenVariable]?, conformsToProtocol: MockGenProtocolConformance? = nil) { | |
self.name = name | |
self.functions = functions | |
self.variables = variables | |
self.conformsToProtocol = conformsToProtocol | |
} | |
func isEmpty() -> Bool { | |
let functionsCount = functions?.count ?? 0 | |
let variablesCount = variables?.count ?? 0 | |
return functionsCount == 0 && variablesCount == 0 | |
} | |
func libRepresentation() -> StructDeclSyntax { | |
return StructDeclSyntax { sBuilder in | |
sBuilder.useIdentifier(SyntaxFactory.makeIdentifier(name)) | |
sBuilder.useStructKeyword(SyntaxFactory.makeStructKeyword(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
sBuilder.useMembers(MemberDeclBlockSyntax { mBuilder in | |
if let functions = functions { | |
for function in functions { | |
mBuilder.addMemberDeclListItem(function.libRepresentation()) | |
} | |
} | |
if let variables = variables { | |
for variable in variables { | |
mBuilder.addMemberDeclListItem(variable.libRepresentation()) | |
} | |
} | |
mBuilder.useLeftBrace(SyntaxFactory.makeLeftBraceToken(leadingTrivia: .spaces(1), trailingTrivia: .zero)) | |
mBuilder.useRightBrace(SyntaxFactory.makeRightBraceToken(leadingTrivia: isEmpty() ? .spaces(1) : .newlines(1), trailingTrivia: .zero)) | |
}) | |
if let conformsToProtocol = conformsToProtocol { | |
sBuilder.useInheritanceClause(conformsToProtocol.libRepresentation()) | |
} | |
} | |
} | |
} | |
struct MockGenProtocolConformance { | |
let name: String | |
func libRepresentation() -> TypeInheritanceClauseSyntax { | |
return TypeInheritanceClauseSyntax { ticBuilder in | |
ticBuilder.addInheritedType(InheritedTypeSyntax { itBuilder in | |
itBuilder.useTypeName(SyntaxFactory.makeTypeIdentifier(name)) | |
}) | |
ticBuilder.useColon(SyntaxFactory.makeColonToken(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
} | |
} | |
} | |
struct MockGenClass { | |
let name: String | |
var functions: [MockGenFunction]? | |
var variables: [MockGenVariable]? | |
var conformsToProtocol: MockGenProtocolConformance? | |
init(name: String, functions: [MockGenFunction]?, variables: [MockGenVariable]?, conformsToProtocol: MockGenProtocolConformance? = nil) { | |
self.name = name | |
self.functions = functions | |
self.variables = variables | |
self.conformsToProtocol = conformsToProtocol | |
} | |
func isEmpty() -> Bool { | |
let functionsCount = functions?.count ?? 0 | |
let variablesCount = variables?.count ?? 0 | |
return functionsCount == 0 && variablesCount == 0 | |
} | |
func libRepresentation() -> ClassDeclSyntax { | |
return ClassDeclSyntax { cBuilder in | |
cBuilder.useIdentifier(SyntaxFactory.makeIdentifier(name)) | |
cBuilder.useClassKeyword(SyntaxFactory.makeClassKeyword(leadingTrivia: .zero, trailingTrivia: .spaces(1))) | |
cBuilder.useMembers(MemberDeclBlockSyntax { mBuilder in | |
if let functions = functions { | |
for function in functions { | |
mBuilder.addMemberDeclListItem(function.libRepresentation()) | |
} | |
} | |
if let variables = variables { | |
for variable in variables { | |
mBuilder.addMemberDeclListItem(variable.libRepresentation()) | |
} | |
} | |
mBuilder.useLeftBrace(SyntaxFactory.makeLeftBraceToken(leadingTrivia: .spaces(1), trailingTrivia: .zero)) | |
mBuilder.useRightBrace(SyntaxFactory.makeRightBraceToken(leadingTrivia: isEmpty() ? .spaces(1) : .newlines(1), trailingTrivia: .zero)) | |
}) | |
if let conformsToProtocol = conformsToProtocol { | |
cBuilder.useInheritanceClause(conformsToProtocol.libRepresentation()) | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment