@@ -119,6 +119,11 @@ public final class SwiftLanguageServer: ToolchainLanguageServer {
119
119
120
120
var commandsByFile : [ DocumentURI : SwiftCompileCommand ] = [ : ]
121
121
122
+ var documentParseTransition : [ DocumentURI : LookaheadRanges ] = [ : ]
123
+
124
+ /// *For Testing*
125
+ public var documentReusedNodeCollector : [ DocumentURI : IncrementalParseReusedNodeCollector ] = [ : ]
126
+
122
127
var keys : sourcekitd_keys { return sourcekitd. keys }
123
128
var requests : sourcekitd_requests { return sourcekitd. requests }
124
129
var values : sourcekitd_values { return sourcekitd. values }
@@ -198,13 +203,32 @@ public final class SwiftLanguageServer: ToolchainLanguageServer {
198
203
199
204
/// Returns the updated lexical tokens for the given `snapshot`.
200
205
private func updateSyntaxTree(
201
- for snapshot: DocumentSnapshot
206
+ for snapshot: DocumentSnapshot ,
207
+ with edits: ConcurrentEdits ? = nil
202
208
) -> DocumentTokens {
203
209
logExecutionTime ( level: . debug) {
204
210
var docTokens = snapshot. tokens
211
+ let documentURI = snapshot. document. uri
212
+
213
+ var reusedNodeCollector = documentReusedNodeCollector [ documentURI]
214
+ if reusedNodeCollector == nil {
215
+ documentReusedNodeCollector [ documentURI] = IncrementalParseReusedNodeCollector ( )
216
+ reusedNodeCollector = documentReusedNodeCollector [ documentURI]
217
+ }
218
+
219
+ var parseTransition : IncrementalParseTransition ? = nil
220
+ if let previousTree = snapshot. tokens. syntaxTree,
221
+ let lookaheadRanges = documentParseTransition [ documentURI] ,
222
+ let edits {
223
+ parseTransition = IncrementalParseTransition ( previousTree: previousTree, edits: edits, lookaheadRanges: lookaheadRanges, reusedNodeDelegate: reusedNodeCollector)
224
+ }
225
+ let ( tree, nextLookaheadRanges) = Parser . parseIncrementally (
226
+ source: snapshot. text, parseTransition: parseTransition)
205
227
206
- docTokens. syntaxTree = Parser . parse ( source : snapshot . text )
228
+ docTokens. syntaxTree = tree
207
229
230
+ documentParseTransition [ documentURI] = nextLookaheadRanges
231
+
208
232
return docTokens
209
233
}
210
234
}
@@ -520,34 +544,45 @@ extension SwiftLanguageServer {
520
544
// Clear settings that should not be cached for closed documents.
521
545
self . commandsByFile [ uri] = nil
522
546
self . currentDiagnostics [ uri] = nil
547
+ self . documentParseTransition [ uri] = nil
548
+ self . documentReusedNodeCollector [ uri] = nil
523
549
524
550
_ = try ? self . sourcekitd. sendSync ( req)
525
551
}
526
552
}
527
553
528
554
public func changeDocument( _ note: DidChangeTextDocumentNotification ) {
529
555
let keys = self . keys
556
+ var edits : [ IncrementalEdit ] = [ ]
530
557
531
558
self . queue. async {
532
559
var lastResponse : SKDResponseDictionary ? = nil
533
560
534
- let snapshot = self . documentManager. edit ( note) { ( before: DocumentSnapshot , edit: TextDocumentContentChangeEvent ) in
561
+ let snapshot = self . documentManager. edit ( note) {
562
+ ( before: DocumentSnapshot , edit: TextDocumentContentChangeEvent ) in
535
563
let req = SKDRequestDictionary ( sourcekitd: self . sourcekitd)
536
564
req [ keys. request] = self . requests. editor_replacetext
537
565
req [ keys. name] = note. textDocument. uri. pseudoPath
538
566
539
567
if let range = edit. range {
540
- guard let offset = before. utf8Offset ( of: range. lowerBound) , let end = before. utf8Offset ( of: range. upperBound) else {
568
+ guard let offset = before. utf8Offset ( of: range. lowerBound) ,
569
+ let end = before. utf8Offset ( of: range. upperBound)
570
+ else {
541
571
fatalError ( " invalid edit \( range) " )
542
572
}
543
573
574
+ let length = end - offset
544
575
req [ keys. offset] = offset
545
- req [ keys. length] = end - offset
576
+ req [ keys. length] = length
546
577
578
+ edits. append ( IncrementalEdit ( offset: offset, length: length, replacementLength: edit. text. utf8. count) )
547
579
} else {
548
580
// Full text
581
+ let length = before. text. utf8. count
549
582
req [ keys. offset] = 0
550
- req [ keys. length] = before. text. utf8. count
583
+ req [ keys. length] = length
584
+
585
+ edits. append ( IncrementalEdit ( offset: 0 , length: length, replacementLength: edit. text. utf8. count) )
551
586
}
552
587
553
588
req [ keys. sourcetext] = edit. text
@@ -556,7 +591,7 @@ extension SwiftLanguageServer {
556
591
self . adjustDiagnosticRanges ( of: note. textDocument. uri, for: edit)
557
592
} updateDocumentTokens: { ( after: DocumentSnapshot ) in
558
593
if lastResponse != nil {
559
- return self . updateSyntaxTree ( for: after)
594
+ return self . updateSyntaxTree ( for: after, with : ConcurrentEdits ( fromSequential : edits ) )
560
595
} else {
561
596
return DocumentTokens ( )
562
597
}
0 commit comments