Skip to content

Commit 437337e

Browse files
committed
Merge remote-tracking branch 'upstream/main' into wasm32-wasi-test
2 parents 4718be7 + 2c847f8 commit 437337e

28 files changed

+2205
-180
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# Order is important. The last matching pattern has the most precedence.
99

1010
# Owner of anything in SwiftSyntax not owned by anyone else.
11-
* @ahoppen
11+
* @ahoppen @bnbarham
1212

1313
# Macros
1414
/Sources/SwiftSyntaxMacros @DougGregor

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxCollectionsFile.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
105105

106106
StmtSyntax("return .choices(\(choices))")
107107
}
108+
109+
for choiceNodeName in node.elementChoices {
110+
let choiceNode = SYNTAX_NODE_MAP[choiceNodeName]!
111+
choiceNodeCastingMethods(for: choiceNode.kind)
112+
}
108113
}
109114
}
110115

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
import SwiftSyntax
14+
import SwiftSyntaxBuilder
15+
import SyntaxSupport
16+
17+
@MemberBlockItemListBuilder
18+
func choiceNodeCastingMethods(for syntaxNodeKind: SyntaxNodeKind) -> MemberBlockItemListSyntax {
19+
if syntaxNodeKind.isBase {
20+
DeclSyntax(
21+
"""
22+
/// Checks if the current syntax node can be cast to the type conforming to the ``\(syntaxNodeKind.protocolType)`` protocol.
23+
///
24+
/// - Returns: `true` if the node can be cast, `false` otherwise.
25+
public func `is`<S: \(syntaxNodeKind.protocolType)>(_ syntaxType: S.Type) -> Bool {
26+
return self.as(syntaxType) != nil
27+
}
28+
"""
29+
)
30+
31+
DeclSyntax(
32+
"""
33+
/// Attempts to cast the current syntax node to the type conforming to the ``\(syntaxNodeKind.protocolType)`` protocol.
34+
///
35+
/// - Returns: An instance of the specialized type, or `nil` if the cast fails.
36+
public func `as`<S: \(syntaxNodeKind.protocolType)>(_ syntaxType: S.Type) -> S? {
37+
return S.init(self)
38+
}
39+
"""
40+
)
41+
42+
DeclSyntax(
43+
"""
44+
/// Force-casts the current syntax node to the type conforming to the ``\(syntaxNodeKind.protocolType)`` protocol.
45+
///
46+
/// - Returns: An instance of the specialized type.
47+
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
48+
public func cast<S: \(syntaxNodeKind.protocolType)>(_ syntaxType: S.Type) -> S {
49+
return self.as(S.self)!
50+
}
51+
"""
52+
)
53+
} else {
54+
DeclSyntax(
55+
"""
56+
/// Checks if the current syntax node can be cast to ``\(syntaxNodeKind.syntaxType)``.
57+
///
58+
/// - Returns: `true` if the node can be cast, `false` otherwise.
59+
public func `is`(_ syntaxType: \(syntaxNodeKind.syntaxType).Type) -> Bool {
60+
return self.as(syntaxType) != nil
61+
}
62+
"""
63+
)
64+
65+
DeclSyntax(
66+
"""
67+
/// Attempts to cast the current syntax node to ``\(syntaxNodeKind.syntaxType)``.
68+
///
69+
/// - Returns: An instance of ``\(syntaxNodeKind.syntaxType)``, or `nil` if the cast fails.
70+
public func `as`(_ syntaxType: \(syntaxNodeKind.syntaxType).Type) -> \(syntaxNodeKind.syntaxType)? {
71+
return \(syntaxNodeKind.syntaxType).init(self)
72+
}
73+
"""
74+
)
75+
76+
DeclSyntax(
77+
"""
78+
/// Force-casts the current syntax node to ``\(syntaxNodeKind.syntaxType)``.
79+
///
80+
/// - Returns: An instance of ``\(syntaxNodeKind.syntaxType)``.
81+
/// - Warning: This function will crash if the cast is not possible. Use `as` to safely attempt a cast.
82+
public func cast(_ syntaxType: \(syntaxNodeKind.syntaxType).Type) -> \(syntaxNodeKind.syntaxType) {
83+
return self.as(\(syntaxNodeKind.syntaxType).self)!
84+
}
85+
"""
86+
)
87+
}
88+
}

CodeGeneration/Sources/generate-swift-syntax/templates/swiftsyntax/SyntaxNodesFile.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,5 +277,9 @@ private func generateSyntaxChildChoices(for child: Child) throws -> EnumDeclSynt
277277

278278
StmtSyntax("return .choices(\(choices))")
279279
}
280+
281+
for choiceNode in choices {
282+
choiceNodeCastingMethods(for: choiceNode.syntaxNodeKind)
283+
}
280284
}
281285
}

Examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Each example can be executed by navigating into this folder and running `swift r
55
- [AddOneToIntegerLiterals](Sources/AddOneToIntegerLiterals/AddOneToIntegerLiterals.swift): Command line tool to add 1 to every integer literal in a source file
66
- [CodeGenerationUsingSwiftSyntaxBuilder](Sources/CodeGenerationUsingSwiftSyntaxBuilder/CodeGenerationUsingSwiftSyntaxBuilder.swift): Code-generate a simple source file using SwiftSyntaxBuilder
77
- [ExamplePlugin](Sources/ExamplePlugin): Compiler plugin executable using [`SwiftCompilerPlugin`](../Sources/SwiftCompilerPlugin)
8+
- [MacroExamples](Sources/MacroExamples): A collection of Swift macros
89

910
Furthermore, SwiftSyntax uses [`SwiftSyntaxBuilder`](../Sources/SwiftSyntaxBuilder) extensively to generate its own code. That code can be found in the [CodeGeneration](../CodeGeneration) package.
1011

Package.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,12 +319,12 @@ package.targets.append(
319319
)
320320

321321
if useLocalDependencies {
322-
// Building standalone.
323322
package.dependencies += [
324-
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.2")
323+
.package(path: "../swift-argument-parser")
325324
]
326325
} else {
326+
// Building standalone.
327327
package.dependencies += [
328-
.package(path: "../swift-argument-parser")
328+
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.2.2")
329329
]
330330
}

README.md

Lines changed: 14 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,38 @@
1-
# SwiftSyntax
1+
# Swift Syntax
22

3-
SwiftSyntax is a set of Swift libraries for parsing, inspecting, generating, and transforming Swift source code.
3+
The swift-syntax package is a set of libraries that work on a source-accurate tree representation of Swift source code, called the SwiftSyntax tree. The SwiftSyntax tree forms the backbone of Swift’s macro system – the macro expansion nodes are represented as SwiftSyntax nodes and a macro generates a SwiftSyntax tree to be inserted into the source file.
44

55
## Documentation
66

77
You can read SwiftSyntax’s documentation on [swiftpackageindex.com](https://swiftpackageindex.com/apple/swift-syntax/documentation).
88

99
A great way to interactively explore the SwiftSyntax tree of a source file is https://swift-ast-explorer.com, developed by [@kishikawakatsumi](https://github.com/kishikawakatsumi).
1010

11-
## Adding SwiftSyntax as a Dependency
11+
A set of example usages of swift-syntax can be found in [Examples](Examples).
1212

13-
### Trunk Development (main)
13+
## Releases
1414

15-
The mainline branch of SwiftSyntax tracks the latest developments. It is not
16-
an official release, and is subject to rapid changes in APIs and behaviors. To
17-
use it, add this repository to the `Package.swift` manifest of your project:
15+
Releases of SwiftSyntax are aligned with corresponding language and tooling releases, for example the major version 509 of swift-syntax is aligned with Swift 5.9.
16+
17+
To depend on swift-syntax in a SwiftPM package, add the following to your `Package.swift`.
1818

19-
```swift
20-
// swift-tools-version:5.7
21-
import PackageDescription
22-
23-
let package = Package(
24-
name: "MyTool",
25-
dependencies: [
26-
.package(url: "https://github.com/apple/swift-syntax.git", branch: "main"),
27-
],
28-
targets: [
29-
.target(name: "MyTool", dependencies: [
30-
.product(name: "SwiftSyntax", package: "swift-syntax"),
31-
]),
32-
]
33-
)
34-
```
35-
36-
Mainline SwiftSyntax also includes
37-
38-
- `SwiftParser` for natively parsing source code
39-
- `SwiftOperators` for folding SwiftSyntax trees containing operators
40-
- `SwiftSyntaxBuilder` for generating Swift code with a result builder-style interface
41-
- `SwiftSyntaxMacros` for providing syntactic macro support
42-
43-
### Releases
44-
45-
Releases of SwiftSyntax are aligned with corresponding language
46-
and tooling releases and are stable. To use them,
47-
add this repository to the `Package.swift` manifest of your project:
4819

4920
```swift
50-
// swift-tools-version:5.7
51-
import PackageDescription
52-
53-
let package = Package(
54-
name: "MyTool",
55-
dependencies: [
56-
.package(url: "https://github.com/apple/swift-syntax.git", exact: "<#Specify Release tag#>"),
57-
],
58-
targets: [
59-
.target(name: "MyTool", dependencies: [
60-
.product(name: "SwiftSyntax", package: "swift-syntax"),
61-
]),
62-
]
63-
)
21+
dependencies: [
22+
.package(url: "https://github.com/apple/swift-syntax.git", from: "<#latest swift-syntax tag#>"),
23+
],
6424
```
25+
26+
To add swift-syntax as a dependency of your Xcode project, go to the *Package Dependencies* tab of your Xcode project, click the plus button and search for https://github.com/apple/swift-syntax.git.
6527

66-
Replace `<#Specify Release tag#>` by the version of SwiftSyntax that you want to use (see the following table for mapping details).
67-
68-
| Xcode Release | Swift Release Tag | SwiftSyntax Release Tag |
69-
|:-------------------:|:-------------------:|:-------------------------:|
70-
| Xcode 14.3 | swift-5.8-RELEASE | 508.0.0 |
71-
| Xcode 14.0 | swift-5.7-RELEASE | 0.50700.1 |
72-
| Xcode 13.3 | swift-5.6-RELEASE | 0.50600.1 |
73-
| Xcode 13.0 | swift-5.5-RELEASE | 0.50500.0 |
74-
| Xcode 12.5 | swift-5.4-RELEASE | 0.50400.0 |
75-
| Xcode 12.0 | swift-5.3-RELEASE | 0.50300.0 |
76-
| Xcode 11.4 | swift-5.2-RELEASE | 0.50200.0 |
77-
78-
## Documentation
79-
80-
SwiftSyntax uses [DocC](https://developer.apple.com/documentation/docc) bundles
81-
for its documentation. To view rendered documentation in Xcode, open the
82-
SwiftSyntax package and select
83-
84-
```
85-
Product > Build Documentation
86-
```
87-
88-
Associated articles are written in markdown, and can be viewed in a browser,
89-
text editor, or IDE.
28+
## Reporting Issues
9029

91-
- [SwiftSyntax](Sources/SwiftSyntax/Documentation.docc)
92-
- [SwiftParser](Sources/SwiftParser/SwiftParser.docc)
93-
- [SwiftOperators](Sources/SwiftOperators/SwiftOperators.docc)
94-
- [SwiftSyntaxMacros](Sources/SwiftSyntaxMacros/SwiftSyntaxMacros.docc)
30+
If you should hit any issues while using SwiftSyntax, we appreciate bug reports on [GitHub Issue](https://github.com/apple/swift-syntax/issues).
9531

9632
## Contributing
9733

9834
Start contributing to SwiftSyntax see [this guide](CONTRIBUTING.md) for more information.
9935

100-
## Reporting Issues
101-
102-
If you should hit any issues while using SwiftSyntax, we appreciate bug reports on [GitHub Issue](https://github.com/apple/swift-syntax/issues).
103-
10436
## Bazel
10537

10638
SwiftSyntax provides an experimental [Bazel](https://bazel.build) build configuration, maintained by Keith Smiley.

Release Notes/510.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
- `SyntaxStringInterpolation.appendInterpolation(_: (some SyntaxProtocol)?)`
66
- Description: Allows optional syntax nodes to be used inside string interpolation of syntax nodes. If the node is `nil`, nothing will get added to the string interpolation.
77
- Pull Request: https://github.com/apple/swift-syntax/pull/2085
8+
89
- `SyntaxCollection.index(at:)`
910
- Description: Returns the index of the n-th element in a `SyntaxCollection`. This computation is in O(n) and `SyntaxCollection` is not subscriptable by an integer.
1011
- Pull Request: https://github.com/apple/swift-syntax/pull/2014
12+
1113
- Convenience initializer `ClosureCaptureSyntax.init()`
1214
- Description: Provides a convenience initializer for `ClosureCaptureSyntax` that takes a concrete `name` argument and automatically adds `equal = TokenSyntax.equalToken()` to it.
1315
- Issue: https://github.com/apple/swift-syntax/issues/1984
1416
- Pull Request: https://github.com/apple/swift-syntax/pull/2127
17+
1518
- Convenience initializer `EnumCaseParameterSyntax.init()`
1619
- Description: Provides a convenience initializer for `EnumCaseParameterSyntax` that takes a concrete `firstName` value and adds `colon = TokenSyntax.colonToken()` automatically to it.
1720
- Issue: https://github.com/apple/swift-syntax/issues/1984
@@ -39,6 +42,11 @@
3942
- Description: `is`, `as`, and `cast` methods on base node protocols with base-type conversions are marked as deprecated. The deprecated methods emit a warning that informs the developer that the cast will always succeed and should be done using the base node's initializer.
4043
- Issue: https://github.com/apple/swift-syntax/issues/2092
4144
- Pull Request: https://github.com/apple/swift-syntax/pull/2108
45+
46+
- Child Choice Node Casts
47+
- Description: `is`, `as`, and `cast` methods for types not contained in the choice node are marked as deprecated. The deprecated methods will emit a warning, indicating that the cast will always fail.
48+
- Issue: https://github.com/apple/swift-syntax/issues/2092
49+
- Pull Request: https://github.com/apple/swift-syntax/pull/2184
4250

4351
## API-Incompatible Changes
4452

Sources/SwiftParser/Declarations.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1040,16 +1040,25 @@ extension Parser {
10401040
) -> RawFunctionDeclSyntax {
10411041
let (unexpectedBeforeFuncKeyword, funcKeyword) = self.eat(handle)
10421042
let unexpectedBeforeIdentifier: RawUnexpectedNodesSyntax?
1043+
let unexpectedAfterIdentifier: RawUnexpectedNodesSyntax?
10431044
let identifier: RawTokenSyntax
10441045
if self.at(anyIn: Operator.self) != nil || self.at(.exclamationMark, .prefixAmpersand) {
10451046
var name = self.currentToken.tokenText
1046-
if name.count > 1 && name.hasSuffix("<") && self.peek(isAt: .identifier) {
1047+
if !currentToken.isEditorPlaceholder && name.count > 1 && name.hasSuffix("<") && self.peek(isAt: .identifier) {
10471048
name = SyntaxText(rebasing: name.dropLast())
10481049
}
10491050
unexpectedBeforeIdentifier = nil
10501051
identifier = self.consumePrefix(name, as: .binaryOperator)
1052+
unexpectedAfterIdentifier = nil
10511053
} else {
10521054
(unexpectedBeforeIdentifier, identifier) = self.expectIdentifier(keywordRecovery: true)
1055+
1056+
if currentToken.isEditorPlaceholder {
1057+
let editorPlaceholder = self.parseAnyIdentifier()
1058+
unexpectedAfterIdentifier = RawUnexpectedNodesSyntax([editorPlaceholder], arena: self.arena)
1059+
} else {
1060+
unexpectedAfterIdentifier = nil
1061+
}
10531062
}
10541063

10551064
let genericParams: RawGenericParameterClauseSyntax?
@@ -1076,6 +1085,7 @@ extension Parser {
10761085
funcKeyword: funcKeyword,
10771086
unexpectedBeforeIdentifier,
10781087
name: identifier,
1088+
unexpectedAfterIdentifier,
10791089
genericParameterClause: genericParams,
10801090
signature: signature,
10811091
genericWhereClause: generics,

Sources/SwiftParser/Types.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,9 @@ extension Parser {
936936

937937
extension Parser {
938938
mutating func parseResultType() -> RawTypeSyntax {
939-
if self.at(prefix: "<") {
939+
if self.currentToken.isEditorPlaceholder {
940+
return self.parseTypeIdentifier()
941+
} else if self.at(prefix: "<") {
940942
let generics = self.parseGenericParameters()
941943
let baseType = self.parseType()
942944
return RawTypeSyntax(

Sources/SwiftParserDiagnostics/MissingNodesError.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,15 +161,27 @@ func nodesDescriptionAndCommonParent(_ nodes: [some SyntaxProtocol], format: Boo
161161
}
162162

163163
let partDescriptions = NodesDescriptionPart.descriptionParts(for: missingSyntaxNodes).map({ $0.description(format: format) ?? "syntax" })
164-
switch partDescriptions.count {
164+
165+
return (nil, formatDescriptions(partDescriptions))
166+
}
167+
168+
/// Formats an array of descriptions into a single string.
169+
///
170+
/// This function takes an array of descriptions and formats them into a single string. Depending on the number
171+
/// of descriptions in the array, it returns different formatted strings.
172+
///
173+
/// - Parameter descriptions: An array of descriptions to be formatted.
174+
/// - Returns: A formatted string representing the descriptions.
175+
func formatDescriptions(_ descriptions: [String]) -> String {
176+
switch descriptions.count {
165177
case 0:
166-
return (nil, "syntax")
178+
return "syntax"
167179
case 1:
168-
return (nil, "\(partDescriptions.first!)")
180+
return descriptions.first!
169181
case 2:
170-
return (nil, "\(partDescriptions.first!) and \(partDescriptions.last!)")
182+
return "\(descriptions.first!) and \(descriptions.last!)"
171183
default:
172-
return (nil, "\(partDescriptions[0..<partDescriptions.count - 1].joined(separator: ", ")), and \(partDescriptions.last!)")
184+
return "\(descriptions[0..<descriptions.count - 1].joined(separator: ", ")), and \(descriptions.last!)"
173185
}
174186
}
175187

0 commit comments

Comments
 (0)