Skip to content

Commit 74e6a67

Browse files
authored
refactor!: migrated to extension macro (#21)
BREAKING CHANGE: use `MemberInit` macro for memberwise initializer(s)
1 parent 72389d9 commit 74e6a67

File tree

85 files changed

+1776
-958
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+1776
-958
lines changed

.github/workflows/main.yml

Lines changed: 72 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,54 @@ concurrency:
2323
cancel-in-progress: true
2424

2525
jobs:
26-
analyze:
27-
name: Analyze
28-
if: github.event_name != 'workflow_dispatch'
29-
uses: SwiftyLab/ci/.github/workflows/analyze.yml@main
30-
permissions:
31-
actions: read
32-
contents: read
33-
security-events: write
34-
with:
35-
matrix: >
36-
{
37-
"include": [
38-
{
39-
"os": "ubuntu-latest",
40-
"language": "swift",
41-
"swift": "5.9"
42-
},
43-
{
44-
"os": "macos-13",
45-
"language": "swift",
46-
"xcode": "15-beta"
47-
}
48-
]
49-
}
26+
build:
27+
name: Build on ${{ matrix.os }}
28+
runs-on: ${{ matrix.os }}
29+
strategy:
30+
matrix:
31+
include:
32+
- os: ubuntu-latest
33+
swift: latest
34+
- os: macos-13
35+
xcode: 15-beta
36+
37+
steps:
38+
- name: Checkout repository
39+
uses: actions/checkout@v3
40+
41+
- name: Setup repository
42+
uses: SwiftyLab/ci/actions/setup@main
43+
with:
44+
swift: ${{ matrix.swift }}
45+
xcode: ${{ matrix.xcode }}
46+
47+
- name: Build package products
48+
run: swift build --build-tests
49+
50+
# analyze:
51+
# name: Analyze
52+
# if: github.event_name != 'workflow_dispatch'
53+
# uses: SwiftyLab/ci/.github/workflows/analyze.yml@main
54+
# permissions:
55+
# actions: read
56+
# contents: read
57+
# security-events: write
58+
# with:
59+
# matrix: >
60+
# {
61+
# "include": [
62+
# {
63+
# "os": "ubuntu-latest",
64+
# "language": "swift",
65+
# "swift": "latest"
66+
# },
67+
# {
68+
# "os": "macos-13",
69+
# "language": "swift",
70+
# "xcode": "15-beta"
71+
# }
72+
# ]
73+
# }
5074

5175
# spell-check:
5276
# name: Run spell check
@@ -60,24 +84,24 @@ jobs:
6084
# with:
6185
# config_path: .github/config/spellcheck.yml
6286

63-
swift-package-test:
64-
name: Swift Package
65-
uses: SwiftyLab/ci/.github/workflows/swift-package.yml@main
66-
secrets: inherit
67-
with:
68-
matrix: >
69-
{
70-
"include": [
71-
{
72-
"os": "ubuntu-latest",
73-
"swift": "5.9"
74-
},
75-
{
76-
"os": ""macos-13",
77-
"xcode": "15-beta"
78-
}
79-
]
80-
}
87+
# swift-package-test:
88+
# name: Swift Package
89+
# uses: SwiftyLab/ci/.github/workflows/swift-package.yml@main
90+
# secrets: inherit
91+
# with:
92+
# matrix: >
93+
# {
94+
# "include": [
95+
# {
96+
# "os": "ubuntu-latest",
97+
# "swift": "5.9"
98+
# },
99+
# {
100+
# "os": ""macos-13",
101+
# "xcode": "15-beta"
102+
# }
103+
# ]
104+
# }
81105
# {
82106
# "os": "windows-latest",
83107
# "swift": "5.9"
@@ -86,7 +110,8 @@ jobs:
86110
ci:
87111
name: CI
88112
if: github.event_name == 'push'
89-
needs: [analyze, swift-package-test]
113+
needs: build
114+
# needs: [analyze, swift-package-test]
90115
uses: SwiftyLab/ci/.github/workflows/ci.yml@main
91116

92117
cd:
@@ -96,10 +121,11 @@ jobs:
96121
(always() &&
97122
github.event_name == 'workflow_dispatch' &&
98123
github.event.inputs.release == 'true' &&
99-
needs.swift-package-test.result == 'success' &&
100124
(needs.ci.result == 'success' || needs.ci.result == 'skipped') &&
101-
(needs.analyze.result == 'success' || needs.analyze.result == 'skipped'))
102-
needs: [analyze, swift-package-test, ci]
125+
(needs.build.result == 'success' || needs.build.result == 'skipped'))
126+
# needs.swift-package-test.result == 'success' &&
127+
needs: [build, ci]
128+
# needs: [analyze, swift-package-test, ci]
103129
uses: SwiftyLab/ci/.github/workflows/cd.yml@main
104130
with:
105131
version: ${{ github.event.inputs.version }}

.swift-format

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"version": 1,
3+
"lineLength": 80,
4+
"indentation": {
5+
"spaces": 4
6+
},
7+
"maximumBlankLines": 1,
8+
"respectsExistingLineBreaks": true,
9+
"indentConditionalCompilationBlocks": false,
10+
"rules": {
11+
"AllPublicDeclarationsHaveDocumentation": true,
12+
"NeverForceUnwrap": true,
13+
"NeverUseForceTry": true,
14+
"NoAccessLevelOnExtensionDeclaration": false,
15+
"OrderedImports": true,
16+
"ValidateDocumentationComments": true
17+
}
18+
}

Package.swift

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,6 @@
33
import PackageDescription
44
import CompilerPluginSupport
55

6-
let macroDeps: [Target.Dependency] = [
7-
.product(name: "SwiftSyntax", package: "swift-syntax"),
8-
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
9-
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
10-
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
11-
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
12-
.product(name: "OrderedCollections", package: "swift-collections"),
13-
]
14-
15-
let testDeps: [Target.Dependency] = [
16-
"CodableMacroPlugin", "MetaCodable",
17-
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
18-
]
19-
206
let package = Package(
217
name: "MetaCodable",
228
platforms: [
@@ -32,11 +18,28 @@ let package = Package(
3218
dependencies: [
3319
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0"),
3420
.package(url: "https://github.com/apple/swift-collections.git", from: "1.0.4"),
21+
.package(url: "https://github.com/apple/swift-format", from: "509.0.0"),
3522
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"),
3623
],
3724
targets: [
38-
.macro(name: "CodableMacroPlugin", dependencies: macroDeps),
25+
.macro(
26+
name: "CodableMacroPlugin",
27+
dependencies: [
28+
.product(name: "SwiftSyntax", package: "swift-syntax"),
29+
.product(name: "SwiftDiagnostics", package: "swift-syntax"),
30+
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
31+
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
32+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
33+
.product(name: "OrderedCollections", package: "swift-collections"),
34+
]
35+
),
3936
.target(name: "MetaCodable", dependencies: ["CodableMacroPlugin"]),
40-
.testTarget(name: "MetaCodableTests", dependencies: testDeps),
37+
.testTarget(
38+
name: "MetaCodableTests",
39+
dependencies: [
40+
"CodableMacroPlugin", "MetaCodable",
41+
.product(name: "SwiftSyntaxMacrosTestSupport", package: "swift-syntax"),
42+
]
43+
),
4144
]
4245
)

README.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ Supercharge `Swift`'s `Codable` implementations with macros.
2121
- Allows to create flattened model for nested `CodingKey` values with ``CodedAt(_:)`` and ``CodedIn(_:)``.
2222
- Allows to create composition of multiple `Codable` types with ``CodedAt(_:)`` passing no arguments.
2323
- Allows to provide default value in case of decoding failures with ``Default(_:)``.
24-
- Generates member-wise initializer(s) considering the above default value syntax as well.
2524
- Allows to create custom decoding/encoding strategies with ``HelperCoder`` and using them with ``CodedBy(_:)``. i.e. ``LossySequenceCoder`` etc.
2625
- Allows to ignore specific properties from decoding/encoding with ``IgnoreCoding()``, ``IgnoreDecoding()`` and ``@IgnoreEncoding()``.
2726
- Allows to use camel-case names for variables according to [Swift API Design Guidelines](https://www.swift.org/documentation/api-design-guidelines/#general-conventions), while enabling a type to work with different case style keys with ``CodingKeys(_:)``.
@@ -185,9 +184,9 @@ struct Coordinate {
185184
</details>
186185

187186
<details>
188-
<summary>Provide default value in case of decoding failures and member-wise initializer(s) generated considers these default values.</summary>
187+
<summary>Provide default value in case of decoding failures.</summary>
189188

190-
Instead of throwing error in case of missing data or type mismatch, you can provide a default value that will be assigned in this case. The memberwise initializer generated also uses this default value for the field. The following definition with `MetaCodable`:
189+
Instead of throwing error in case of missing data or type mismatch, you can provide a default value that will be assigned in this case. The following definition with `MetaCodable`:
191190

192191
```swift
193192
@Codable
@@ -197,7 +196,20 @@ struct CodableData {
197196
}
198197
```
199198

200-
will not throw any error when empty JSON(`{}`) or JSON with type mismatch(`{ "field": 5 }`) is provided. The default value will be assigned in such case. Also, the memberwise initializer generated will look like this:
199+
will not throw any error when empty JSON(`{}`) or JSON with type mismatch(`{ "field": 5 }`) is provided. The default value will be assigned in such case.
200+
201+
Also, memberwise initializer can be generated that uses this default value for the field.
202+
203+
```swift
204+
@Codable
205+
@MemberInit
206+
struct CodableData {
207+
@Default("some")
208+
let field: String
209+
}
210+
```
211+
212+
The memberwise initializer generated will look like this:
201213

202214
```swift
203215
init(field: String = "some") {

Sources/CodableMacroPlugin/Attributes/AttributableDeclSyntax.swift

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ extension SyntaxProtocol {
3232
let declaration = declaration as? AttributableDeclSyntax
3333
else { return [] }
3434

35-
return declaration.attributes?.compactMap { attribute in
35+
return declaration.attributes.compactMap { attribute in
3636
guard case .attribute(let attribute) = attribute else { return nil }
3737
return type.init(from: attribute)
38-
} ?? []
38+
}
3939
}
4040
}
4141

@@ -45,12 +45,12 @@ extension SyntaxProtocol {
4545
/// is for this attribute and perform validation of this attribute usage.
4646
protocol AttributableDeclSyntax: DeclSyntaxProtocol {
4747
/// The list of attributes attached to this declaration.
48-
var attributes: AttributeListSyntax? { get }
48+
var attributes: AttributeListSyntax { get }
4949
}
5050

5151
extension AccessorDeclSyntax: AttributableDeclSyntax {}
5252
extension ActorDeclSyntax: AttributableDeclSyntax {}
53-
extension AssociatedtypeDeclSyntax: AttributableDeclSyntax {}
53+
extension AssociatedTypeDeclSyntax: AttributableDeclSyntax {}
5454
extension ClassDeclSyntax: AttributableDeclSyntax {}
5555
extension DeinitializerDeclSyntax: AttributableDeclSyntax {}
5656
extension EditorPlaceholderDeclSyntax: AttributableDeclSyntax {}
@@ -63,10 +63,9 @@ extension InitializerDeclSyntax: AttributableDeclSyntax {}
6363
extension MacroDeclSyntax: AttributableDeclSyntax {}
6464
extension MacroExpansionDeclSyntax: AttributableDeclSyntax {}
6565
extension MissingDeclSyntax: AttributableDeclSyntax {}
66-
extension OperatorDeclSyntax: AttributableDeclSyntax {}
6766
extension PrecedenceGroupDeclSyntax: AttributableDeclSyntax {}
6867
extension ProtocolDeclSyntax: AttributableDeclSyntax {}
6968
extension StructDeclSyntax: AttributableDeclSyntax {}
7069
extension SubscriptDeclSyntax: AttributableDeclSyntax {}
71-
extension TypealiasDeclSyntax: AttributableDeclSyntax {}
70+
extension TypeAliasDeclSyntax: AttributableDeclSyntax {}
7271
extension VariableDeclSyntax: AttributableDeclSyntax {}

Sources/CodableMacroPlugin/Attributes/Attribute.swift

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import SwiftSyntax
21
import SwiftDiagnostics
2+
import SwiftSyntax
33
import SwiftSyntaxMacros
44

55
/// A type indicating a macro-attribute.
@@ -62,8 +62,7 @@ extension Attribute {
6262
/// provided declaration.
6363
///
6464
/// - Parameter declaration: The declaration this macro attribute
65-
/// is attached to.
66-
///
65+
/// is attached to.
6766
/// - Returns: Whether this attribute is applied more than once.
6867
func isDuplicated(in declaration: some SyntaxProtocol) -> Bool {
6968
return declaration.attributes(for: Self.self).count > 1

0 commit comments

Comments
 (0)