Skip to content

Commit e6b82d0

Browse files
committed
Add helper function for getting the ConcurrentEdits of two strings
1 parent 8311d8d commit e6b82d0

File tree

1 file changed

+91
-15
lines changed

1 file changed

+91
-15
lines changed

Tests/SwiftParserTest/IncrementalParsingTests.swift

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,109 @@ import XCTest
1414
import SwiftSyntax
1515
import SwiftParser
1616

17+
/// Returns the `ConcurrentEdits`s to transition from `base` to `new`.
18+
func getConcurrentEdits(from base: String, to new: String) -> ConcurrentEdits {
19+
let diffCollection = new.difference(from: base)
20+
21+
let diffArray: [(offset: Int, isInsert: Bool)] =
22+
diffCollection
23+
.map { diff in
24+
switch diff {
25+
case .remove(offset: let offset, element: _, associatedWith: _):
26+
return (offset, false)
27+
case .insert(offset: let offset, element: _, associatedWith: _):
28+
return (offset, true)
29+
}
30+
}
31+
.sorted {
32+
// Change.remove should prior to Change.insert
33+
if $0.0 < $1.0 {
34+
return true
35+
} else if $0.0 == $1.0 {
36+
return !$0.1
37+
} else {
38+
return false
39+
}
40+
}
41+
42+
let sourceEdits = diffArray.map({
43+
return $0.1 ? SourceEdit(offset: $0.0, length: 0, replacementLength: 1) : SourceEdit(offset: $0.0, length: 1, replacementLength: 0)
44+
})
45+
46+
return ConcurrentEdits(fromSequential: sourceEdits)
47+
}
48+
1749
public class IncrementalParsingTests: XCTestCase {
1850

51+
public func testDiffOfTwoStringsSimple() throws {
52+
let s1 = "struct A { func f() {"
53+
let s2 = "struct AA { func f() {"
54+
55+
let diffs = getConcurrentEdits(from: s1, to: s2)
56+
XCTAssertEqual(diffs.edits.count, 1)
57+
58+
let firstDiff = try XCTUnwrap(diffs.edits.first)
59+
XCTAssert(firstDiff == SourceEdit(offset: 8, length: 0, replacementLength: 1))
60+
XCTAssertEqual(firstDiff, SourceEdit(offset: 8, length: 0, replacementLength: 1))
61+
}
62+
63+
public func testDiffOfTwoSameStrings() {
64+
let s1 = "0123456"
65+
let s2 = "0123456"
66+
67+
let diffs = getConcurrentEdits(from: s1, to: s2)
68+
XCTAssert(diffs.edits.isEmpty)
69+
}
70+
71+
public func testDiffOfTwoStrings() {
72+
let s1 = "0123456"
73+
let s2 = "x12456yz"
74+
75+
let diffs = getConcurrentEdits(from: s1, to: s2)
76+
77+
let expectedDiffs: [SourceEdit] = [
78+
SourceEdit(offset: 0, length: 1, replacementLength: 1),
79+
SourceEdit(offset: 3, length: 1, replacementLength: 0),
80+
SourceEdit(offset: 7, length: 0, replacementLength: 2),
81+
]
82+
83+
XCTAssertEqual(diffs.edits, expectedDiffs)
84+
}
85+
1986
public func testIncrementalInvalid() {
2087
let original = "struct A { func f() {"
21-
let step: (String, (Int, Int, String)) =
22-
("struct AA { func f() {", (8, 0, "A"))
23-
24-
var tree = Parser.parse(source: original)
25-
let sourceEdit = SourceEdit(range: ByteSourceRange(offset: step.1.0, length: step.1.1), replacementLength: step.1.2.utf8.count)
26-
let lookup = IncrementalParseTransition(previousTree: tree, edits: ConcurrentEdits(sourceEdit))
27-
tree = Parser.parse(source: step.0, parseTransition: lookup)
28-
XCTAssertEqual("\(tree)", step.0)
88+
let newSource = "struct AA { func f() {"
89+
90+
let concurrentEdits = getConcurrentEdits(from: original, to: newSource)
91+
92+
let oldTree = Parser.parse(source: original)
93+
let lookup = IncrementalParseTransition(previousTree: oldTree, edits: concurrentEdits)
94+
let newTree = Parser.parse(source: newSource, parseTransition: lookup)
95+
96+
XCTAssertEqual("\(newTree)", "\(newSource)")
2997
}
3098

3199
public func testReusedNode() throws {
32100
try XCTSkipIf(true, "Swift parser does not handle node reuse yet")
33101

34-
let original = "struct A {}\nstruct B {}\n"
35-
let step: (String, (Int, Int, String)) =
36-
("struct AA {}\nstruct B {}\n", (8, 0, "A"))
102+
let original =
103+
"""
104+
struct A {}
105+
struct B {}
106+
"""
107+
108+
let newSource =
109+
"""
110+
struct A {}
111+
struct B {}
112+
"""
37113

38114
let origTree = Parser.parse(source: original)
39-
let sourceEdit = SourceEdit(range: ByteSourceRange(offset: step.1.0, length: step.1.1), replacementLength: step.1.2.utf8.count)
115+
let concurrentEdits = getConcurrentEdits(from: original, to: newSource)
40116
let reusedNodeCollector = IncrementalParseReusedNodeCollector()
41-
let transition = IncrementalParseTransition(previousTree: origTree, edits: ConcurrentEdits(sourceEdit), reusedNodeDelegate: reusedNodeCollector)
42-
let newTree = Parser.parse(source: step.0, parseTransition: transition)
43-
XCTAssertEqual("\(newTree)", step.0)
117+
let transition = IncrementalParseTransition(previousTree: origTree, edits: concurrentEdits, reusedNodeDelegate: reusedNodeCollector)
118+
let newTree = Parser.parse(source: newSource, parseTransition: transition)
119+
XCTAssertEqual("\(newTree)", "\(newSource)")
44120

45121
let origStructB = origTree.statements[1]
46122
let newStructB = newTree.statements[1]

0 commit comments

Comments
 (0)