Skip to content

Commit e0ee126

Browse files
authored
Merge pull request #1946 from ahoppen/ahoppen/macrosystem-rework
Re-work MacroSystem on top of the same expansion functions that the compiler invokes
2 parents 3a4cc67 + 3477df6 commit e0ee126

39 files changed

+2460
-1379
lines changed

CodeGeneration/Sources/SyntaxSupport/DeclNodes.swift

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public let DECL_NODES: [Node] = [
4646
kind: .accessorBlock,
4747
base: .syntax,
4848
nameForDiagnostics: nil,
49+
parserFunction: "parseAccessorBlock",
4950
traits: [
5051
"Braced"
5152
],
@@ -56,7 +57,16 @@ public let DECL_NODES: [Node] = [
5657
),
5758
Child(
5859
name: "Accessors",
59-
kind: .collection(kind: .accessorDeclList, collectionElementName: "Accessor")
60+
kind: .nodeChoices(choices: [
61+
Child(
62+
name: "Accessors",
63+
kind: .collection(kind: .accessorDeclList, collectionElementName: "Accessor")
64+
),
65+
Child(
66+
name: "Getter",
67+
kind: .node(kind: .codeBlockItemList)
68+
),
69+
])
6070
),
6171
Child(
6272
name: "RightBrace",
@@ -1629,18 +1639,9 @@ public let DECL_NODES: [Node] = [
16291639
isOptional: true
16301640
),
16311641
Child(
1632-
name: "Accessors",
1642+
name: "AccessorBlock",
16331643
deprecatedName: "Accessor",
1634-
kind: .nodeChoices(choices: [
1635-
Child(
1636-
name: "Accessors",
1637-
kind: .node(kind: .accessorBlock)
1638-
),
1639-
Child(
1640-
name: "Getter",
1641-
kind: .node(kind: .codeBlock)
1642-
),
1643-
]),
1644+
kind: .node(kind: .accessorBlock),
16441645
isOptional: true
16451646
),
16461647
Child(
@@ -2190,18 +2191,9 @@ public let DECL_NODES: [Node] = [
21902191
isOptional: true
21912192
),
21922193
Child(
2193-
name: "Accessors",
2194+
name: "AccessorBlock",
21942195
deprecatedName: "Accessor",
2195-
kind: .nodeChoices(choices: [
2196-
Child(
2197-
name: "Accessors",
2198-
kind: .node(kind: .accessorBlock)
2199-
),
2200-
Child(
2201-
name: "Getter",
2202-
kind: .node(kind: .codeBlock)
2203-
),
2204-
]),
2196+
kind: .node(kind: .accessorBlock),
22052197
isOptional: true
22062198
),
22072199
]

CodeGeneration/Sources/generate-swiftsyntax/GenerateSwiftSyntax.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ struct GenerateSwiftSyntax: ParsableCommand {
8282
[
8383
// SwiftParser
8484
GeneratedFileSpec(swiftParserGeneratedDir + ["IsLexerClassified.swift"], isLexerClassifiedFile),
85-
GeneratedFileSpec(swiftParserGeneratedDir + ["Parser+Entry.swift"], parserEntryFile),
85+
GeneratedFileSpec(swiftParserGeneratedDir + ["LayoutNodes+Parsable.swift"], parserEntryFile),
8686
GeneratedFileSpec(swiftParserGeneratedDir + ["Parser+TokenSpecSet.swift"], parserTokenSpecSetFile),
8787
GeneratedFileSpec(swiftParserGeneratedDir + ["TokenSpecStaticMembers.swift"], tokenSpecStaticMembersFile),
8888

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftparser/ParserEntryFile.swift

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -18,84 +18,6 @@ import Utils
1818
let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
1919
DeclSyntax("@_spi(RawSyntax) import SwiftSyntax")
2020

21-
try! ExtensionDeclSyntax("extension Parser") {
22-
DeclSyntax(
23-
"""
24-
/// Parse the source code in the given string as Swift source file. See
25-
/// `Parser.init` for more details.
26-
public static func parse(
27-
source: String
28-
) -> SourceFileSyntax {
29-
var parser = Parser(source)
30-
return SourceFileSyntax.parse(from: &parser)
31-
}
32-
"""
33-
)
34-
35-
DeclSyntax(
36-
"""
37-
/// Parse the source code in the given buffer as Swift source file. See
38-
/// `Parser.init` for more details.
39-
public static func parse(
40-
source: UnsafeBufferPointer<UInt8>,
41-
maximumNestingLevel: Int? = nil
42-
) -> SourceFileSyntax {
43-
var parser = Parser(source, maximumNestingLevel: maximumNestingLevel)
44-
return SourceFileSyntax.parse(from: &parser)
45-
}
46-
"""
47-
)
48-
49-
DeclSyntax(
50-
"""
51-
/// Parse the source code in the given string as Swift source file with support
52-
/// for incremental parsing.
53-
///
54-
/// When parsing a source file for the first time, invoke `parseIncrementally`
55-
/// with `parseTransition: nil`. This returns the initial tree as well as
56-
/// ``LookaheadRanges``. If an edit is made to the source file, an
57-
/// ``IncrementalParseTransition`` can be constructed from the initial tree
58-
/// and its ``LookaheadRanges``. When invoking `parseIncrementally` again with
59-
/// the post-edit source and that parse transition, the parser will re-use
60-
/// nodes that haven’t changed.
61-
///
62-
/// - Parameters:
63-
/// - source: The source code to parse
64-
/// - parseTransition: If a similar source file has already been parsed, the
65-
/// ``IncrementalParseTransition`` that contains the previous tree as well
66-
/// as the edits that were performed to it.
67-
/// - Returns: The parsed tree as well as the ``LookaheadRanges`` that describe
68-
/// how far the parser looked ahead while parsing a node, which is
69-
/// necessary to construct an ``IncrementalParseTransition`` for a
70-
/// subsequent incremental parse
71-
public static func parseIncrementally(
72-
source: String,
73-
parseTransition: IncrementalParseTransition?
74-
) -> (tree: SourceFileSyntax, lookaheadRanges: LookaheadRanges) {
75-
var parser = Parser(source, parseTransition: parseTransition)
76-
return (SourceFileSyntax.parse(from: &parser), parser.lookaheadRanges)
77-
}
78-
"""
79-
)
80-
81-
DeclSyntax(
82-
"""
83-
/// Parse the source code in the given buffer as Swift source file with support
84-
/// for incremental parsing.
85-
///
86-
/// See doc comments in ``Parser/parseIncrementally(source:parseTransition:)``
87-
public static func parseIncrementally(
88-
source: UnsafeBufferPointer<UInt8>,
89-
maximumNestingLevel: Int? = nil,
90-
parseTransition: IncrementalParseTransition?
91-
) -> (tree: SourceFileSyntax, lookaheadRanges: LookaheadRanges) {
92-
var parser = Parser(source, maximumNestingLevel: maximumNestingLevel, parseTransition: parseTransition)
93-
return (SourceFileSyntax.parse(from: &parser), parser.lookaheadRanges)
94-
}
95-
"""
96-
)
97-
}
98-
9921
DeclSyntax(
10022
"""
10123
public protocol SyntaxParseable: SyntaxProtocol {
@@ -128,33 +50,6 @@ let parserEntryFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
12850
}
12951

13052
try! ExtensionDeclSyntax("fileprivate extension Parser") {
131-
DeclSyntax(
132-
"""
133-
mutating func parseRemainder<R: RawSyntaxNodeProtocol>(into: R) -> R {
134-
guard !into.raw.kind.isSyntaxCollection, let layout = into.raw.layoutView else {
135-
preconditionFailure("Only support parsing of non-collection layout nodes")
136-
}
137-
138-
let remainingTokens = self.consumeRemainingTokens()
139-
if remainingTokens.isEmpty {
140-
return into
141-
}
142-
143-
let existingUnexpected: [RawSyntax]
144-
if let unexpectedNode = layout.children[layout.children.count - 1] {
145-
precondition(unexpectedNode.is(RawUnexpectedNodesSyntax.self))
146-
existingUnexpected = unexpectedNode.as(RawUnexpectedNodesSyntax.self).elements
147-
} else {
148-
existingUnexpected = []
149-
}
150-
let unexpected = RawUnexpectedNodesSyntax(elements: existingUnexpected + remainingTokens, arena: self.arena)
151-
152-
let withUnexpected = layout.replacingChild(at: layout.children.count - 1, with: unexpected.raw, arena: self.arena)
153-
return R.init(withUnexpected)!
154-
}
155-
"""
156-
)
157-
15853
DeclSyntax(
15954
"""
16055
mutating func parseNonOptionalCodeBlockItem() -> RawCodeBlockItemSyntax {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ let syntaxCollectionsFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
4141
} else {
4242
try EnumDeclSyntax(
4343
"""
44-
public enum Element: SyntaxChildChoices
44+
public enum Element: SyntaxChildChoices, SyntaxHashable
4545
"""
4646
) {
4747
for choiceName in node.elementChoices {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ private func generateSyntaxChildChoices(for child: Child) throws -> EnumDeclSynt
241241
return nil
242242
}
243243

244-
return try! EnumDeclSyntax("public enum \(raw: child.name): SyntaxChildChoices") {
244+
return try! EnumDeclSyntax("public enum \(raw: child.name): SyntaxChildChoices, SyntaxHashable") {
245245
for choice in choices {
246246
DeclSyntax("case `\(choice.varOrCaseName)`(\(raw: choice.syntaxNodeKind.syntaxType))")
247247
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntaxbuilder/ResultBuildersFile.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ let resultBuildersFile = SourceFileSyntax(leadingTrivia: copyrightHeader) {
9090
DeclSyntax(
9191
"""
9292
/// Add all the elements of `expression` to this result builder, effectively flattening them.
93+
///
94+
/// - Note: This overload is disfavored to resolve an ambiguity when both the final result and
95+
/// the elements are expressible by string interpolation. In that case we favor creating a
96+
/// single element from the string literal.
97+
@_disfavoredOverload
9398
public static func buildExpression(_ expression: Self.FinalResult) -> Self.Component {
9499
return expression.map { $0 }
95100
}

CodeGeneration/Sources/generate-swiftsyntax/templates/swiftsyntaxbuilder/SyntaxExpressibleByStringInterpolationConformancesFile.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,11 @@ let syntaxExpressibleByStringInterpolationConformancesFile = SourceFileSyntax(le
2121
for node in SYNTAX_NODES where node.parserFunction != nil {
2222
DeclSyntax("extension \(node.kind.syntaxType): SyntaxExpressibleByStringInterpolation {}")
2323
}
24+
25+
// `SyntaxParsable` conformance for collection nodes is hand-written.
26+
// We also need to hand-write the corresponding `SyntaxExpressibleByStringInterpolation` conformances.
27+
DeclSyntax("extension AccessorDeclListSyntax: SyntaxExpressibleByStringInterpolation {}")
28+
DeclSyntax("extension AttributeListSyntax: SyntaxExpressibleByStringInterpolation {}")
29+
DeclSyntax("extension CodeBlockItemListSyntax: SyntaxExpressibleByStringInterpolation {}")
30+
DeclSyntax("extension MemberBlockItemListSyntax: SyntaxExpressibleByStringInterpolation {}")
2431
}

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ let package = Package(
182182

183183
.target(
184184
name: "SwiftSyntaxMacroExpansion",
185-
dependencies: ["SwiftSyntax", "SwiftSyntaxMacros", "SwiftDiagnostics"],
185+
dependencies: ["SwiftSyntax", "SwiftSyntaxBuilder", "SwiftSyntaxMacros", "SwiftDiagnostics"],
186186
exclude: ["CMakeLists.txt"]
187187
),
188188

Sources/SwiftBasicFormat/BasicFormat.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,14 @@ open class BasicFormat: SyntaxRewriter {
4949
private var previousToken: TokenSyntax? = nil
5050

5151
public init(
52-
indentationWidth: Trivia = .spaces(4),
52+
indentationWidth: Trivia? = nil,
5353
initialIndentation: Trivia = [],
5454
viewMode: SyntaxTreeViewMode = .sourceAccurate
5555
) {
56-
self.indentationWidth = indentationWidth
56+
// Default to 4 spaces if no indentation was passed.
57+
// In the future, we could consider inferring the indentation width from the
58+
// source file to format in case it is already partially formatted.
59+
self.indentationWidth = indentationWidth ?? .spaces(4)
5760
self.indentationStack = [(indentation: initialIndentation, isUserDefined: false)]
5861
super.init(viewMode: viewMode)
5962
}

Sources/SwiftParser/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_swift_host_library(SwiftParser
1010
Attributes.swift
1111
Availability.swift
1212
CharacterInfo.swift
13+
CollectionNodes+Parsable.swift
1314
Declarations.swift
1415
Directives.swift
1516
Expressions.swift
@@ -21,6 +22,7 @@ add_swift_host_library(SwiftParser
2122
Nominals.swift
2223
Parameters.swift
2324
Parser.swift
25+
ParseSourceFile.swift
2426
Patterns.swift
2527
TokenSpec.swift
2628
TokenSpecSet.swift
@@ -37,7 +39,7 @@ add_swift_host_library(SwiftParser
3739
Types.swift
3840

3941
generated/IsLexerClassified.swift
40-
generated/Parser+Entry.swift
42+
generated/LayoutNodes+Parsable.swift
4143
generated/Parser+TokenSpecSet.swift
4244
generated/TokenSpecStaticMembers.swift
4345

0 commit comments

Comments
 (0)