Skip to content

Commit 7bc8b94

Browse files
committed
Add trailing comma support in cases missing from Swift 6.1
1 parent a0400e0 commit 7bc8b94

File tree

9 files changed

+161
-24
lines changed

9 files changed

+161
-24
lines changed

Sources/SwiftParser/Attributes.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ extension Parser {
362362
let additionalArgs = self.parseArgumentListElements(
363363
pattern: .none,
364364
flavor: .attributeArguments,
365-
allowTrailingComma: false
365+
allowTrailingComma: true
366366
)
367367
return [roleElement] + additionalArgs
368368
}
@@ -852,6 +852,11 @@ extension Parser {
852852
arena: self.arena
853853
)
854854
)
855+
856+
// If this was a trailing closure then there are no more elements
857+
if self.at(.rightParen) {
858+
break
859+
}
855860
} while keepGoing != nil
856861
return RawBackDeployedAttributeArgumentsSyntax(
857862
unexpectedBeforeLabel,
@@ -883,6 +888,11 @@ extension Parser {
883888
arena: self.arena
884889
)
885890
)
891+
892+
// If this was a trailing closure then there are no more elements
893+
if self.at(.rightParen) {
894+
break
895+
}
886896
} while keepGoing != nil
887897

888898
return RawOriginallyDefinedInAttributeArgumentsSyntax(
@@ -1001,6 +1011,11 @@ extension Parser {
10011011
arena: self.arena
10021012
)
10031013
)
1014+
1015+
// If this was a trailing closure then there are no more elements
1016+
if self.at(.rightParen) {
1017+
break
1018+
}
10041019
} while keepGoing != nil
10051020

10061021
return RawDocumentationAttributeArgumentListSyntax(elements: arguments, arena: self.arena)

Sources/SwiftParser/Availability.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ extension Parser {
4747
arena: self.arena
4848
)
4949
)
50+
51+
// If this was a trailing closure, there are no more elements
52+
if self.at(.rightParen) {
53+
break
54+
}
5055
} while keepGoing != nil
5156
&& self.hasProgressed(&availabilityArgumentProgress)
5257
}

Sources/SwiftParser/Nominals.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,11 @@ extension Parser {
361361
arena: self.arena
362362
)
363363
)
364+
365+
// If this was a trailing comma, there are no more elements
366+
if at(prefix: ">") {
367+
break
368+
}
364369
} while keepGoing != nil && self.hasProgressed(&loopProgress)
365370
}
366371
let rangle = self.expectWithoutRecovery(prefix: ">", as: .rightAngle)

Sources/SwiftParser/Types.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,11 @@ extension Parser {
430430
arena: self.arena
431431
)
432432
)
433+
434+
// If this was a trailing comma, we're done parsing the list
435+
if self.at(prefix: ">") {
436+
break
437+
}
433438
} while keepGoing != nil && self.hasProgressed(&loopProgress)
434439
}
435440

Tests/SwiftParserTest/AttributeTests.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,13 +470,31 @@ final class AttributeTests: ParserTestCase {
470470
"""
471471
)
472472

473+
assertParse(
474+
"""
475+
@backDeployed(
476+
before: macOS 12.0,
477+
)
478+
struct Foo {}
479+
"""
480+
)
481+
473482
assertParse(
474483
"""
475484
@backDeployed(before: macos 12.0, iOS 15.0)
476485
struct Foo {}
477486
"""
478487
)
479488

489+
assertParse(
490+
"""
491+
@backDeployed(
492+
before: macos 12.0,
493+
iOS 15.0,)
494+
struct Foo {}
495+
"""
496+
)
497+
480498
assertParse(
481499
"""
482500
@available(macOS 11.0, *)
@@ -537,6 +555,16 @@ final class AttributeTests: ParserTestCase {
537555
"""
538556
)
539557

558+
assertParse(
559+
"""
560+
@_originallyDefinedIn(
561+
module: "ToasterKit",
562+
macOS 10.15,
563+
)
564+
struct Vehicle {}
565+
"""
566+
)
567+
540568
assertParse(
541569
"""
542570
@_originallyDefinedIn(module: "ToasterKit", macOS 10.15, iOS 13)
@@ -846,6 +874,26 @@ final class AttributeTests: ParserTestCase {
846874
}
847875
"""
848876
)
877+
878+
assertParse(
879+
"""
880+
@attached(
881+
member,
882+
names: named(deinit),
883+
)
884+
macro m()
885+
"""
886+
)
887+
888+
assertParse(
889+
"""
890+
@attached(
891+
extension,
892+
conformances: P1, P2,
893+
)
894+
macro AddAllConformances()
895+
"""
896+
)
849897
}
850898

851899
func testAttachedExtensionAttribute() {

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3529,4 +3529,31 @@ final class DeclarationTests: ParserTestCase {
35293529
]
35303530
)
35313531
}
3532+
3533+
func testTrailingCommas() {
3534+
assertParse(
3535+
"""
3536+
protocol Baaz<
3537+
Foo,
3538+
Bar,
3539+
> {
3540+
associatedtype Foo
3541+
associatedtype Bar
3542+
}
3543+
"""
3544+
)
3545+
3546+
assertParse(
3547+
"""
3548+
struct Foo<
3549+
T1,
3550+
T2,
3551+
T3,
3552+
>: Baaz<
3553+
T1,
3554+
T2,
3555+
> {}
3556+
"""
3557+
)
3558+
}
35323559
}

Tests/SwiftParserTest/TypeTests.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,44 @@ final class TypeTests: ParserTestCase {
734734
fixedSource: "func foo(test: nonisolated(nonsendinghello) () async -> Void)"
735735
)
736736
}
737+
738+
func testTrailingCommas() {
739+
assertParse(
740+
"""
741+
let foo: (
742+
bar: String,
743+
quux: String,
744+
)
745+
"""
746+
)
747+
748+
assertParse(
749+
"""
750+
let closure: (
751+
String,
752+
String,
753+
) -> (
754+
bar: String,
755+
quux: String,
756+
)
757+
"""
758+
)
759+
760+
assertParse(
761+
"""
762+
struct Foo<T1, T2, T3,> {}
763+
764+
typealias Bar<
765+
T1,
766+
T2,
767+
> = Foo<
768+
T1,
769+
T2,
770+
Bool,
771+
>
772+
"""
773+
)
774+
}
737775
}
738776

739777
final class InlineArrayTypeTests: ParserTestCase {

Tests/SwiftParserTest/translated/AvailabilityQueryTests.swift

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -400,17 +400,7 @@ final class AvailabilityQueryTests: ParserTestCase {
400400
"""
401401
if #available(OSX 10.51,1️⃣) {
402402
}
403-
""",
404-
diagnostics: [
405-
DiagnosticSpec(
406-
message: "expected version restriction in availability argument",
407-
fixIts: ["insert version restriction"]
408-
)
409-
],
410-
fixedSource: """
411-
if #available(OSX 10.51, <#identifier#>) {
412-
}
413-
"""
403+
"""
414404
)
415405
}
416406

Tests/SwiftParserTest/translated/AvailabilityQueryUnavailabilityTests.swift

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -381,19 +381,9 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase {
381381
func testAvailabilityQueryUnavailability23() {
382382
assertParse(
383383
"""
384-
if #unavailable(OSX 10.51,1️⃣) {
384+
if #unavailable(OSX 10.51,) {
385385
}
386-
""",
387-
diagnostics: [
388-
DiagnosticSpec(
389-
message: "expected version restriction in availability argument",
390-
fixIts: ["insert version restriction"]
391-
)
392-
],
393-
fixedSource: """
394-
if #unavailable(OSX 10.51, <#identifier#>) {
395-
}
396-
"""
386+
"""
397387
)
398388
}
399389

@@ -611,4 +601,18 @@ final class AvailabilityQueryUnavailabilityTests: ParserTestCase {
611601
]
612602
)
613603
}
604+
605+
func testTrailingComma() {
606+
assertParse(
607+
"""
608+
func fooDeprecated() {
609+
if #available(
610+
iOS 18.0,
611+
macOS 14.0,
612+
*,
613+
) {}
614+
}
615+
"""
616+
)
617+
}
614618
}

0 commit comments

Comments
 (0)