Skip to content

Commit 69e3469

Browse files
committed
Rename the incremental source edit to IncrementalEdit
This was called `SourceEdit`, which would be nice to reserve for refactorings rather than incremental parsing. Ideally we'd also move all the incremental parsing types into `SwiftParser` as well. (cherry picked from commit 40f2954)
1 parent 99c9bea commit 69e3469

File tree

7 files changed

+177
-191
lines changed

7 files changed

+177
-191
lines changed

Sources/SwiftSyntax/IncrementalParseTransition.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,11 @@ public struct ConcurrentEdits {
9797

9898
/// The raw concurrent edits. Are guaranteed to satisfy the requirements
9999
/// stated above.
100-
public let edits: [SourceEdit]
100+
public let edits: [IncrementalEdit]
101101

102102
/// Initialize this struct from edits that are already in a concurrent form
103103
/// and are guaranteed to satisfy the requirements posed above.
104-
public init(concurrent: [SourceEdit]) throws {
104+
public init(concurrent: [IncrementalEdit]) throws {
105105
if !Self.isValidConcurrentEditArray(concurrent) {
106106
throw ConcurrentEditsError.editsNotConcurrent
107107
}
@@ -117,7 +117,7 @@ public struct ConcurrentEdits {
117117
/// - insert 'z' at offset 2
118118
/// to '012345' results in 'xyz012345'.
119119

120-
public init(fromSequential sequentialEdits: [SourceEdit]) {
120+
public init(fromSequential sequentialEdits: [IncrementalEdit]) {
121121
do {
122122
try self.init(concurrent: Self.translateSequentialEditsToConcurrentEdits(sequentialEdits))
123123
} catch {
@@ -128,7 +128,7 @@ public struct ConcurrentEdits {
128128
/// Construct a concurrent edits struct from a single edit. For a single edit,
129129
/// there is no differentiation between being it being applied concurrently
130130
/// or sequentially.
131-
public init(_ single: SourceEdit) {
131+
public init(_ single: IncrementalEdit) {
132132
do {
133133
try self.init(concurrent: [single])
134134
} catch {
@@ -137,24 +137,24 @@ public struct ConcurrentEdits {
137137
}
138138

139139
private static func translateSequentialEditsToConcurrentEdits(
140-
_ edits: [SourceEdit]
141-
) -> [SourceEdit] {
142-
var concurrentEdits: [SourceEdit] = []
140+
_ edits: [IncrementalEdit]
141+
) -> [IncrementalEdit] {
142+
var concurrentEdits: [IncrementalEdit] = []
143143
for editToAdd in edits {
144144
var editToAdd = editToAdd
145145
var editIndiciesMergedWithNewEdit: [Int] = []
146146
for (index, existingEdit) in concurrentEdits.enumerated() {
147147
if existingEdit.replacementRange.intersectsOrTouches(editToAdd.range) {
148148
let intersectionLength =
149149
existingEdit.replacementRange.intersected(editToAdd.range).length
150-
editToAdd = SourceEdit(
150+
editToAdd = IncrementalEdit(
151151
offset: Swift.min(existingEdit.offset, editToAdd.offset),
152152
length: existingEdit.length + editToAdd.length - intersectionLength,
153153
replacementLength: existingEdit.replacementLength + editToAdd.replacementLength - intersectionLength
154154
)
155155
editIndiciesMergedWithNewEdit.append(index)
156156
} else if existingEdit.offset < editToAdd.endOffset {
157-
editToAdd = SourceEdit(
157+
editToAdd = IncrementalEdit(
158158
offset: editToAdd.offset - existingEdit.replacementLength + existingEdit.length,
159159
length: editToAdd.length,
160160
replacementLength: editToAdd.replacementLength
@@ -175,7 +175,7 @@ public struct ConcurrentEdits {
175175
return concurrentEdits
176176
}
177177

178-
private static func isValidConcurrentEditArray(_ edits: [SourceEdit]) -> Bool {
178+
private static func isValidConcurrentEditArray(_ edits: [IncrementalEdit]) -> Bool {
179179
// Not quite sure if we should disallow creating an `IncrementalParseTransition`
180180
// object without edits but there doesn't seem to be much benefit if we do,
181181
// and there are 'lit' tests that want to test incremental re-parsing without edits.
@@ -195,7 +195,7 @@ public struct ConcurrentEdits {
195195
}
196196

197197
/// **Public for testing purposes only**
198-
public static func _isValidConcurrentEditArray(_ edits: [SourceEdit]) -> Bool {
198+
public static func _isValidConcurrentEditArray(_ edits: [IncrementalEdit]) -> Bool {
199199
return isValidConcurrentEditArray(edits)
200200
}
201201
}

Sources/SwiftSyntax/Utils.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public struct ByteSourceRange: Equatable {
4747
}
4848
}
4949

50-
public struct SourceEdit: Equatable {
50+
public struct IncrementalEdit: Equatable {
5151
/// The byte range of the original source buffer that the edit applies to.
5252
public let range: ByteSourceRange
5353
/// The length of the edit replacement in UTF8 bytes.

Sources/_SwiftSyntaxTestSupport/IncrementalParseTestUtils.swift

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,83 @@ public struct ReusedNodeSpec {
135135
self.line = line
136136
}
137137
}
138+
139+
/// Get `ConcurrentEdits` in source whose edited zones are marked with markers
140+
/// Also extract the markers from source to get original source and edited source
141+
///
142+
/// `⏩️` is *start marker*, `⏸️` is *separate marker*, `⏪️` is *end marker*
143+
/// Contents between `⏩️` and `⏸️` are source text that before modification, contents
144+
/// betwwen `⏸️` and `⏪️` are source text that after modification
145+
/// i.e. `⏩️foo⏸️bar⏪️`, the original source is `foo` and the edited source is `bar`
146+
public func getEditsAndSources(_ source: String) -> (edits: ConcurrentEdits, orignialSource: Substring, editedSource: Substring) {
147+
var editedSource = Substring()
148+
var originalSource = Substring()
149+
var concurrentEdits: [IncrementalEdit] = []
150+
151+
var lastStartIndex = source.startIndex
152+
while let startIndex = source[lastStartIndex...].firstIndex(where: { $0 == "⏩️" }),
153+
let separateIndex = source[startIndex...].firstIndex(where: { $0 == "⏸️" }),
154+
let endIndex = source[separateIndex...].firstIndex(where: { $0 == "⏪️" })
155+
{
156+
157+
originalSource += source[lastStartIndex..<startIndex]
158+
let edit = IncrementalEdit(
159+
offset: originalSource.utf8.count,
160+
length: source.utf8.distance(
161+
from: source.index(after: startIndex),
162+
to: separateIndex
163+
),
164+
replacementLength: source.utf8.distance(
165+
from: source.index(after: separateIndex),
166+
to: endIndex
167+
)
168+
)
169+
originalSource += source[source.index(after: startIndex)..<separateIndex]
170+
171+
editedSource += source[lastStartIndex..<startIndex] + source[source.index(after: separateIndex)..<endIndex]
172+
173+
concurrentEdits.append(edit)
174+
175+
lastStartIndex = source.index(after: endIndex)
176+
}
177+
178+
editedSource += source[lastStartIndex...]
179+
originalSource += source[lastStartIndex...]
180+
181+
do {
182+
let edits = try ConcurrentEdits(concurrent: concurrentEdits)
183+
return (edits, originalSource, editedSource)
184+
} catch {
185+
fatalError("ConcurrentEdits created by the test case do not satisfy ConcurrentEdits requirements, please check the test setup")
186+
}
187+
}
188+
189+
/// Apply the given edits to `testString` and return the resulting string.
190+
/// `concurrent` specifies whether the edits should be interpreted as being
191+
/// applied sequentially or concurrently.
192+
public func applyEdits(
193+
_ edits: [IncrementalEdit],
194+
concurrent: Bool,
195+
to testString: String,
196+
replacementChar: Character = "?"
197+
) -> String {
198+
guard let replacementAscii = replacementChar.asciiValue else {
199+
fatalError("replacementChar must be an ASCII character")
200+
}
201+
var edits = edits
202+
if concurrent {
203+
XCTAssert(ConcurrentEdits._isValidConcurrentEditArray(edits))
204+
205+
// If the edits are concurrent, sorted and not overlapping (as guaranteed by
206+
// the check above, we can apply them sequentially to the string in reverse
207+
// order because later edits don't affect earlier edits.
208+
edits = edits.reversed()
209+
}
210+
var bytes = Array(testString.utf8)
211+
for edit in edits {
212+
assert(edit.endOffset <= bytes.count)
213+
bytes.removeSubrange(edit.offset..<edit.endOffset)
214+
bytes.insert(contentsOf: [UInt8](repeating: replacementAscii, count: edit.replacementLength), at: edit.offset)
215+
}
216+
return String(bytes: bytes, encoding: .utf8)!
217+
}

Sources/_SwiftSyntaxTestSupport/SourceEditsTestUtils.swift

Lines changed: 0 additions & 94 deletions
This file was deleted.

Sources/lit-test-helper/main.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,11 @@ func printHelp() {
8989
}
9090

9191
extension CommandLineArguments {
92-
func getIncrementalEdits() throws -> [IncrementalEdit] {
92+
func getIncrementalEdits() throws -> [IncrementalEditSpec] {
9393
let regex = try NSRegularExpression(
9494
pattern: "([0-9]+):([0-9]+)-([0-9]+):([0-9]+)=(.*)"
9595
)
96-
var parsedEdits = [IncrementalEdit]()
96+
var parsedEdits = [IncrementalEditSpec]()
9797
let editArgs = try self.getValues("-incremental-edit")
9898
for edit in editArgs {
9999
guard
@@ -111,7 +111,7 @@ extension CommandLineArguments {
111111
let region = getSourceRegion(match, text: edit)
112112
let replacement = match.match(at: 5, text: edit)
113113
parsedEdits.append(
114-
IncrementalEdit(
114+
IncrementalEditSpec(
115115
region: region,
116116
replacement: replacement
117117
)
@@ -232,7 +232,7 @@ struct SourceRegion {
232232
let endColumn: Int
233233
}
234234

235-
struct IncrementalEdit {
235+
struct IncrementalEditSpec {
236236
let region: SourceRegion
237237
let replacement: String
238238
}
@@ -312,8 +312,8 @@ func getByteRange(
312312

313313
func parseIncrementalEditArguments(
314314
args: CommandLineArguments
315-
) throws -> [SourceEdit] {
316-
var edits = [SourceEdit]()
315+
) throws -> [IncrementalEdit] {
316+
var edits = [IncrementalEdit]()
317317
let argEdits = try args.getIncrementalEdits()
318318
let preEditURL =
319319
URL(fileURLWithPath: try args.getRequired("-old-source-file"))
@@ -326,7 +326,7 @@ func parseIncrementalEditArguments(
326326
argName: "-incremental-edit"
327327
)
328328
let replacementLength = argEdit.replacement.utf8.count
329-
edits.append(SourceEdit(range: range, replacementLength: replacementLength))
329+
edits.append(IncrementalEdit(range: range, replacementLength: replacementLength))
330330
}
331331
return edits
332332
}

0 commit comments

Comments
 (0)