Skip to content

Commit

Permalink
Merge pull request #10 from bibbi-team/feat/#8-Wrapper-매크로-구현
Browse files Browse the repository at this point in the history
feat: @wrapper, @DependencyValue(s) 매크로 구현
  • Loading branch information
rlarjsdn3 authored Jun 1, 2024
2 parents 86b384b + 4782d5e commit daeef2e
Show file tree
Hide file tree
Showing 21 changed files with 843 additions and 32 deletions.
72 changes: 72 additions & 0 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
{
"pins" : [
{
"identity" : "combine-schedulers",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/combine-schedulers",
"state" : {
"revision" : "9dc9cbe4bc45c65164fa653a563d8d8db61b09bb",
"version" : "1.0.0"
}
},
{
"identity" : "reactorkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ReactorKit/ReactorKit.git",
"state" : {
"revision" : "8fa33f09c6f6621a2aa536d739956d53b84dd139",
"version" : "3.2.0"
}
},
{
"identity" : "rxswift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ReactiveX/RxSwift.git",
"state" : {
"revision" : "b06a8c8596e4c3e8e7788e08e720e3248563ce6a",
"version" : "6.7.1"
}
},
{
"identity" : "swift-clocks",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-clocks",
"state" : {
"revision" : "a8421d68068d8f45fbceb418fbf22c5dad4afd33",
"version" : "1.0.2"
}
},
{
"identity" : "swift-concurrency-extras",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-concurrency-extras",
"state" : {
"revision" : "bb5059bde9022d69ac516803f4f227d8ac967f71",
"version" : "1.1.0"
}
},
{
"identity" : "swift-dependencies",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/swift-dependencies",
"state" : {
"revision" : "350e1e119babe8525f9bd155b76640a5de270184",
"version" : "1.3.0"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
Expand All @@ -8,6 +62,24 @@
"revision" : "64889f0c732f210a935a0ad7cda38f77f876262d",
"version" : "509.1.1"
}
},
{
"identity" : "weakmaptable",
"kind" : "remoteSourceControl",
"location" : "https://github.com/ReactorKit/WeakMapTable.git",
"state" : {
"revision" : "cb05d64cef2bbf51e85c53adee937df46540a74e",
"version" : "1.2.1"
}
},
{
"identity" : "xctest-dynamic-overlay",
"kind" : "remoteSourceControl",
"location" : "https://github.com/pointfreeco/xctest-dynamic-overlay",
"state" : {
"revision" : "6f30bdba373bbd7fbfe241dddd732651f2fbd1e2",
"version" : "1.1.2"
}
}
],
"version" : 2
Expand Down
25 changes: 15 additions & 10 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,39 +7,44 @@ import CompilerPluginSupport
let package = Package(
name: "Bibbi-Package",
platforms: [
.macOS(.v10_15),
.iOS(.v13)
.iOS(.v15),
.macOS(.v10_15)
],
products: [
.library(
name: "Macros",
targets: ["MacrosInterface"]
),

.executable(
name: "MacrosPlayground",
targets: ["MacrosPlayground"]
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
.package(url: "https://github.com/ReactorKit/ReactorKit.git", from: "3.2.0"),
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.3.0")
],
targets: [
.macro(
name: "MacrosImplementation",
dependencies: [
"MacrosHelper",
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
.product(name: "SwiftDiagnostics", package: "swift-syntax")
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
],
path: "Sources/Macros/Implementation"
),

.target(
name: "MacrosHelper",
path: "Sources/Macros/Helper"
),

.target(
name: "MacrosInterface",
dependencies: [
"MacrosImplementation"
"MacrosImplementation",
.product(name: "ReactorKit", package: "ReactorKit"),
.product(name: "Dependencies", package: "swift-dependencies")
],
path: "Sources/Macros/Interface"
),
Expand All @@ -55,7 +60,7 @@ let package = Package(
.testTarget(
name: "Bibbi-MacroTests",
dependencies: [
"MacrosInterface",
"MacrosImplementation",
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
],
path: "Tests/Macros"
Expand Down
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
<img src="https://github.com/rlarjsdn3/swift-macro-playground/assets/21079970/03ea4a38-951a-450f-9f38-36520b994e18" align="center" width="150" height="150"> </br>

Bibbi Package는 삐삐(Bibbi) 앱을 개발하는 데 유용한 `매크로`가 포함되어 있습니다. 해당 리포지토리는 구현된 매크로의 기본 컨셉과 매크로를 활용한 적용법을 명시하고 있습니다. 매크로 예제 코드는 [Playground](Sources/Macros/Playground)에서 찾아보실 수 있으며, 자세한 사용법은 각 매크로에 `Option`키를 누르면 확인할 수 있습니다. </br>
**Bibbi Package** 삐삐(Bibbi)개발하는 데 유용한 `라이브러리``매크로`가 포함되어 있습니다. 리포지토리는 구현된 매크로의 기본 지식과 활용 방법을 설명하고 있습니다. </br>

아래는 구현된 매크로의 목록을 보여줍니다.
## Featrues

## Table Of Macros
### Macros

* [#URL]()
- [v] [@Codable]()
- [v] [@CodableKey(_:)]()
- [v] [@Deprecated]()
- [v] [@DependencyValue(for:)]()
- [v] [@DependencyValues]()
- [v] [@Wrapper]()

* [@Codable]()
* [@CodableKey]()
* [@Deprecated]()
## Requirements

* iOS 15.0+ / macOS 10.15+
* Swift 5.0+

## ChangeLog

| 버전 | 내용 |
| :----: | :------------------: |
| - | - |
33 changes: 33 additions & 0 deletions Sources/Macros/Helper/Extensions/AttributeListDecl+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// File.swift
//
//
// Created by 김건우 on 6/1/24.
//

import SwiftSyntax

public extension AttributeListSyntax {

/// 특정 속성이 적용되었는지 확인합니다.
///
/// - Parameters:
/// - attributeName: 속성 이름
/// - Returns: 속성이 있으면 true, 없으면 false
///
/// - Author: 김소월
///
func isAttributeApplied(_ attributeName: String) -> Bool {
guard
let _ = self.first(where: { attribute in
attribute
.as(AttributeSyntax.self)?
.attributeName
.as(IdentifierTypeSyntax.self)?
.name.text == attributeName
})
else { return false }
return true
}

}
21 changes: 21 additions & 0 deletions Sources/Macros/Helper/Extensions/String+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// File.swift
//
//
// Created by 김건우 on 6/1/24.
//

import Foundation

public extension String {

/// 문자열의 첫 문자를 대문자로 바꿉니다.
///
/// - Returns: String
/// - Author: 김소월
///
func capitalizeFirstLetter() -> String {
return prefix(1).uppercased() + dropFirst()
}

}
66 changes: 66 additions & 0 deletions Sources/Macros/Helper/Extensions/VariableDecl+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// File.swift
//
//
// Created by 김건우 on 6/1/24.
//

import SwiftSyntax

public extension VariableDeclSyntax {

/// 프로퍼티에 초기값이 있는지 확인합니다.
///
/// - Returns: 초기값이 있으면 true, 없으면 false
/// - Author: 김소월
///
var hasIntializer: Bool {
// 라인 하나에 바인딩 하나
if bindings.count != 1 {
return false
}

let binding = bindings.first
guard
let _ = binding?.initializer?.value
else { return true }
return false
}

/// 저장 프로퍼티인지 확인합니다.
///
/// - Returns: 저장 프로퍼티라면 true, 아니라면 false
/// - Author: 김소월
///
var isStoredProperty: Bool {
// 라인 하나에 바인딩 하나
if bindings.count != 1 {
return false
}

let binding = bindings.first
switch binding?.accessorBlock?.accessors {
case .none:
return true

case let .accessors(accessors):
for accessor in accessors {
switch accessor.accessorSpecifier.tokenKind {
case .keyword(.willSet), .keyword(.didSet):
// willset, didset 옵저버는 저장 프로퍼티
break

default:
return false
}
}

return true

case .getter:
//
return false
}
}

}
38 changes: 38 additions & 0 deletions Sources/Macros/Implementation/Accessor/DependencyValueMacro.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// File.swift
//
//
// Created by 김건우 on 5/31/24.
//

import SwiftSyntax
import SwiftSyntaxBuilder
import SwiftSyntaxMacros

public struct DependencyValueMacro: AccessorMacro {

public static func expansion(
of node: AttributeSyntax,
providingAccessorsOf declaration: some DeclSyntaxProtocol,
in context: some MacroExpansionContext
) throws -> [AccessorDeclSyntax] {
guard
case let .argumentList(arguments) = node.arguments,
let expression = arguments.first?
.expression
else {
throw MacroError.message("유효하지 않은 인자입니다.")
}

return [
"""
get { self[\(expression)] }
""",
"""
set { self[\(expression)] = newValue }
"""
]
}

}

2 changes: 1 addition & 1 deletion Sources/Macros/Implementation/Complex/CodableMacro.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension CodableMacro: MemberMacro {
guard
let structDecl = declaration.as(StructDeclSyntax.self)
else {
throw MacroError.message("해당 매크로는 Struct에만 적용할 수 있습니다.")
throw MacroError.message(" 매크로는 Struct에만 적용할 수 있습니다.")
}

let memberList = structDecl.memberBlock.members
Expand Down
Loading

0 comments on commit daeef2e

Please sign in to comment.