Skip to content

Commit ea592ba

Browse files
committed
(WIP) Add diagnostics for reasync in getter declaration &
Add a convenient initializer for RawUnexpectedNodesSyntax & Update test cases
1 parent 85ca7c5 commit ea592ba

File tree

6 files changed

+87
-37
lines changed

6 files changed

+87
-37
lines changed

Sources/SwiftParser/Declarations.swift

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1713,20 +1713,36 @@ extension Parser {
17131713

17141714
var effectSpecifiers = self.parseDeclEffectSpecifiers()
17151715

1716-
if introducer.kind == .get,
1717-
let throwSpecifier = effectSpecifiers?.throwsSpecifier,
1718-
throwSpecifier.tokenText == "rethrows" {
1719-
1720-
let unexpected = RawUnexpectedNodesSyntax([ effectSpecifiers?.unexpectedBetweenAsyncSpecifierAndThrowsSpecifier, RawUnexpectedNodesSyntax([throwSpecifier], arena: self.arena)], arena: self.arena)
1721-
1722-
effectSpecifiers = RawDeclEffectSpecifiersSyntax(
1723-
effectSpecifiers?.unexpectedBeforeAsyncSpecifier,
1724-
asyncSpecifier: effectSpecifiers?.asyncSpecifier,
1725-
unexpected,
1726-
throwsSpecifier: nil,
1727-
effectSpecifiers?.unexpectedAfterThrowsSpecifier,
1728-
arena: self.arena
1729-
)
1716+
if introducer.kind == .get {
1717+
if let asyncSpecifier = effectSpecifiers?.asyncSpecifier,
1718+
asyncSpecifier.tokenText == Keyword.reasync.defaultText {
1719+
1720+
let unexpected = RawUnexpectedNodesSyntax(combining: effectSpecifiers?.unexpectedBetweenAsyncSpecifierAndThrowsSpecifier, asyncSpecifier, arena: self.arena)
1721+
1722+
effectSpecifiers = RawDeclEffectSpecifiersSyntax(
1723+
effectSpecifiers?.unexpectedBeforeAsyncSpecifier,
1724+
asyncSpecifier: nil,
1725+
unexpected,
1726+
throwsSpecifier: effectSpecifiers?.throwsSpecifier,
1727+
effectSpecifiers?.unexpectedAfterThrowsSpecifier,
1728+
arena: self.arena
1729+
)
1730+
}
1731+
1732+
if let throwSpecifier = effectSpecifiers?.throwsSpecifier,
1733+
throwSpecifier.tokenText == Keyword.rethrows.defaultText {
1734+
1735+
let unexpected = RawUnexpectedNodesSyntax(combining: effectSpecifiers?.unexpectedBetweenAsyncSpecifierAndThrowsSpecifier, throwSpecifier, arena: self.arena)
1736+
1737+
effectSpecifiers = RawDeclEffectSpecifiersSyntax(
1738+
effectSpecifiers?.unexpectedBeforeAsyncSpecifier,
1739+
asyncSpecifier: effectSpecifiers?.asyncSpecifier,
1740+
unexpected,
1741+
throwsSpecifier: nil,
1742+
effectSpecifiers?.unexpectedAfterThrowsSpecifier,
1743+
arena: self.arena
1744+
)
1745+
}
17301746
}
17311747

17321748
let body = self.parseOptionalCodeBlock()

Sources/SwiftParser/SyntaxUtils.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ extension RawUnexpectedNodesSyntax {
8080
init?<T1: UnexpectedNodesCombinable, T2: UnexpectedNodesCombinable, T3: UnexpectedNodesCombinable>(combining syntax1: T1, _ syntax2: T2, _ syntax3: T3, arena: __shared SyntaxArena) {
8181
self.init(syntax1.elements + syntax2.elements + syntax3.elements, arena: arena)
8282
}
83+
84+
init?<T1: UnexpectedNodesCombinable, T2: UnexpectedNodesCombinable>(conbining optionalSyntax1: T1?, _ optionalSyntax2: T2?, arena: __shared SyntaxArena) {
85+
if let syntax1 = optionalSyntax1,
86+
let syntax2 = optionalSyntax2 {
87+
self.init(syntax1.elements + syntax2.elements, arena: arena)
88+
} else if let syntax1 = optionalSyntax1 {
89+
self.init(elements: syntax1.elements, arena: arena)
90+
} else if let syntax2 = optionalSyntax2 {
91+
self.init(elements: syntax2.elements, arena: arena)
92+
} else {
93+
return nil
94+
}
95+
}
8396
}
8497

8598
// MARK: - Misc

Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,22 @@ public class ParseDiagnosticsGenerator: SyntaxAnyVisitor {
390390
return .skipChildren
391391
}
392392

393-
if let unexpectedBetweenAsyncSpecifierAndThrowsSpecifier = node.effectSpecifiers?.unexpectedBetweenAsyncSpecifierAndThrowsSpecifier,
394-
unexpectedBetweenAsyncSpecifierAndThrowsSpecifier.tokens(viewMode: .sourceAccurate).contains(where: {$0.tokenKind == .keyword(.rethrows)}) == true {
395-
addDiagnostic(
396-
unexpectedBetweenAsyncSpecifierAndThrowsSpecifier, .misspelledThrowsInEffectfulProperties,
397-
handledNodes: [unexpectedBetweenAsyncSpecifierAndThrowsSpecifier.id])
393+
if let unexpectedBetweenAsyncSpecifierAndThrowsSpecifier = node.effectSpecifiers?.unexpectedBetweenAsyncSpecifierAndThrowsSpecifier {
394+
if let unexpectedRethrows = unexpectedBetweenAsyncSpecifierAndThrowsSpecifier.tokens(viewMode: .sourceAccurate).first(where: { $0.tokenKind == .keyword(.rethrows)}) {
395+
addDiagnostic(
396+
unexpectedRethrows,
397+
.misspelledThrowsInEffectfulProperties,
398+
handledNodes: [unexpectedRethrows.id]
399+
)
400+
}
401+
402+
if let unexpectedReasync = unexpectedBetweenAsyncSpecifierAndThrowsSpecifier.tokens(viewMode: .sourceAccurate).first(where: {$0.tokenKind == .keyword(.reasync)}) {
403+
addDiagnostic(
404+
unexpectedReasync,
405+
.misspelledAsyncInEffectfulProperties,
406+
handledNodes: [unexpectedReasync.id]
407+
)
408+
}
398409
}
399410

400411
return .visitChildren

Sources/SwiftParserDiagnostics/ParserDiagnosticMessages.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ extension DiagnosticMessage where Self == StaticParserError {
176176
public static var misspelledThrowsInEffectfulProperties: Self {
177177
.init("only function declarations may be marked 'rethrows'; did you mean 'throws'?")
178178
}
179+
public static var misspelledAsyncInEffectfulProperties: Self {
180+
.init("only function declarations may be marked 'reasync'; did you mean 'async'?")
181+
}
179182
public static var multiLineStringLiteralMustBeginOnNewLine: Self {
180183
.init("multi-line string literal content must begin on a new line")
181184
}

Tests/SwiftParserTest/DeclarationTests.swift

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -733,9 +733,12 @@ final class DeclarationTests: XCTestCase {
733733
assertParse(
734734
"""
735735
var bad2 : Int {
736-
get reasync { 0 }
736+
get 1️⃣reasync { 0 }
737737
}
738-
"""
738+
""",
739+
diagnostics: [
740+
DiagnosticSpec(message: "only function declarations may be marked 'reasync'; did you mean 'async'?")
741+
]
739742
)
740743
}
741744

@@ -761,7 +764,7 @@ final class DeclarationTests: XCTestCase {
761764
assertParse(
762765
"""
763766
protocol P {
764-
var prop : Int { get 1️⃣bogus rethrows set }
767+
var prop : Int { get 1️⃣bogus 2️⃣rethrows set }
765768
}
766769
""",
767770
substructure: Syntax(
@@ -770,16 +773,20 @@ final class DeclarationTests: XCTestCase {
770773
AccessorDeclSyntax(
771774
accessorKind: .keyword(.get),
772775
effectSpecifiers: DeclEffectSpecifiersSyntax(
773-
UnexpectedNodesSyntax([TokenSyntax.identifier("bogus")]),
774-
throwsSpecifier: .keyword(.rethrows)
776+
UnexpectedNodesSyntax([
777+
TokenSyntax.identifier("bogus"),TokenSyntax.keyword(.rethrows)
778+
]
779+
),
780+
throwsSpecifier: nil
775781
)
776782
),
777783
AccessorDeclSyntax(accessorKind: .keyword(.set)),
778784
])
779785
)
780786
),
781787
diagnostics: [
782-
DiagnosticSpec(message: "unexpected code 'bogus' before effect specifiers")
788+
DiagnosticSpec(message: "unexpected code 'bogus rethrows' before effect specifiers"),
789+
DiagnosticSpec(locationMarker: "2️⃣", message: "only function declarations may be marked 'rethrows'; did you mean 'throws'?")
783790
]
784791
)
785792
}

Tests/SwiftParserTest/translated/EffectfulPropertiesTests.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,13 @@ final class EffectfulPropertiesTests: XCTestCase {
188188
assertParse(
189189
"""
190190
var bad2 : Int {
191-
get reasync { 0 }
191+
get 1️⃣reasync { 0 }
192192
set reasync { }
193193
}
194194
""",
195195
diagnostics: [
196196
// TODO: Old parser expected error on line 2: expected '{' to start getter definition
197+
DiagnosticSpec(message: "only function declarations may be marked 'reasync'; did you mean 'async'?")
197198
]
198199
)
199200
}
@@ -240,13 +241,12 @@ final class EffectfulPropertiesTests: XCTestCase {
240241
assertParse(
241242
"""
242243
var bad5 : Int {
243-
get 1️⃣bogus rethrows {}
244+
get 1️⃣bogus 2️⃣rethrows {}
244245
}
245246
""",
246247
diagnostics: [
247-
// TODO: Should produce two diagnostics?
248-
//DiagnosticSpec(message: "unexpected code 'bogus' before effect specifiers"),
249-
DiagnosticSpec(message: "only function declarations may be marked 'rethrows'; did you mean 'throws'?")
248+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'bogus rethrows' before effect specifiers"),
249+
DiagnosticSpec(locationMarker: "2️⃣", message: "only function declarations may be marked 'rethrows'; did you mean 'throws'?")
250250
]
251251
)
252252
}
@@ -293,23 +293,23 @@ final class EffectfulPropertiesTests: XCTestCase {
293293
}
294294

295295
func testEffectfulProperties20() {
296-
// TODO: diagnostics at 1️⃣ should be valid
297296
assertParse(
298297
"""
299298
protocol BadP {
300-
var prop2 : Int { get 2️⃣bogus rethrows set }
299+
var prop2 : Int { get 1️⃣bogus 2️⃣rethrows set }
301300
var prop3 : Int { get 3️⃣rethrows 4️⃣bogus set }
302-
var prop4 : Int { get reasync 5️⃣bogus set }
303-
var prop5 : Int { get throws 6️⃣async }
301+
var prop4 : Int { get 5️⃣reasync 6️⃣bogus set }
302+
var prop5 : Int { get throws 7️⃣async }
304303
}
305304
""",
306305
diagnostics: [
307-
// DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'bogus' before effect specifiers"),
306+
DiagnosticSpec(locationMarker: "1️⃣", message: "unexpected code 'bogus rethrows' before effect specifiers"),
308307
DiagnosticSpec(locationMarker: "2️⃣", message: "only function declarations may be marked 'rethrows'; did you mean 'throws'?"),
309308
DiagnosticSpec(locationMarker: "3️⃣", message: "only function declarations may be marked 'rethrows'; did you mean 'throws'?"),
310309
DiagnosticSpec(locationMarker: "4️⃣", message: "unexpected code 'bogus set' in variable"),
311-
DiagnosticSpec(locationMarker: "5️⃣", message: "unexpected code 'bogus set' in variable"),
312-
DiagnosticSpec(locationMarker: "6️⃣", message: "'async' must precede 'throws'"),
310+
DiagnosticSpec(locationMarker: "5️⃣", message: "only function declarations may be marked 'reasync'; did you mean 'async'?"),
311+
DiagnosticSpec(locationMarker: "6️⃣", message: "unexpected code 'bogus set' in variable"),
312+
DiagnosticSpec(locationMarker: "7️⃣", message: "'async' must precede 'throws'"),
313313
]
314314
)
315315
}

0 commit comments

Comments
 (0)