@@ -14,33 +14,108 @@ import XCTest
1414import SwiftSyntax
1515import 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+
1749public 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+ XCTAssertEqual ( firstDiff, SourceEdit ( offset: 8 , length: 0 , replacementLength: 1 ) )
60+ }
61+
62+ public func testDiffOfTwoSameStrings( ) {
63+ let s1 = " 0123456 "
64+ let s2 = " 0123456 "
65+
66+ let diffs = getConcurrentEdits ( from: s1, to: s2)
67+ XCTAssert ( diffs. edits. isEmpty)
68+ }
69+
70+ public func testDiffOfTwoStrings( ) {
71+ let s1 = " 0123456 "
72+ let s2 = " x12456yz "
73+
74+ let diffs = getConcurrentEdits ( from: s1, to: s2)
75+
76+ let expectedDiffs : [ SourceEdit ] = [
77+ SourceEdit ( offset: 0 , length: 1 , replacementLength: 1 ) ,
78+ SourceEdit ( offset: 3 , length: 1 , replacementLength: 0 ) ,
79+ SourceEdit ( offset: 7 , length: 0 , replacementLength: 2 ) ,
80+ ]
81+
82+ XCTAssertEqual ( diffs. edits, expectedDiffs)
83+ }
84+
1985 public func testIncrementalInvalid( ) {
2086 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 )
87+ let newSource = " struct AA { func f() { "
88+
89+ let concurrentEdits = getConcurrentEdits ( from: original, to: newSource)
90+
91+ let oldTree = Parser . parse ( source: original)
92+ let lookup = IncrementalParseTransition ( previousTree: oldTree, edits: concurrentEdits)
93+ let newTree = Parser . parse ( source: newSource, parseTransition: lookup)
94+
95+ XCTAssertEqual ( " \( newTree) " , " \( newSource) " )
2996 }
3097
3198 public func testReusedNode( ) throws {
3299 try XCTSkipIf ( true , " Swift parser does not handle node reuse yet " )
33100
34- let original = " struct A {} \n struct B {} \n "
35- let step : ( String , ( Int , Int , String ) ) =
36- ( " struct AA {} \n struct B {} \n " , ( 8 , 0 , " A " ) )
101+ let original =
102+ """
103+ struct A {}
104+ struct B {}
105+ """
106+
107+ let newSource =
108+ """
109+ struct A {}
110+ struct B {}
111+ """
37112
38113 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 )
114+ let concurrentEdits = getConcurrentEdits ( from : original , to : newSource )
40115 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 )
116+ let transition = IncrementalParseTransition ( previousTree: origTree, edits: concurrentEdits , reusedNodeDelegate: reusedNodeCollector)
117+ let newTree = Parser . parse ( source: newSource , parseTransition: transition)
118+ XCTAssertEqual ( " \( newTree) " , " \( newSource ) " )
44119
45120 let origStructB = origTree. statements [ 1 ]
46121 let newStructB = newTree. statements [ 1 ]
0 commit comments