-
Notifications
You must be signed in to change notification settings - Fork 23
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
21acdcb
commit 274973c
Showing
17 changed files
with
160 additions
and
108 deletions.
There are no files selected for viewing
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
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
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
This file was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import SwiftSyntax | ||
|
||
extension String { | ||
var withoutQuotes: String { | ||
filter { $0 != "\"" } | ||
} | ||
|
||
var inQuotes: String { | ||
"\"\(self)\"" | ||
} | ||
|
||
// Need this since `capitalized` lowercases everything else. | ||
var capitalizeFirst: String { | ||
prefix(1).capitalized + dropFirst() | ||
} | ||
} |
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
File renamed without changes.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import SwiftSyntax | ||
import SwiftSyntaxMacros | ||
|
||
public struct APIRoutesMacro: PeerMacro, ExtensionMacro { | ||
public static func expansion( | ||
of node: SwiftSyntax.AttributeSyntax, | ||
attachedTo declaration: some SwiftSyntax.DeclGroupSyntax, | ||
providingExtensionsOf type: some SwiftSyntax.TypeSyntaxProtocol, | ||
conformingTo protocols: [SwiftSyntax.TypeSyntax], | ||
in context: some SwiftSyntaxMacros.MacroExpansionContext | ||
) throws -> [SwiftSyntax.ExtensionDeclSyntax] { | ||
guard let type = declaration.as(ProtocolDeclSyntax.self) else { | ||
throw PapyrusPluginError("@APIRoutes can only be applied to protocols.") | ||
} | ||
|
||
return try [ | ||
ExtensionDeclSyntax( | ||
.init(stringLiteral: type.createRoutesExtension()) | ||
) | ||
] | ||
} | ||
|
||
public static func expansion(of node: AttributeSyntax, | ||
providingPeersOf declaration: some DeclSyntaxProtocol, | ||
in context: some MacroExpansionContext) throws -> [DeclSyntax] { | ||
// try handleError { | ||
// guard let type = declaration.as(ProtocolDeclSyntax.self) else { | ||
// throw PapyrusPluginError("@APIRoutes can only be applied to protocols.") | ||
// } | ||
// | ||
// let name = node.firstArgument ?? "\(type.typeName)Live" | ||
// return try [ | ||
// type.createAPI(named: name), | ||
// type.createRegistry(), | ||
// ] | ||
// } | ||
[] | ||
} | ||
} | ||
|
||
extension ProtocolDeclSyntax { | ||
func createRoutesExtension() throws -> String { | ||
""" | ||
\(access)extension \(protocolName) where Self: PapyrusRouter { | ||
func useAPI(_ api: (any \(protocolName)).Type) { | ||
\(protocolName)Registry.register(api: self, router: self) | ||
} | ||
} | ||
""" | ||
} | ||
|
||
func createRegistry() throws -> String { | ||
""" | ||
private enum \(protocolName)Registry { | ||
static func register(api: \(protocolName), router: PapyrusRouter) { | ||
// TODO | ||
} | ||
} | ||
""" | ||
} | ||
} |
File renamed without changes.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import SwiftSyntax | ||
import SwiftSyntaxMacros | ||
|
||
public struct MockMacro: PeerMacro { | ||
public static func expansion( | ||
of node: AttributeSyntax, | ||
providingPeersOf declaration: some DeclSyntaxProtocol, | ||
in context: some MacroExpansionContext | ||
) throws -> [DeclSyntax] { | ||
guard let proto = declaration.as(ProtocolDeclSyntax.self) else { | ||
throw PapyrusPluginError("@Mock can only be applied to protocols.") | ||
} | ||
|
||
return [ | ||
try proto | ||
.mockService(named: "\(proto.protocolName)\(node.attributeName)") | ||
.declSyntax() | ||
] | ||
} | ||
} | ||
|
||
extension ProtocolDeclSyntax { | ||
fileprivate func mockService(named mockName: String) throws -> Declaration { | ||
try Declaration("\(access)final class \(mockName): \(protocolName), @unchecked Sendable") { | ||
"private let notMockedError: Error" | ||
"private var mocks: [String: Any]" | ||
|
||
Declaration("\(access)init(notMockedError: Error = PapyrusError(\"Not mocked\"))") { | ||
"self.notMockedError = notMockedError" | ||
"mocks = [:]" | ||
} | ||
|
||
for function in functions { | ||
try function.mockEndpointFunction(access: access) | ||
|
||
function.mockerFunction(access: access) | ||
} | ||
} | ||
} | ||
} | ||
|
||
extension FunctionDeclSyntax { | ||
fileprivate func mockEndpointFunction(access: String) throws -> Declaration { | ||
guard effects == ["async", "throws"] else { | ||
throw PapyrusPluginError("Function signature must have `async throws`.") | ||
} | ||
|
||
return Declaration("\(access)func \(functionName)\(signature)") { | ||
Declaration("guard let mocker = mocks[\(functionName.inQuotes)] as? \(mockClosureType) else") { | ||
"throw notMockedError" | ||
} | ||
|
||
"" | ||
|
||
let mockerArguments = parameters.map(\.name).joined(separator: ", ") | ||
"return try await mocker(\(mockerArguments))" | ||
} | ||
} | ||
|
||
fileprivate func mockerFunction(access: String) -> Declaration { | ||
Declaration("\(access)func mock\(functionName.capitalizeFirst)(mock: @escaping \(mockClosureType))") { | ||
"mocks[\(functionName.inQuotes)] = mock" | ||
} | ||
} | ||
|
||
private var mockClosureType: String { | ||
let parameterTypes = parameters.map(\.typeName).joined(separator: ", ") | ||
let returnType = signature.returnClause?.type.trimmedDescription ?? "Void" | ||
return "(\(parameterTypes)) async throws -> \(returnType)" | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
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
This file was deleted.
Oops, something went wrong.