@@ -3,52 +3,49 @@ import * as vscode from 'vscode-languageserver';
3
3
import * as shared from '@volar/shared' ;
4
4
import type * as ts from 'typescript/lib/tsserverlibrary' ;
5
5
6
- interface IncrementalScriptSnapshotVersion {
6
+ interface IncrementalScriptSnapshotChange {
7
7
applyed : boolean ,
8
8
changeRange : ts . TextChangeRange | undefined ,
9
9
version : number ,
10
- contentChanges : {
10
+ contentChange : {
11
11
range : vscode . Range ;
12
12
text : string ;
13
- } [ ] | undefined ,
13
+ } | undefined ,
14
14
snapshot : WeakRef < ts . IScriptSnapshot > | undefined ,
15
15
}
16
16
17
17
class IncrementalScriptSnapshot {
18
18
19
19
private document : TextDocument ;
20
20
uri : string ;
21
- versions : IncrementalScriptSnapshotVersion [ ] ;
21
+ changes : IncrementalScriptSnapshotChange [ ] ;
22
22
23
23
constructor ( uri : string , languageId : string , version : number , text : string ) {
24
24
this . uri = uri ;
25
25
this . document = TextDocument . create ( uri , languageId , version , text ) ;
26
- this . versions = [
26
+ this . changes = [
27
27
{
28
28
applyed : true ,
29
29
changeRange : undefined ,
30
30
version,
31
- contentChanges : undefined ,
31
+ contentChange : undefined ,
32
32
snapshot : undefined ,
33
33
}
34
34
] ;
35
35
}
36
36
37
37
get version ( ) {
38
- if ( this . versions . length ) {
39
- return this . versions [ this . versions . length - 1 ] . version ;
40
- }
41
- return this . document . version ;
38
+ return this . changes [ this . changes . length - 1 ] . version ;
42
39
}
43
40
44
41
update ( params : vscode . DidChangeTextDocumentParams ) {
45
42
TextDocument . update ( this . document , params . contentChanges , params . textDocument . version ) ;
46
- this . versions = [
43
+ this . changes = [
47
44
{
48
45
applyed : true ,
49
46
changeRange : undefined ,
50
47
version : params . textDocument . version ,
51
- contentChanges : undefined ,
48
+ contentChange : undefined ,
52
49
snapshot : undefined ,
53
50
}
54
51
] ;
@@ -58,7 +55,7 @@ class IncrementalScriptSnapshot {
58
55
59
56
this . clearUnReferenceVersions ( ) ;
60
57
61
- const lastChange = this . versions [ this . versions . length - 1 ] ;
58
+ const lastChange = this . changes [ this . changes . length - 1 ] ;
62
59
if ( ! lastChange . snapshot ) {
63
60
this . applyVersionToRootDocument ( lastChange . version , false ) ;
64
61
const text = this . document . getText ( ) ;
@@ -68,10 +65,10 @@ class IncrementalScriptSnapshot {
68
65
getLength : ( ) => text . length ,
69
66
getChangeRange : ( oldSnapshot ) => {
70
67
if ( ! cache . has ( oldSnapshot ) ) {
71
- const start = this . versions . findIndex ( change => change . snapshot ?. deref ( ) === oldSnapshot ) + 1 ;
72
- const end = this . versions . indexOf ( lastChange ) + 1 ;
68
+ const start = this . changes . findIndex ( change => change . snapshot ?. deref ( ) === oldSnapshot ) + 1 ;
69
+ const end = this . changes . indexOf ( lastChange ) + 1 ;
73
70
if ( start >= 0 && end >= 0 ) {
74
- const changeRanges = this . versions . slice ( start , end ) . map ( change => change . changeRange ) . filter ( shared . notEmpty ) ;
71
+ const changeRanges = this . changes . slice ( start , end ) . map ( change => change . changeRange ) . filter ( shared . notEmpty ) ;
75
72
const result = combineContinuousChangeRanges . apply ( null , changeRanges ) ;
76
73
cache . set ( oldSnapshot , result ) ;
77
74
}
@@ -92,7 +89,7 @@ class IncrementalScriptSnapshot {
92
89
93
90
this . clearUnReferenceVersions ( ) ;
94
91
95
- const lastChange = this . versions [ this . versions . length - 1 ] ;
92
+ const lastChange = this . changes [ this . changes . length - 1 ] ;
96
93
if ( ! lastChange . applyed ) {
97
94
this . applyVersionToRootDocument ( lastChange . version , false ) ;
98
95
}
@@ -102,9 +99,10 @@ class IncrementalScriptSnapshot {
102
99
103
100
clearUnReferenceVersions ( ) {
104
101
let versionToApply : number | undefined ;
105
- for ( let i = 0 ; i < this . versions . length - 1 ; i ++ ) {
106
- const change = this . versions [ i ] ;
107
- if ( ! change . snapshot ?. deref ( ) ) {
102
+ const lastVersion = this . changes [ this . changes . length - 1 ] . version ;
103
+ for ( let i = 0 ; i <= this . changes . length - 2 ; i ++ ) {
104
+ const change = this . changes [ i ] ;
105
+ if ( change . version !== lastVersion && ! change . snapshot ?. deref ( ) ) {
108
106
versionToApply = change . version ;
109
107
}
110
108
else {
@@ -118,29 +116,28 @@ class IncrementalScriptSnapshot {
118
116
119
117
applyVersionToRootDocument ( version : number , removeBeforeVersions : boolean ) {
120
118
let removeEnd = - 1 ;
121
- for ( let i = 0 ; i < this . versions . length ; i ++ ) {
122
- const change = this . versions [ i ] ;
119
+ for ( let i = 0 ; i < this . changes . length ; i ++ ) {
120
+ const change = this . changes [ i ] ;
123
121
if ( change . version > version ) {
124
122
break ;
125
123
}
126
124
if ( ! change . applyed ) {
127
- if ( change . contentChanges ) {
128
- const changeRanges : ts . TextChangeRange [ ] = change . contentChanges . map ( edit => ( {
125
+ if ( change . contentChange ) {
126
+ change . changeRange = {
129
127
span : {
130
- start : this . document . offsetAt ( edit . range . start ) ,
131
- length : this . document . offsetAt ( edit . range . end ) - this . document . offsetAt ( edit . range . start ) ,
128
+ start : this . document . offsetAt ( change . contentChange . range . start ) ,
129
+ length : this . document . offsetAt ( change . contentChange . range . end ) - this . document . offsetAt ( change . contentChange . range . start ) ,
132
130
} ,
133
- newLength : edit . text . length ,
134
- } ) ) ;
135
- change . changeRange = combineMultiLineChangeRanges . apply ( null , changeRanges ) ;
136
- TextDocument . update ( this . document , change . contentChanges , change . version ) ;
131
+ newLength : change . contentChange . text . length ,
132
+ } ;
133
+ TextDocument . update ( this . document , [ change . contentChange ] , change . version ) ;
137
134
}
138
135
change . applyed = true ;
139
136
}
140
137
removeEnd = i + 1 ;
141
138
}
142
139
if ( removeBeforeVersions && removeEnd >= 1 ) {
143
- this . versions . splice ( 0 , removeEnd ) ;
140
+ this . changes . splice ( 0 , removeEnd ) ;
144
141
}
145
142
}
146
143
}
@@ -174,27 +171,6 @@ function _combineContinuousChangeRanges(a: ts.TextChangeRange, b: ts.TextChangeR
174
171
return { span : { start, length } , newLength } ;
175
172
}
176
173
177
- export function combineMultiLineChangeRanges ( ...changeRanges : ts . TextChangeRange [ ] ) {
178
- if ( changeRanges . length === 1 ) {
179
- return changeRanges [ 0 ] ;
180
- }
181
- const starts = changeRanges . map ( change => change . span . start ) ;
182
- const ends = changeRanges . map ( change => change . span . start + change . span . length ) ;
183
- const start = Math . min ( ...starts ) ;
184
- const end = Math . max ( ...ends ) ;
185
- const lengthDiff = changeRanges . map ( change => change . newLength - change . span . length ) . reduce ( ( a , b ) => a + b , 0 ) ;
186
- const lastChangeRange = changeRanges . sort ( ( a , b ) => b . span . start - a . span . start ) [ 0 ] ;
187
- const newEnd = lastChangeRange . span . start + lastChangeRange . span . length + lengthDiff ;
188
- const lastChange : ts . TextChangeRange = {
189
- span : {
190
- start,
191
- length : end - start ,
192
- } ,
193
- newLength : newEnd - start ,
194
- } ;
195
- return lastChange ;
196
- }
197
-
198
174
export function createSnapshots ( connection : vscode . Connection ) {
199
175
200
176
const snapshots = shared . createPathMap < IncrementalScriptSnapshot > ( ) ;
@@ -217,13 +193,15 @@ export function createSnapshots(connection: vscode.Connection) {
217
193
const incrementalSnapshot = snapshots . uriGet ( params . textDocument . uri ) ;
218
194
if ( incrementalSnapshot ) {
219
195
if ( params . contentChanges . every ( vscode . TextDocumentContentChangeEvent . isIncremental ) ) {
220
- incrementalSnapshot . versions . push ( {
221
- applyed : false ,
222
- changeRange : undefined ,
223
- contentChanges : params . contentChanges ,
224
- version : params . textDocument . version ,
225
- snapshot : undefined ,
226
- } ) ;
196
+ for ( const contentChange of params . contentChanges ) {
197
+ incrementalSnapshot . changes . push ( {
198
+ applyed : false ,
199
+ changeRange : undefined ,
200
+ contentChange,
201
+ version : params . textDocument . version ,
202
+ snapshot : undefined ,
203
+ } ) ;
204
+ }
227
205
}
228
206
else {
229
207
incrementalSnapshot . update ( params ) ;
0 commit comments