Skip to content

Commit 4d0d98b

Browse files
committed
Improve documentation articles
1 parent 38c2624 commit 4d0d98b

File tree

8 files changed

+53
-14
lines changed

8 files changed

+53
-14
lines changed

CONTRIBUTING.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,21 @@ Tip: Running SwiftSyntax’s self-parse tests takes the majority of testing time
6363
2. Select the Arguments tab in the Run section
6464
3. Add a `SKIP_LONG_TESTS` environment variable with value `1`
6565

66-
### Additional testing methods
66+
### Additional Verification
6767

68-
swift-syntax has two additional testing methods that provide more extensive validation. They have significant runtime impact on swift-syntax and are thus not enabled by default when building swift-syntax. The validations are run in CI. If CI fails and you are unable to reproduce the failure locally, make sure that `SKIP_LONG_TESTS` is not set and try enabling these validations.
68+
swift-syntax has two additional verification methods (see the two sections below) that provide more extensive validation. They have significant runtime impact on swift-syntax and are thus not enabled by default when building swift-syntax, but are enabled in CI. If CI fails and you are unable to reproduce the failure locally, make sure that `SKIP_LONG_TESTS` is not set and try enabling these validations.
6969

70-
#### RawSyntax validation
70+
#### RawSyntax Validation
7171

7272
When the `SWIFTSYNTAX_ENABLE_RAWSYNTAX_VALIDATION` environment variable is set while building swift-syntax (or the check for that variable has been changed to always return `true` in Package.swift), SwiftSyntax will perform additional validation that the layout of the syntax tree is correct. It validates that every child of a syntax node has the correct kind (which should be guaranteed by the Swift type system in most cases) and, more importantly, validates that each token only has one of the token kinds that is specified in the syntax tree layout of the `CodeGeneration` package.
7373

7474
If this validation hits an assertion failure that a token is not accepted at a certain position in the syntax tree, double check if the token kind that is being stored in the syntax tree actually makes sense here. If it does not, check if there is a parser bug or whether you need to remap the token kind. If it does make sense, add the token kind to `.token(choices:)` of the syntax node in CodeGeneration, re-generate that source code and run tests again.
7575

76-
#### Test case mutation
76+
#### Test Case Mutation
7777

7878
When the `SWIFTPARSER_ENABLE_ALTERNATE_TOKEN_INTROSPECTION` environment variable is set while building swift-syntax (or the check for that variable has been changed to always return `true` in Package.swift), SwiftParser records alternative tokens that the parser was looking for at specific offsets in the source file (e.g. whether it also checked for a `struct` keyword when the source code contained a `class` keyword). It will then use that information to mutate the test case by e.g. substituting `class` by `struct`.
7979

80-
When testing finds one of these failures, it will show you the syntax tree that produced the failure. Create a new test case with the source code the failure gives you and fix it.
80+
When testing finds one of these failures, it will show you the syntax tree that produced the failure. Create a new test case with the source code the failure gives you and fix the failure.
8181

8282
### `lit`-based Tests
8383

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SwiftSyntaxDoccIndex.swift

+33-2
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,40 @@ let nodesSections: String = {
6767
return result
6868
}()
6969

70+
var contributingDocs: String = {
71+
let contributingDocsFolder = URL(fileURLWithPath: #filePath)
72+
.deletingLastPathComponent()
73+
.deletingLastPathComponent()
74+
.deletingLastPathComponent()
75+
.deletingLastPathComponent()
76+
.deletingLastPathComponent()
77+
.deletingLastPathComponent()
78+
.appendingPathComponent("Sources")
79+
.appendingPathComponent("SwiftSyntax")
80+
.appendingPathComponent("Documentation.docc")
81+
.appendingPathComponent("Contributing")
82+
83+
let files = (try? FileManager.default.contentsOfDirectory(at: contributingDocsFolder, includingPropertiesForKeys: nil)) ?? []
84+
85+
return files.compactMap { file in
86+
if file.pathExtension != "md" {
87+
return nil
88+
}
89+
let doccName = file.lastPathComponent
90+
.replacingOccurrences(of: ".md", with: "")
91+
.replacingOccurrences(of: " ", with: "-")
92+
return "- <doc:\(doccName)>"
93+
}.sorted().joined(separator: "\n")
94+
}()
95+
7096
let swiftSyntaxDoccIndex: String = {
71-
let templateURL = URL(fileURLWithPath: #filePath).deletingLastPathComponent().appendingPathComponent("SwiftSyntaxDoccIndexTemplate.md")
97+
let templateURL = URL(fileURLWithPath: #filePath)
98+
.deletingLastPathComponent()
99+
.appendingPathComponent("SwiftSyntaxDoccIndexTemplate.md")
72100
let template = try! String(contentsOf: templateURL)
73101

74-
return template.replacingOccurrences(of: "{{Nodes}}", with: nodesSections)
102+
return
103+
template
104+
.replacingOccurrences(of: "{{Nodes}}", with: nodesSections)
105+
.replacingOccurrences(of: "{{ContributingDocs}}", with: contributingDocs)
75106
}()

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntax/SwiftSyntaxDoccIndexTemplate.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ allows Swift tools to parse, inspect, generate, and transform Swift source code.
2626

2727
These articles are intended for developers wishing to contribute to SwiftSyntax
2828

29-
- <doc:ChangingSwiftSyntax>
30-
- <doc:Existentials>
29+
{{ContributingDocs}}
3130

3231
### Syntax
3332

Sources/SwiftSyntax/Documentation.docc/Existentials.md Sources/SwiftSyntax/Documentation.docc/Contributing/Existentials.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
Learn when to use protocols value types like ``ExprSyntax`` over protocols like ``ExprSyntaxProtocol``.
44

55

6-
SwiftSyntax tries to minimize the use of existentials (aka. protocols spelled with `any` or protocols spelled without `some`) wherever possible. This is because when the stored value is more than 3 words (a word is the size of a pointer) large, these existentials store their data on the heap. The data stored inside `RawSyntax` is bigger than 3 words and thus every time you pass a value around as a e.g. an `ExprSyntaxProtocol`, a new heap allocation will be made and that data needs to be reference-counted, which causes a very noticable performance overhead.
6+
SwiftSyntax tries to minimize the use of existentials (aka. protocols spelled with `any` or protocols spelled without `some`) wherever possible. This is because when the stored value is more than 3 words (a word is the size of a pointer) large, these existentials store their data on the heap. The data stored inside `RawSyntax` is larger than 3 words and thus every time you pass a value around as a e.g. an `ExprSyntaxProtocol`, a new heap allocation will be made and that data needs to be reference-counted, which causes a very noticeable performance overhead.
77

8-
There are two more performant alternatives:
8+
swift-syntax offers two alternatives:
99
- When passing a single node around, use `some ExprSyntaxProtocol`. This allows the concrete expression node (e.g. an ``IntegerLiteralExprSyntax``) to be passed directly without the need to wrap it in an existential and thus avoid the performance overhead.
10-
- When multiple expression nodes need to be represented that might be of different types, eg. in an array of expressions, use the ``ExprSyntax`` type. ``ExprSyntax`` is a struct and can thus be allocated on the stack. The downside is that specific expression nodes need to explicitly be upcast to `ExprSyntax`, eg. as `ExprSyntax(integerLiteral)`. ``ExprSyntax`` can be cast to more specific types using the `as` method, e.g. `expr.as(IntegerLiteralExprSyntax.self)`.
10+
- When multiple expression nodes need to be represented that might be of different types, eg. in an array of expressions, use the ``ExprSyntax`` type. ``ExprSyntax`` is a struct and can thus be allocated on the stack. The downside is that specific expression nodes need to explicitly be upcast to `ExprSyntax` (`ExprSyntax(integerLiteral)`) and downcast to more specific types using a custom `as` method (`expr.as(IntegerLiteralExprSyntax.self)`).
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
# `@_spi` attribute
1+
# @_spi attribute
22

33
Learn when SwiftSyntax exposes declaration annotated as `@_spi`.
44

55
Functions marked as `@_spi(RawSyntax)` (where ``RawSyntax`` can be any name) are considered *SPI* (System Programming Interface) and are only accessible if the module that declares them is imported as `@_spi(RawSyntax)`.
66

77
Since functions marked as SPI are not part of the public API, swift-syntax makes no guarantee to their source stability. swift-syntax makes no effort to keep its SPI stable.
88

9-
Declarations are typically marked as SPI because they have some kind of caveat that makes them unsafe to use in general. For example, when accessing ``RawSyntax`` nodes, you need to manually guarantee that the ``SyntaxArena`` they live in doesn’t get de-allocated. Other declarations have an `@_spi` to share them between different modudules within the swift-syntax package but those APIs shouldn’t be accessed publicly.
9+
Declarations are typically marked as SPI because they have some kind of caveat that makes them unsafe to use in general. For example, when accessing ``RawSyntax`` nodes, you need to manually guarantee that the ``SyntaxArena`` they’re allocated in will not be de-allocated. Other declarations have an `@_spi` to share them between different modules within the swift-syntax package. These would use the [`package` modifier](https://github.com/apple/swift-evolution/blob/main/proposals/0386-package-access-modifier.md) if not for the fact that swift-syntax needed to compile with the last two Swift releases (see <doc:Swift-Version>).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Language Features Usable in swift-syntax
2+
3+
Defines which language features the swift-syntax package can use.
4+
5+
We require that SwiftSyntax builds with the latest released compiler and the previous major version (e.g. with Swift 5.8 and Swift 5.7).
6+
7+
*This documentation article needs to be expanded*

Sources/SwiftSyntax/Documentation.docc/generated/SwiftSyntax.md

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ These articles are intended for developers wishing to contribute to SwiftSyntax
2828

2929
- <doc:ChangingSwiftSyntax>
3030
- <doc:Existentials>
31+
- <doc:SPI>
32+
- <doc:Swift-Version>
3133

3234
### Syntax
3335

0 commit comments

Comments
 (0)