Skip to content

Commit

Permalink
#35: Add error handling for @apiservice macro
Browse files Browse the repository at this point in the history
  • Loading branch information
tdeleon committed Jan 2, 2024
1 parent ef5284f commit 6c0c553
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 2 deletions.
10 changes: 10 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Relax-Package.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "RelaxMacrosTests"
BuildableName = "RelaxMacrosTests"
BlueprintName = "RelaxMacrosTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
Expand Down
19 changes: 17 additions & 2 deletions Sources/RelaxMacros/APIServiceMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros
import SwiftDiagnostics
import Foundation

public struct APIServiceMacro: ExtensionMacro {
public static func expansion(
Expand All @@ -17,14 +19,27 @@ public struct APIServiceMacro: ExtensionMacro {
conformingTo protocols: [TypeSyntax],
in context: some MacroExpansionContext
) throws -> [ExtensionDeclSyntax] {
guard let arguments = node.arguments?.as(LabeledExprListSyntax.self) else {
guard let urlString = node
.arguments?.as(LabeledExprListSyntax.self)?
.first?.expression.as(StringLiteralExprSyntax.self)?
.segments
.first?.trimmedDescription else {
let error = Diagnostic(node: node, message: RelaxMacroDiagnostic.invalidBaseURL)
context.diagnose(error)
return []
}

// check that the URL will be valid
guard URL(string: urlString) != nil else {
let error = Diagnostic(node: node, message: RelaxMacroDiagnostic.invalidBaseURL)
context.diagnose(error)
return []
}

let decl: DeclSyntax =
"""
extension \(type.trimmed): APIComponent {
static let baseURL: URL = URL(string: \(raw: arguments.trimmedDescription))!
static let baseURL: URL = URL(string: \"\(raw: urlString)\")!
}
"""

Expand Down
25 changes: 25 additions & 0 deletions Sources/RelaxMacros/RelaxMacroDiagnostic.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// RelaxMacroDiagnostic.swift
//
//
// Created by Thomas De Leon on 1/2/24.
//

import SwiftDiagnostics

enum RelaxMacroDiagnostic: String, DiagnosticMessage {
case invalidBaseURL

var severity: DiagnosticSeverity { .error }

var message: String {
switch self {
case .invalidBaseURL:
"The base URL is invalid."
}
}

var diagnosticID: MessageID {
MessageID(domain: "RelaxMacros", id: rawValue)
}
}
21 changes: 21 additions & 0 deletions Tests/RelaxMacrosTests/MacroTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import SwiftSyntaxMacros
import SwiftSyntaxMacrosTestSupport
import XCTest
@testable import RelaxMacros

#if canImport(RelaxMacros)
import RelaxMacros
Expand Down Expand Up @@ -39,4 +40,24 @@ final class MacroTests: XCTestCase {
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}

func testAPIServiceInvalidBaseURL() throws {
#if canImport(RelaxMacros)
assertMacroExpansion(
"""
@APIService("https:// .com")
enum TestService {
}
""",
expandedSource: """
enum TestService {
}
""",
diagnostics: [.init(message: RelaxMacroDiagnostic.invalidBaseURL.message, line: 1, column: 1)],
macros: testMacros
)
#else
throw XCTSkip("macros are only supported when running tests for the host platform")
#endif
}
}

0 comments on commit 6c0c553

Please sign in to comment.