Skip to content

Commit 666dc31

Browse files
committed
Create documentation homepage with symbols sorted into sensible categories and document more symbols
1 parent 18bceb6 commit 666dc31

21 files changed

+323
-62
lines changed

Package.resolved

+18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
{
22
"pins" : [
3+
{
4+
"identity" : "swift-docc-plugin",
5+
"kind" : "remoteSourceControl",
6+
"location" : "https://github.com/apple/swift-docc-plugin",
7+
"state" : {
8+
"revision" : "26ac5758409154cc448d7ab82389c520fa8a8247",
9+
"version" : "1.3.0"
10+
}
11+
},
12+
{
13+
"identity" : "swift-docc-symbolkit",
14+
"kind" : "remoteSourceControl",
15+
"location" : "https://github.com/apple/swift-docc-symbolkit",
16+
"state" : {
17+
"revision" : "b45d1f2ed151d057b54504d653e0da5552844e34",
18+
"version" : "1.0.0"
19+
}
20+
},
321
{
422
"identity" : "swift-syntax",
523
"kind" : "remoteSourceControl",

Package.swift

+8-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// swift-tools-version: 5.9
22

3-
import PackageDescription
43
import CompilerPluginSupport
4+
import PackageDescription
55

66
let package = Package(
77
name: "swift-macro-toolkit",
@@ -10,10 +10,13 @@ let package = Package(
1010
.library(
1111
name: "MacroToolkit",
1212
targets: ["MacroToolkit"]
13-
),
13+
)
1414
],
1515
dependencies: [
16-
.package(url: "https://github.com/apple/swift-syntax.git", from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b"),
16+
.package(
17+
url: "https://github.com/apple/swift-syntax.git",
18+
from: "509.0.0-swift-5.9-DEVELOPMENT-SNAPSHOT-2023-04-25-b"),
19+
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
1720
],
1821
targets: [
1922
// Implementations of macros tested by tests
@@ -22,7 +25,7 @@ let package = Package(
2225
dependencies: [
2326
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
2427
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
25-
"MacroToolkit"
28+
"MacroToolkit",
2629
]
2730
),
2831

@@ -33,7 +36,7 @@ let package = Package(
3336
name: "MacroToolkit",
3437
dependencies: [
3538
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
36-
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
39+
.product(name: "SwiftCompilerPlugin", package: "swift-syntax"),
3740
]
3841
),
3942

README.md

+6-8
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,7 @@ return literal.value
115115
#### With Macro Toolkit
116116

117117
```swift
118-
guard
119-
case let .nominal("Result", (successType, failureType))? = destructure(returnType)
120-
else {
118+
guard case let .simple("Result", (successType, failureType))? = destructure(returnType) else {
121119
throw MacroError("Invalid return type")
122120
}
123121
```
@@ -126,9 +124,9 @@ else {
126124

127125
```swift
128126
guard
129-
let nominalReturnType = returnType.as(SimpleTypeIdentifierSyntax.self),
130-
nominalReturnType.name.description == "Result",
131-
let genericArguments = (nominalReturnType.genericArgumentClause?.arguments).map(Array.init),
127+
let simpleReturnType = returnType.as(SimpleTypeIdentifierSyntax.self),
128+
simpleReturnType.name.description == "Result",
129+
let genericArguments = (simpleReturnType.genericArgumentClause?.arguments).map(Array.init),
132130
genericArguments.count == 2
133131
else {
134132
throw MacroError("Invalid return type")
@@ -165,8 +163,8 @@ func returnsVoid(_ function: FunctionDeclSyntax) -> Bool {
165163
}
166164

167165
if let element = tuple.elements.first, tuple.elements.count == 1 {
168-
let isLabeled = element.name == nil && element.secondName == nil
169-
return isLabeled && isVoid(TypeSyntax(element.type))
166+
let isUnlabeled = element.name == nil && element.secondName == nil
167+
return isUnlabeled && isVoid(TypeSyntax(element.type))
170168
}
171169
return false
172170
}

Sources/MacroToolkit/Attribute.swift

+9-5
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,24 @@ public struct Attribute {
1212

1313
/// Creates a new attribute with the given name.
1414
public init(named name: String) {
15-
_syntax = AttributeSyntax(attributeName: SimpleTypeIdentifierSyntax(
16-
name: .identifier("DictionaryStorage")
17-
))
15+
_syntax = AttributeSyntax(
16+
attributeName: SimpleTypeIdentifierSyntax(
17+
name: .identifier("DictionaryStorage")
18+
)
19+
)
1820
}
1921

2022
/// The attribute's name.
2123
public var name: SimpleType {
2224
guard let type = SimpleType(_syntax.attributeName) else {
23-
fatalError("Assumed that attribute name would be simple type, but got: \(_syntax.attributeName)")
25+
fatalError(
26+
"Assumed that attribute name would be simple type, but got: \(_syntax.attributeName)"
27+
)
2428
}
2529
return type
2630
}
2731

28-
///
32+
/// Attempts to get the attribute as a macro attribute (e.g. `@MyMacro` as opposed to `@propertyWrapper`).
2933
public var asMacroAttribute: MacroAttribute? {
3034
MacroAttribute(_syntax)
3135
}

Sources/MacroToolkit/AttributeListElement.swift

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public enum AttributeListElement {
66
case attribute(Attribute)
77
case conditionalCompilationBlock(ConditionalCompilationBlock)
88

9+
/// The underlying attribute (if any).
910
public var attribute: Attribute? {
1011
switch self {
1112
case .attribute(let attribute):
@@ -15,6 +16,8 @@ public enum AttributeListElement {
1516
}
1617
}
1718

19+
/// The underlying conditional compilation block (e.g.
20+
/// `#if ... \n @propertyWrapper \n #endif`).
1821
public var conditionalCompilationBlock: ConditionalCompilationBlock? {
1922
switch self {
2023
case .conditionalCompilationBlock(let conditionalCompilationBlock):
@@ -36,13 +39,16 @@ extension Sequence where Element == AttributeListElement {
3639
case .attribute(let attribute):
3740
element = .attribute(attribute._syntax.with(\.trailingTrivia, [.spaces(1)]))
3841
case .conditionalCompilationBlock(let conditionalCompilationBlock):
39-
element = .ifConfigDecl(conditionalCompilationBlock._syntax.with(\.trailingTrivia, [.spaces(1)]))
42+
element = .ifConfigDecl(
43+
conditionalCompilationBlock._syntax.with(\.trailingTrivia, [.spaces(1)]))
4044
}
4145
list = list.appending(element)
4246
}
4347
return list
4448
}
4549

50+
/// Gets the first attribute with the given `name`. The name doesn't include
51+
/// any generic parameters (see ``Attribute/name``).
4652
public func first(called name: String) -> Attribute? {
4753
// TODO: How should conditional compilation attributes be handled?
4854
compactMap(\.attribute).first { attribute in
+3-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import SwiftSyntax
22

3+
/// Wraps a boolean literal (i.e. `true` or `false`).
34
public struct BooleanLiteral: LiteralProtocol {
45
public var _syntax: BooleanLiteralExprSyntax
56

7+
/// Wraps a boolean literal syntax node.
68
public init(_ syntax: BooleanLiteralExprSyntax) {
79
_syntax = syntax
810
}
911

1012
public var value: Bool {
1113
_syntax.booleanLiteral.tokenKind == .keyword(.true)
12-
}
14+
}
1315
}

Sources/MacroToolkit/ConditionalCompilationBlock.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import SwiftSyntax
22

3-
/// A compile-time conditional block (i.e. `#if ...`).
3+
/// A compile-time conditional block (i.e. `#if ... \n ... \n #endif`).
44
public struct ConditionalCompilationBlock {
5+
/// The underlying syntax node.
56
public var _syntax: IfConfigDeclSyntax
67

8+
/// Wraps a compile-time conditional block syntax node.
79
public init(_ syntax: IfConfigDeclSyntax) {
810
_syntax = syntax
911
}

Sources/MacroToolkit/Decl.swift

+7-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
import SwiftSyntax
22

3+
/// A declaration (e.g. an `enum` or a `struct` etc.).
34
public struct Decl {
5+
/// The underlying syntax node for the declaration.
46
public var _syntax: DeclSyntax
57

6-
public init(_ syntax: DeclSyntax) {
7-
_syntax = syntax
8-
}
9-
8+
/// Wraps a declaration syntax node.
109
public init(_ syntax: any DeclSyntaxProtocol) {
1110
_syntax = DeclSyntax(syntax)
1211
}
1312

14-
// TODO: Add conversions for all possible member types
13+
// TODO: Add conversions for all possible member types. Maybe make this into an enum like ``Type``
14+
/// Attempts to get the declaration as an enum.
1515
public var asEnum: Enum? {
1616
_syntax.as(EnumDeclSyntax.self).map(Enum.init)
1717
}
1818

19+
/// Attempts to get the declaration as a struct.
1920
public var asStruct: Struct? {
2021
_syntax.as(StructDeclSyntax.self).map(Struct.init)
2122
}
2223

24+
/// Attempts to get the declaration as a variable.
2325
public var asVariable: Variable? {
2426
_syntax.as(VariableDeclSyntax.self).map(Variable.init)
2527
}

Sources/MacroToolkit/DeclGroup.swift

+6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
import SwiftSyntax
22

3+
/// Wraps a declaration group (a declaration with a scoped block of members).
4+
/// For example an `enum` or a `struct` etc.
35
public struct DeclGroup {
6+
/// The underlying syntax node.
47
public var _syntax: DeclGroupSyntax
58

9+
/// Wraps a declaration group syntax node.
610
public init(_ syntax: DeclGroupSyntax) {
711
_syntax = syntax
812
}
913

14+
/// Gets whether the declaration has the `public` access modifier.
1015
public var isPublic: Bool {
1116
_syntax.isPublic
1217
}
1318

19+
/// Gets all of the declaration group's member declarations.
1420
public var members: [Decl] {
1521
_syntax.memberBlock.members.map(\.decl).map(Decl.init)
1622
}

Sources/MacroToolkit/Destructuring.swift

+28-13
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public func destructure<Element>(_ elements: some Sequence<Element>) -> ()? {
77
return ()
88
}
99

10+
/// Destructures the given `elements` into a single element if there is exactly one element.
1011
/// Named differently to allow type inference to still work correctly (single element tuples
1112
/// are weird in Swift).
1213
public func destructureSingle<Element>(_ elements: some Sequence<Element>) -> (Element)? {
@@ -17,6 +18,7 @@ public func destructureSingle<Element>(_ elements: some Sequence<Element>) -> (E
1718
return (array[0])
1819
}
1920

21+
/// Destructures the given `elements` into a tuple of 2 elements if there are exactly 2 elements.
2022
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element)? {
2123
let array = Array(elements)
2224
guard array.count == 2 else {
@@ -25,31 +27,42 @@ public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element
2527
return (array[0], array[1])
2628
}
2729

28-
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element, Element)? {
30+
/// Destructures the given `elements` into a tuple of 3 elements if there are exactly 3 elements.
31+
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element, Element)?
32+
{
2933
let array = Array(elements)
3034
guard array.count == 3 else {
3135
return nil
3236
}
3337
return (array[0], array[1], array[2])
3438
}
3539

36-
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element, Element, Element)? {
40+
/// Destructures the given `elements` into a tuple of 4 elements if there are exactly 4 elements.
41+
public func destructure<Element>(_ elements: some Sequence<Element>) -> (
42+
Element, Element, Element, Element
43+
)? {
3744
let array = Array(elements)
3845
guard array.count == 4 else {
3946
return nil
4047
}
4148
return (array[0], array[1], array[2], array[3])
4249
}
4350

44-
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element, Element, Element, Element)? {
51+
/// Destructures the given `elements` into a tuple of 5 elements if there are exactly 5 elements.
52+
public func destructure<Element>(_ elements: some Sequence<Element>) -> (
53+
Element, Element, Element, Element, Element
54+
)? {
4555
let array = Array(elements)
4656
guard array.count == 5 else {
4757
return nil
4858
}
4959
return (array[0], array[1], array[2], array[3], array[4])
5060
}
5161

52-
public func destructure<Element>(_ elements: some Sequence<Element>) -> (Element, Element, Element, Element, Element, Element)? {
62+
/// Destructures the given `elements` into a tuple of 6 elements if there are exactly 6 elements.
63+
public func destructure<Element>(_ elements: some Sequence<Element>) -> (
64+
Element, Element, Element, Element, Element, Element
65+
)? {
5366
let array = Array(elements)
5467
guard array.count == 6 else {
5568
return nil
@@ -148,7 +161,7 @@ public func destructure(_ type: FunctionType) -> ((Type, Type, Type, Type, Type,
148161
public func destructure(_ type: Type) -> DestructuredType<()>? {
149162
if let type = type.asSimpleType {
150163
return destructure(type).map { destructured in
151-
.nominal(name: destructured.0, genericArguments: destructured.1)
164+
.simple(name: destructured.0, genericArguments: destructured.1)
152165
}
153166
} else if let type = type.asFunctionType {
154167
return destructure(type).map { destructured in
@@ -164,7 +177,7 @@ public func destructure(_ type: Type) -> DestructuredType<()>? {
164177
public func destructureSingle(_ type: Type) -> DestructuredType<(Type)>? {
165178
if let type = type.asSimpleType {
166179
return destructureSingle(type).map { destructured in
167-
.nominal(name: destructured.0, genericArguments: destructured.1)
180+
.simple(name: destructured.0, genericArguments: destructured.1)
168181
}
169182
} else if let type = type.asFunctionType {
170183
return destructureSingle(type).map { destructured in
@@ -178,7 +191,7 @@ public func destructureSingle(_ type: Type) -> DestructuredType<(Type)>? {
178191
public func destructure(_ type: Type) -> DestructuredType<(Type, Type)>? {
179192
if let type = type.asSimpleType {
180193
return destructure(type).map { destructured in
181-
.nominal(name: destructured.0, genericArguments: destructured.1)
194+
.simple(name: destructured.0, genericArguments: destructured.1)
182195
}
183196
} else if let type = type.asFunctionType {
184197
return destructure(type).map { destructured in
@@ -192,7 +205,7 @@ public func destructure(_ type: Type) -> DestructuredType<(Type, Type)>? {
192205
public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type)>? {
193206
if let type = type.asSimpleType {
194207
return destructure(type).map { destructured in
195-
.nominal(name: destructured.0, genericArguments: destructured.1)
208+
.simple(name: destructured.0, genericArguments: destructured.1)
196209
}
197210
} else if let type = type.asFunctionType {
198211
return destructure(type).map { destructured in
@@ -206,7 +219,7 @@ public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type)>? {
206219
public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Type)>? {
207220
if let type = type.asSimpleType {
208221
return destructure(type).map { destructured in
209-
.nominal(name: destructured.0, genericArguments: destructured.1)
222+
.simple(name: destructured.0, genericArguments: destructured.1)
210223
}
211224
} else if let type = type.asFunctionType {
212225
return destructure(type).map { destructured in
@@ -220,7 +233,7 @@ public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Typ
220233
public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Type, Type)>? {
221234
if let type = type.asSimpleType {
222235
return destructure(type).map { destructured in
223-
.nominal(name: destructured.0, genericArguments: destructured.1)
236+
.simple(name: destructured.0, genericArguments: destructured.1)
224237
}
225238
} else if let type = type.asFunctionType {
226239
return destructure(type).map { destructured in
@@ -234,7 +247,7 @@ public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Typ
234247
public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Type, Type, Type)>? {
235248
if let type = type.asSimpleType {
236249
return destructure(type).map { destructured in
237-
.nominal(name: destructured.0, genericArguments: destructured.1)
250+
.simple(name: destructured.0, genericArguments: destructured.1)
238251
}
239252
} else if let type = type.asFunctionType {
240253
return destructure(type).map { destructured in
@@ -245,8 +258,10 @@ public func destructure(_ type: Type) -> DestructuredType<(Type, Type, Type, Typ
245258
}
246259
}
247260

248-
/// A destructured type (e.g. `Result<Success, Failure>` => `.nominal(name: "Result", genericArguments: ("Success", "Failure"))`).
261+
/// A destructured type (e.g. `Result<Success, Failure>` becomes `.simple(name: "Result", genericArguments: ("Success", "Failure"))`).
249262
public enum DestructuredType<TypeList> {
250-
case nominal(name: String, genericArguments: TypeList)
263+
/// A simple type (often referred to as a nominal type) such as `Int` or `Array<String>`.
264+
case simple(name: String, genericArguments: TypeList)
265+
/// A function type such as `(Int) -> Void`.
251266
case function(parameterTypes: TypeList, returnType: Type)
252267
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Destructuring
2+
3+
Destructuring is a game changer for developing robust macros without drowning yourself in verbose input validation code.

0 commit comments

Comments
 (0)