-
Swift Macro - implementIOS/WWDC24 2025. 6. 1. 23:32
1. 패키지 생성
Xcode -> File -> New -> Package 선택 시 Swift macro가 있습니다.

2. 구성 보기
패키지 생성 시 기본적으로 #stringfy 메크로 선언, 구현, 단위 테스트 코드가 존재합니다.

3. 메크로 선언

stringify표현에 사용할 매크로 구현체가 있는 모듈을 #externalMacro로 상세한다.

메크로에 사용될 구현체는 @main으로 프로그램 진입 시점에 선언
@main struct WWDC_MacroPlugin: CompilerPlugin { let providingMacros: [Macro.Type] = [ StringifyMacro.self, SlopeSubsetMacro.self ] }- 플러그인 메커니즘
- 플러그인은 호스트 프로세스와 swift enum을 JSON 직렬화 형식으로 메시지를 주고받음
- Swift 컴파일러가 플러그인에게 명령을 주고 플러그인은 결과를 되돌려줌
- stdin, stdout 파이프를 통해서 주고받는데, 플러그인은 호스트 프로세스 외 stdin는 막혀있음
- 즉 이 부분에서 메크로 구현체가 맵핑되는걸 선언해 줌
4. 메크로 구현체
stringifyMacro 구현부를 ExpressionMacro 타입을 구현하기 때문에 다음과 같은 프로토콜을 상속해서 구현체를 구현해야 한다.
한 단계 깊이 들어가면 FreestandingMacroExpansionSyntax 프로토콜로 parse에 의해 sytanx tree로 구성된 토큰들을 추출할 수 있습니다.
// MARK: - FreestandingMacroExpansionSyntax public protocol FreestandingMacroExpansionSyntax: SyntaxProtocol { /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be `#`. var pound: TokenSyntax { get set } /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be `<identifier>`. var macroName: TokenSyntax { get set } var genericArgumentClause: GenericArgumentClauseSyntax? { get set } /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be `(`. var leftParen: TokenSyntax? { get set } var arguments: LabeledExprListSyntax { get set } /// ### Tokens /// /// For syntax trees generated by the parser, this is guaranteed to be `)`. var rightParen: TokenSyntax? { get set } var trailingClosure: ClosureExprSyntax? { get set } var additionalTrailingClosures: MultipleTrailingClosureElementListSyntax { get set } }5. 메크로 테스트
메크로에 사용하는 테스트 코드는 단위 테스트에 용이하도록 설계되어 있습니다.
assertMacroExpansion를 사용해 테스트하는데 메서드 시그니처는 다음과 같습니다.
func assertMacroExpansion( _ originalSource: String, expandedSource expectedExpandedSource: String, diagnostics: [DiagnosticSpec] = [], macros: [String : any Macro.Type], applyFixIts: [String]? = nil, fixedSource expectedFixedSource: String? = nil, testModuleName: String = "TestModule", testFileName: String = "test.swift", indentationWidth: Trivia = .spaces(4), file: StaticString = #filePath, line: UInt = #line )
다음은 사용법 코드입니다.
import WWDC_MacroMacros let testMacros: [String: Macro.Type] = [ "stringify": StringifyMacro.self, // 메크로 맵핑된 구현체를 dictionary형태로 ] #endif final class WWDC_MacroTests: XCTestCase { func testMacro() throws { #if canImport(WWDC_MacroMacros) assertMacroExpansion( """ #stringify(a + b) // 매크로 표현식 """, expandedSource: """ (a + b, "a + b") // 예상되는 확장 코드 """, macros: testMacros ) #else throw XCTSkip("macros are only supported when running tests for the host platform") #endif } }'IOS > WWDC24' 카테고리의 다른 글
Swift Macro - attach (2) 2025.06.08 Swift Macro - Intro (0) 2025.05.10 [WWDC24] Swift의 성능 살펴보기 (3/3) (0) 2025.02.09 [WWDC24] Swift의 성능 살펴보기 (2 / 3) (0) 2025.02.08 [WWDC24] Swift의 성능 살펴보기 (1 / 3) (0) 2024.12.07 - 플러그인 메커니즘