diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Relax-Package.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Relax-Package.xcscheme index 7b27a32..1809d9f 100644 --- a/.swiftpm/xcode/xcshareddata/xcschemes/Relax-Package.xcscheme +++ b/.swiftpm/xcode/xcshareddata/xcschemes/Relax-Package.xcscheme @@ -67,6 +67,16 @@ ReferencedContainer = "container:"> + + + + [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)\")! } """ diff --git a/Sources/RelaxMacros/RelaxMacroDiagnostic.swift b/Sources/RelaxMacros/RelaxMacroDiagnostic.swift new file mode 100644 index 0000000..078dfef --- /dev/null +++ b/Sources/RelaxMacros/RelaxMacroDiagnostic.swift @@ -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) + } +} diff --git a/Tests/RelaxMacrosTests/MacroTests.swift b/Tests/RelaxMacrosTests/MacroTests.swift index b89f331..a281765 100644 --- a/Tests/RelaxMacrosTests/MacroTests.swift +++ b/Tests/RelaxMacrosTests/MacroTests.swift @@ -8,6 +8,7 @@ import SwiftSyntaxMacros import SwiftSyntaxMacrosTestSupport import XCTest +@testable import RelaxMacros #if canImport(RelaxMacros) import RelaxMacros @@ -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 + } }