Skip to content

Commit 46d64a6

Browse files
authored
Adding Documentation (#19)
1 parent 6790d95 commit 46d64a6

31 files changed

+434
-7
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,5 @@ Support/*/macOS.entitlements
136136
vendor/ruby
137137
public
138138
.mint
139-
*.lcov
139+
*.lcov
140+
.docc-build

Sources/SyntaxKit/Assignment.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,15 @@
2929

3030
import SwiftSyntax
3131

32+
/// An assignment expression.
3233
public struct Assignment: CodeBlock {
3334
private let target: String
3435
private let value: String
36+
37+
/// Creates an assignment expression.
38+
/// - Parameters:
39+
/// - target: The variable to assign to.
40+
/// - value: The value to assign.
3541
public init(_ target: String, _ value: String) {
3642
self.target = target
3743
self.value = value

Sources/SyntaxKit/Case.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,15 @@
2929

3030
import SwiftSyntax
3131

32+
/// A `case` in a `switch` statement with tuple-style patterns.
3233
public struct Case: CodeBlock {
3334
private let patterns: [String]
3435
private let body: [CodeBlock]
3536

37+
/// Creates a `case` for a `switch` statement.
38+
/// - Parameters:
39+
/// - patterns: The patterns to match for the case.
40+
/// - content: A ``CodeBlockBuilder`` that provides the body of the case.
3641
public init(_ patterns: String..., @CodeBlockBuilderResult content: () -> [CodeBlock]) {
3742
self.patterns = patterns
3843
self.body = content()

Sources/SyntaxKit/CodeBlock+Generate.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ import Foundation
3131
import SwiftSyntax
3232

3333
extension CodeBlock {
34+
/// Generates the Swift code for the ``CodeBlock``.
35+
/// - Returns: The generated Swift code as a string.
3436
public func generateCode() -> String {
3537
let statements: CodeBlockItemListSyntax
3638
if let list = self.syntax.as(CodeBlockItemListSyntax.self) {

Sources/SyntaxKit/CodeBlock.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,52 @@
3030
import Foundation
3131
import SwiftSyntax
3232

33+
/// A protocol for types that can be represented as a SwiftSyntax node.
3334
public protocol CodeBlock {
35+
/// The SwiftSyntax representation of the code block.
3436
var syntax: SyntaxProtocol { get }
3537
}
3638

39+
/// A protocol for types that can build a ``CodeBlock``.
3740
public protocol CodeBlockBuilder {
41+
/// The type of ``CodeBlock`` that this builder creates.
3842
associatedtype Result: CodeBlock
43+
/// Builds the ``CodeBlock``.
3944
func build() -> Result
4045
}
4146

47+
/// A result builder for creating arrays of ``CodeBlock``s.
4248
@resultBuilder
4349
public struct CodeBlockBuilderResult {
50+
/// Builds a block of ``CodeBlock``s.
4451
public static func buildBlock(_ components: CodeBlock...) -> [CodeBlock] {
4552
components
4653
}
4754

55+
/// Builds an optional ``CodeBlock``.
4856
public static func buildOptional(_ component: CodeBlock?) -> CodeBlock {
4957
component ?? EmptyCodeBlock()
5058
}
5159

60+
/// Builds a ``CodeBlock`` from an `if` statement.
5261
public static func buildEither(first: CodeBlock) -> CodeBlock {
5362
first
5463
}
5564

65+
/// Builds a ``CodeBlock`` from an `else` statement.
5666
public static func buildEither(second: CodeBlock) -> CodeBlock {
5767
second
5868
}
5969

70+
/// Builds an array of ``CodeBlock``s from a `for` loop.
6071
public static func buildArray(_ components: [CodeBlock]) -> [CodeBlock] {
6172
components
6273
}
6374
}
6475

76+
/// An empty ``CodeBlock``.
6577
public struct EmptyCodeBlock: CodeBlock {
78+
/// The syntax for an empty code block.
6679
public var syntax: SyntaxProtocol {
6780
StringSegmentSyntax(content: .unknown(""))
6881
}

Sources/SyntaxKit/CommentBuilderResult.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,20 @@
2727
// OTHER DEALINGS IN THE SOFTWARE.
2828
//
2929

30+
/// A result builder for creating arrays of ``Line``s for comments.
3031
@resultBuilder
3132
public enum CommentBuilderResult {
33+
/// Builds a block of ``Line``s.
3234
public static func buildBlock(_ components: Line...) -> [Line] { components }
3335
}
3436

3537
// MARK: - Public DSL surface
3638

3739
extension CodeBlock {
38-
/// Attach comments to the current `CodeBlock`.
40+
/// Attaches comments to the current ``CodeBlock``.
41+
///
42+
/// The provided lines are injected as leading trivia to the declaration produced by this ``CodeBlock``.
43+
///
3944
/// Usage:
4045
/// ```swift
4146
/// Struct("MyStruct") { ... }
@@ -44,7 +49,8 @@ extension CodeBlock {
4449
/// Line(.doc, "This is a documentation comment")
4550
/// }
4651
/// ```
47-
/// The provided lines are injected as leading trivia to the declaration produced by this `CodeBlock`.
52+
/// - Parameter content: A ``CommentBuilderResult`` that provides the comment lines.
53+
/// - Returns: A new ``CodeBlock`` with the comments attached.
4854
public func comment(@CommentBuilderResult _ content: () -> [Line]) -> CodeBlock {
4955
CommentedCodeBlock(base: self, lines: content())
5056
}

Sources/SyntaxKit/ComputedProperty.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,17 @@
2929

3030
import SwiftSyntax
3131

32+
/// A Swift `var` declaration with a computed value.
3233
public struct ComputedProperty: CodeBlock {
3334
private let name: String
3435
private let type: String
3536
private let body: [CodeBlock]
3637

38+
/// Creates a computed property declaration.
39+
/// - Parameters:
40+
/// - name: The name of the property.
41+
/// - type: The type of the property.
42+
/// - content: A ``CodeBlockBuilder`` that provides the body of the getter.
3743
public init(_ name: String, type: String, @CodeBlockBuilderResult _ content: () -> [CodeBlock]) {
3844
self.name = name
3945
self.type = type

Sources/SyntaxKit/Default.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@
2929

3030
import SwiftSyntax
3131

32+
/// A `default` case in a `switch` statement.
3233
public struct Default: CodeBlock {
3334
private let body: [CodeBlock]
35+
36+
/// Creates a `default` case for a `switch` statement.
37+
/// - Parameter content: A ``CodeBlockBuilder`` that provides the body of the case.
3438
public init(@CodeBlockBuilderResult _ content: () -> [CodeBlock]) {
3539
self.body = content()
3640
}
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# ``SyntaxKit``
2+
3+
SyntaxKit provides a declarative way to generate Swift code structures using SwiftSyntax.
4+
5+
## Overview
6+
7+
SyntaxKit allows developers to build Swift code using result builders which enable the creation of Swift code structures in a declarative way. Here's an example:
8+
9+
```swift
10+
import SyntaxKit
11+
12+
let code = Struct("BlackjackCard") {
13+
Enum("Suit") {
14+
EnumCase("spades").equals("")
15+
EnumCase("hearts").equals("")
16+
EnumCase("diamonds").equals("")
17+
EnumCase("clubs").equals("")
18+
}
19+
.inherits("Character")
20+
.comment("nested Suit enumeration")
21+
}
22+
23+
let generatedCode = code.generateCode()
24+
```
25+
26+
This will generate the following Swift code:
27+
28+
```swift
29+
struct BlackjackCard {
30+
// nested Suit enumeration
31+
enum Suit: Character {
32+
case spades = ""
33+
case hearts = ""
34+
case diamonds = ""
35+
case clubs = ""
36+
}
37+
}
38+
```
39+
40+
## Full Example
41+
42+
Here is a more comprehensive example that demonstrates many of SyntaxKit's features to generate a `BlackjackCard` struct.
43+
44+
### DSL Code
45+
46+
```swift
47+
import SyntaxKit
48+
49+
let structExample = Struct("BlackjackCard") {
50+
Enum("Suit") {
51+
EnumCase("spades").equals("")
52+
EnumCase("hearts").equals("")
53+
EnumCase("diamonds").equals("")
54+
EnumCase("clubs").equals("")
55+
}
56+
.inherits("Character")
57+
.comment("nested Suit enumeration")
58+
59+
Enum("Rank") {
60+
EnumCase("two").equals(2)
61+
EnumCase("three")
62+
EnumCase("four")
63+
EnumCase("five")
64+
EnumCase("six")
65+
EnumCase("seven")
66+
EnumCase("eight")
67+
EnumCase("nine")
68+
EnumCase("ten")
69+
EnumCase("jack")
70+
EnumCase("queen")
71+
EnumCase("king")
72+
EnumCase("ace")
73+
74+
Struct("Values") {
75+
Variable(.let, name: "first", type: "Int")
76+
Variable(.let, name: "second", type: "Int?")
77+
}
78+
79+
ComputedProperty("values") {
80+
Switch("self") {
81+
SwitchCase(".ace") {
82+
Return {
83+
Init("Values") {
84+
Parameter(name: "first", value: "1")
85+
Parameter(name: "second", value: "11")
86+
}
87+
}
88+
}
89+
SwitchCase(".jack", ".queen", ".king") {
90+
Return {
91+
Init("Values") {
92+
Parameter(name: "first", value: "10")
93+
Parameter(name: "second", value: "nil")
94+
}
95+
}
96+
}
97+
Default {
98+
Return {
99+
Init("Values") {
100+
Parameter(name: "first", value: "self.rawValue")
101+
Parameter(name: "second", value: "nil")
102+
}
103+
}
104+
}
105+
}
106+
}
107+
}
108+
.inherits("Int")
109+
.comment("nested Rank enumeration")
110+
111+
Variable(.let, name: "rank", type: "Rank")
112+
Variable(.let, name: "suit", type: "Suit")
113+
.comment("BlackjackCard properties and methods")
114+
115+
ComputedProperty("description") {
116+
VariableDecl(.var, name: "output", equals: "\"suit is \\(suit.rawValue),\"")
117+
PlusAssign("output", "\" value is \\(rank.values.first)\"")
118+
If(Let("second", "rank.values.second"), then: {
119+
PlusAssign("output", "\" or \\(second)\"")
120+
})
121+
Return {
122+
VariableExp("output")
123+
}
124+
}
125+
}
126+
```
127+
128+
### Generated Code
129+
130+
```swift
131+
import Foundation
132+
133+
struct BlackjackCard {
134+
// nested Suit enumeration
135+
enum Suit: Character {
136+
case spades = ""
137+
case hearts = ""
138+
case diamonds = ""
139+
case clubs = ""
140+
}
141+
142+
// nested Rank enumeration
143+
enum Rank: Int {
144+
case two = 2
145+
case three
146+
case four
147+
case five
148+
case six
149+
case seven
150+
case eight
151+
case nine
152+
case ten
153+
case jack
154+
case queen
155+
case king
156+
case ace
157+
158+
struct Values {
159+
let first: Int, second: Int?
160+
}
161+
162+
var values: Values {
163+
switch self {
164+
case .ace:
165+
return Values(first: 1, second: 11)
166+
case .jack, .queen, .king:
167+
return Values(first: 10, second: nil)
168+
default:
169+
return Values(first: self.rawValue, second: nil)
170+
}
171+
}
172+
}
173+
174+
// BlackjackCard properties and methods
175+
let rank: Rank
176+
let suit: Suit
177+
var description: String {
178+
var output = "suit is \\(suit.rawValue),"
179+
output += " value is \\(rank.values.first)"
180+
if let second = rank.values.second {
181+
output += " or \\(second)"
182+
}
183+
return output
184+
}
185+
}
186+
```
187+
188+
## Topics
189+
190+
### Declarations
191+
192+
- ``Struct``
193+
- ``Enum``
194+
- ``EnumCase``
195+
- ``Function``
196+
- ``Init``
197+
- ``ComputedProperty``
198+
- ``VariableDecl``
199+
- ``Let``
200+
- ``Variable``
201+
202+
### Expressions & Statements
203+
- ``Assignment``
204+
- ``PlusAssign``
205+
- ``Return``
206+
- ``VariableExp``
207+
208+
### Control Flow
209+
- ``If``
210+
- ``Switch``
211+
- ``SwitchCase``
212+
- ``Default``
213+
214+
### Building Blocks
215+
- ``CodeBlock``
216+
- ``Parameter``
217+
- ``Literal``
218+

0 commit comments

Comments
 (0)