Skip to content

Commit b6d7e69

Browse files
authored
Merge pull request #311 from ahoppen/pr/throwing-concurrent-edits
Make `ConcurrentEdits.init(concurrent:)` throw instead of crash if edits are not concurrent
2 parents 717dbba + 2ba541c commit b6d7e69

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

Sources/SwiftSyntax/IncrementalParseTransition.swift

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public final class IncrementalParseTransition {
6363
reusedNodeDelegate: IncrementalParseReusedNodeDelegate? = nil) {
6464
self.init(
6565
previousTree: previousTree,
66-
edits: ConcurrentEdits(concurrent: edits),
66+
edits: try! ConcurrentEdits(concurrent: edits),
6767
reusedNodeDelegate: reusedNodeDelegate
6868
)
6969
}
@@ -101,14 +101,27 @@ fileprivate extension Sequence where Element: Comparable {
101101
/// 1. not be overlapping.
102102
/// 2. be in increasing source offset order.
103103
public struct ConcurrentEdits {
104+
enum ConcurrentEditsError: Error, CustomStringConvertible {
105+
case editsNotConcurrent
106+
107+
var description: String {
108+
switch self {
109+
case .editsNotConcurrent:
110+
return "Edits passed to ConcurrentEdits(concurrent:) does not satisfy the requirements posed by ConcurrentEdits"
111+
}
112+
}
113+
}
114+
104115
/// The raw concurrent edits. Are guaranteed to satisfy the requirements
105116
/// stated above.
106117
public let edits: [SourceEdit]
107118

108119
/// Initialize this struct from edits that are already in a concurrent form
109120
/// and are guaranteed to satisfy the requirements posed above.
110-
public init(concurrent: [SourceEdit]) {
111-
precondition(Self.isValidConcurrentEditArray(concurrent))
121+
public init(concurrent: [SourceEdit]) throws {
122+
if !Self.isValidConcurrentEditArray(concurrent) {
123+
throw ConcurrentEditsError.editsNotConcurrent
124+
}
112125
self.edits = concurrent
113126
}
114127

@@ -122,14 +135,22 @@ public struct ConcurrentEdits {
122135
/// to '012345' results in 'xyz012345'.
123136

124137
public init(fromSequential sequentialEdits: [SourceEdit]) {
125-
self.init(concurrent: Self.translateSequentialEditsToConcurrentEdits(sequentialEdits))
138+
do {
139+
try self.init(concurrent: Self.translateSequentialEditsToConcurrentEdits(sequentialEdits))
140+
} catch {
141+
fatalError("ConcurrentEdits created by translateSequentialEditsToConcurrentEdits do not satisfy ConcurrentEdits requirements")
142+
}
126143
}
127144

128145
/// Construct a concurrent edits struct from a single edit. For a single edit,
129146
/// there is no differentiation between being it being applied concurrently
130147
/// or sequentially.
131148
public init(_ single: SourceEdit) {
132-
self.init(concurrent: [single])
149+
do {
150+
try self.init(concurrent: [single])
151+
} catch {
152+
fatalError("A single edit doesn't satisfy the ConcurrentEdits requirements?")
153+
}
133154
}
134155

135156
private static func translateSequentialEditsToConcurrentEdits(

Sources/lit-test-helper/main.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ func performParseIncremental(args: CommandLineArguments) throws {
291291
let regionCollector = IncrementalParseReusedNodeCollector()
292292
let editTransition = IncrementalParseTransition(
293293
previousTree: preEditTree,
294-
edits: ConcurrentEdits(concurrent: edits),
294+
edits: try ConcurrentEdits(concurrent: edits),
295295
reusedNodeDelegate: regionCollector
296296
)
297297

Tests/SwiftSyntaxTest/SequentialToConcurrentEditTranslationTests.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,20 @@ func verifySequentialToConcurrentTranslation(
6262
)
6363
}
6464

65-
6665
final class TranslateSequentialToConcurrentEditsTests: XCTestCase {
6766
func testEmpty() throws {
6867
verifySequentialToConcurrentTranslation([], [])
6968
}
7069

70+
func testCreatingConcurrentFailsIfEditsDoNotSatisfyConcurrentRequirements() {
71+
XCTAssertThrowsError(try {
72+
try ConcurrentEdits(concurrent: [
73+
SourceEdit(offset: 5, length: 1, replacementLength: 0),
74+
SourceEdit(offset: 5, length: 1, replacementLength: 0)
75+
])
76+
}())
77+
}
78+
7179
func testSingleEdit1() throws {
7280
verifySequentialToConcurrentTranslation([
7381
SourceEdit(offset: 5, length: 1, replacementLength: 0)

0 commit comments

Comments
 (0)