@@ -123,11 +123,11 @@ export interface BufferCursor {
123123}
124124
125125export class Piece {
126- bufferIndex : number ;
127- start : BufferCursor ;
128- end : BufferCursor ;
129- length : number ;
130- lineFeedCnt : number ;
126+ readonly bufferIndex : number ;
127+ readonly start : BufferCursor ;
128+ readonly end : BufferCursor ;
129+ readonly length : number ;
130+ readonly lineFeedCnt : number ;
131131
132132 constructor ( bufferIndex : number , start : BufferCursor , end : BufferCursor , lineFeedCnt : number , length : number ) {
133133 this . bufferIndex = bufferIndex ;
@@ -155,28 +155,28 @@ export class StringBuffer {
155155 * 2. TreeNode/Buffers normalization should not happen during snapshot reading.
156156 */
157157class PieceTreeSnapshot implements ITextSnapshot {
158- private _nodes : TreeNode [ ] ; // pieces/tree nodes in order
158+ private _pieces : Piece [ ] ;
159159 private _index : number ;
160160 private _tree : PieceTreeBase ;
161161 private _BOM : string ;
162162
163163 constructor ( tree : PieceTreeBase , BOM : string ) {
164- this . _nodes = [ ] ;
164+ this . _pieces = [ ] ;
165165 this . _tree = tree ;
166166 this . _BOM = BOM ;
167167 this . _index = 0 ;
168168 if ( tree . root !== SENTINEL ) {
169169 tree . iterate ( tree . root , node => {
170170 if ( node !== SENTINEL ) {
171- this . _nodes . push ( node ) ;
171+ this . _pieces . push ( node . piece ) ;
172172 }
173173 return true ;
174174 } ) ;
175175 }
176176 }
177177
178178 read ( ) : string {
179- if ( this . _nodes . length === 0 ) {
179+ if ( this . _pieces . length === 0 ) {
180180 if ( this . _index === 0 ) {
181181 this . _index ++ ;
182182 return this . _BOM ;
@@ -185,14 +185,14 @@ class PieceTreeSnapshot implements ITextSnapshot {
185185 }
186186 }
187187
188- if ( this . _index > this . _nodes . length - 1 ) {
188+ if ( this . _index > this . _pieces . length - 1 ) {
189189 return null ;
190190 }
191191
192192 if ( this . _index === 0 ) {
193- return this . _BOM + this . _tree . getNodeContent ( this . _nodes [ this . _index ++ ] ) ;
193+ return this . _BOM + this . _tree . getPieceContent ( this . _pieces [ this . _index ++ ] ) ;
194194 }
195- return this . _tree . getNodeContent ( this . _nodes [ this . _index ++ ] ) ;
195+ return this . _tree . getPieceContent ( this . _pieces [ this . _index ++ ] ) ;
196196 }
197197}
198198
@@ -578,9 +578,14 @@ export class PieceTreeBase {
578578
579579 if ( headOfRight === 10 /** \n */ ) {
580580 let newStart : BufferCursor = { line : newRightPiece . start . line + 1 , column : 0 } ;
581- newRightPiece . start = newStart ;
582- newRightPiece . length -= 1 ;
583- newRightPiece . lineFeedCnt = this . getLineFeedCnt ( newRightPiece . bufferIndex , newRightPiece . start , newRightPiece . end ) ;
581+ newRightPiece = new Piece (
582+ newRightPiece . bufferIndex ,
583+ newStart ,
584+ newRightPiece . end ,
585+ this . getLineFeedCnt ( newRightPiece . bufferIndex , newStart , newRightPiece . end ) ,
586+ newRightPiece . length - 1
587+ ) ;
588+
584589 value += '\n' ;
585590 }
586591 }
@@ -703,9 +708,15 @@ export class PieceTreeBase {
703708
704709 let piece = node . piece ;
705710 let newStart : BufferCursor = { line : piece . start . line + 1 , column : 0 } ;
706- piece . start = newStart ;
707- piece . lineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , piece . end ) ;
708- piece . length -= 1 ;
711+ let nPiece = new Piece (
712+ piece . bufferIndex ,
713+ newStart ,
714+ piece . end ,
715+ this . getLineFeedCnt ( piece . bufferIndex , newStart , piece . end ) ,
716+ piece . length - 1
717+ ) ;
718+
719+ node . piece = nPiece ;
709720
710721 value += '\n' ;
711722 updateTreeMetadata ( this , node , - 1 , - 1 ) ;
@@ -987,46 +998,72 @@ export class PieceTreeBase {
987998 }
988999
9891000 deleteNodeTail ( node : TreeNode , pos : BufferCursor ) {
990- let piece = node . piece ;
991- let originalLFCnt = piece . lineFeedCnt ;
992- let originalEndOffset = this . offsetInBuffer ( piece . bufferIndex , piece . end ) ;
993- piece . end = pos ;
994- let newEndOffset = this . offsetInBuffer ( piece . bufferIndex , piece . end ) ;
995- piece . lineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , piece . end ) ;
996- let lf_delta = piece . lineFeedCnt - originalLFCnt ;
997- let size_delta = newEndOffset - originalEndOffset ;
998- piece . length += size_delta ;
1001+ const piece = node . piece ;
1002+ const originalLFCnt = piece . lineFeedCnt ;
1003+ const originalEndOffset = this . offsetInBuffer ( piece . bufferIndex , piece . end ) ;
1004+
1005+ const newEnd = pos ;
1006+ const newEndOffset = this . offsetInBuffer ( piece . bufferIndex , newEnd ) ;
1007+ const newLineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , newEnd ) ;
1008+
1009+ const lf_delta = newLineFeedCnt - originalLFCnt ;
1010+ const size_delta = newEndOffset - originalEndOffset ;
1011+ const newLength = piece . length + size_delta ;
1012+
1013+ node . piece = new Piece (
1014+ piece . bufferIndex ,
1015+ piece . start ,
1016+ newEnd ,
1017+ newLineFeedCnt ,
1018+ newLength
1019+ ) ;
1020+
9991021 updateTreeMetadata ( this , node , size_delta , lf_delta ) ;
10001022 }
10011023
10021024 deleteNodeHead ( node : TreeNode , pos : BufferCursor ) {
1003- let piece = node . piece ;
1004- let originalLFCnt = piece . lineFeedCnt ;
1005- let originalStartOffset = this . offsetInBuffer ( piece . bufferIndex , piece . start ) ;
1006-
1007- piece . start = pos ;
1008- piece . lineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , piece . end ) ;
1009- let newStartOffset = this . offsetInBuffer ( piece . bufferIndex , piece . start ) ;
1010- let lf_delta = piece . lineFeedCnt - originalLFCnt ;
1011- let size_delta = originalStartOffset - newStartOffset ;
1012- piece . length += size_delta ;
1025+ const piece = node . piece ;
1026+ const originalLFCnt = piece . lineFeedCnt ;
1027+ const originalStartOffset = this . offsetInBuffer ( piece . bufferIndex , piece . start ) ;
1028+
1029+ const newStart = pos ;
1030+ const newLineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , newStart , piece . end ) ;
1031+ const newStartOffset = this . offsetInBuffer ( piece . bufferIndex , newStart ) ;
1032+ const lf_delta = newLineFeedCnt - originalLFCnt ;
1033+ const size_delta = originalStartOffset - newStartOffset ;
1034+ const newLength = piece . length + size_delta ;
1035+ node . piece = new Piece (
1036+ piece . bufferIndex ,
1037+ newStart ,
1038+ piece . end ,
1039+ newLineFeedCnt ,
1040+ newLength
1041+ ) ;
1042+
10131043 updateTreeMetadata ( this , node , size_delta , lf_delta ) ;
10141044 }
10151045
10161046 shrinkNode ( node : TreeNode , start : BufferCursor , end : BufferCursor ) {
1017- let piece = node . piece ;
1018- let originalStartPos = piece . start ;
1019- let originalEndPos = piece . end ;
1047+ const piece = node . piece ;
1048+ const originalStartPos = piece . start ;
1049+ const originalEndPos = piece . end ;
10201050
10211051 // old piece, originalStartPos, start
1022- let oldLength = piece . length ;
1023- let oldLFCnt = piece . lineFeedCnt ;
1024- piece . end = start ;
1025- piece . lineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , piece . end ) ;
1026- let newLength = this . offsetInBuffer ( piece . bufferIndex , start ) - this . offsetInBuffer ( piece . bufferIndex , originalStartPos ) ;
1027- let newLFCnt = piece . lineFeedCnt ;
1028- piece . length = newLength ;
1029- updateTreeMetadata ( this , node , newLength - oldLength , newLFCnt - oldLFCnt ) ;
1052+ const oldLength = piece . length ;
1053+ const oldLFCnt = piece . lineFeedCnt ;
1054+ const newEnd = start ;
1055+ const newLineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , newEnd ) ;
1056+ const newLength = this . offsetInBuffer ( piece . bufferIndex , start ) - this . offsetInBuffer ( piece . bufferIndex , originalStartPos ) ;
1057+
1058+ node . piece = new Piece (
1059+ piece . bufferIndex ,
1060+ piece . start ,
1061+ newEnd ,
1062+ newLineFeedCnt ,
1063+ newLength
1064+ ) ;
1065+
1066+ updateTreeMetadata ( this , node , newLength - oldLength , newLineFeedCnt - oldLFCnt ) ;
10301067
10311068 // new right piece, end, originalEndPos
10321069 let newPiece = new Piece (
@@ -1046,7 +1083,7 @@ export class PieceTreeBase {
10461083 value += '\n' ;
10471084 }
10481085
1049- let hitCRLF = this . shouldCheckCRLF ( ) && this . startWithLF ( value ) && this . endWithCR ( node ) ;
1086+ const hitCRLF = this . shouldCheckCRLF ( ) && this . startWithLF ( value ) && this . endWithCR ( node ) ;
10501087 const startOffset = this . _buffers [ 0 ] . buffer . length ;
10511088 this . _buffers [ 0 ] . buffer += value ;
10521089 const lineStarts = createLineStartsFast ( value , false ) ;
@@ -1061,16 +1098,23 @@ export class PieceTreeBase {
10611098 }
10621099
10631100 this . _buffers [ 0 ] . lineStarts = ( < number [ ] > this . _buffers [ 0 ] . lineStarts ) . concat ( < number [ ] > lineStarts . slice ( 1 ) ) ;
1064- let endIndex = this . _buffers [ 0 ] . lineStarts . length - 1 ;
1065- let endColumn = this . _buffers [ 0 ] . buffer . length - this . _buffers [ 0 ] . lineStarts [ endIndex ] ;
1066- let endPos = { line : endIndex , column : endColumn } ;
1067- node . piece . end = endPos ;
1068- node . piece . length += value . length ;
1069- let oldLineFeedCnt = node . piece . lineFeedCnt ;
1070- let newLineFeedCnt = this . getLineFeedCnt ( 0 , node . piece . start , endPos ) ;
1071- node . piece . lineFeedCnt = newLineFeedCnt ;
1072- let lf_delta = newLineFeedCnt - oldLineFeedCnt ;
1073- this . _lastChangeBufferPos = endPos ;
1101+ const endIndex = this . _buffers [ 0 ] . lineStarts . length - 1 ;
1102+ const endColumn = this . _buffers [ 0 ] . buffer . length - this . _buffers [ 0 ] . lineStarts [ endIndex ] ;
1103+ const newEnd = { line : endIndex , column : endColumn } ;
1104+ const newLength = node . piece . length + value . length ;
1105+ const oldLineFeedCnt = node . piece . lineFeedCnt ;
1106+ const newLineFeedCnt = this . getLineFeedCnt ( 0 , node . piece . start , newEnd ) ;
1107+ const lf_delta = newLineFeedCnt - oldLineFeedCnt ;
1108+
1109+ node . piece = new Piece (
1110+ node . piece . bufferIndex ,
1111+ node . piece . start ,
1112+ newEnd ,
1113+ newLineFeedCnt ,
1114+ newLength
1115+ ) ;
1116+
1117+ this . _lastChangeBufferPos = newEnd ;
10741118 updateTreeMetadata ( this , node , value . length , lf_delta ) ;
10751119 }
10761120
@@ -1266,18 +1310,24 @@ export class PieceTreeBase {
12661310 let nodesToDel = [ ] ;
12671311 // update node
12681312 let lineStarts = this . _buffers [ prev . piece . bufferIndex ] . lineStarts ;
1313+ let newEnd : BufferCursor ;
12691314 if ( prev . piece . end . column === 0 ) {
12701315 // it means, last line ends with \r, not \r\n
1271- let newEnd : BufferCursor = { line : prev . piece . end . line - 1 , column : lineStarts [ prev . piece . end . line ] - lineStarts [ prev . piece . end . line - 1 ] - 1 } ;
1272- prev . piece . end = newEnd ;
1316+ newEnd = { line : prev . piece . end . line - 1 , column : lineStarts [ prev . piece . end . line ] - lineStarts [ prev . piece . end . line - 1 ] - 1 } ;
12731317 } else {
12741318 // \r\n
1275- let newEnd : BufferCursor = { line : prev . piece . end . line , column : prev . piece . end . column - 1 } ;
1276- prev . piece . end = newEnd ;
1319+ newEnd = { line : prev . piece . end . line , column : prev . piece . end . column - 1 } ;
12771320 }
12781321
1279- prev . piece . length -= 1 ;
1280- prev . piece . lineFeedCnt -= 1 ;
1322+ const prevNewLength = prev . piece . length - 1 ;
1323+ const prevNewLFCnt = prev . piece . lineFeedCnt - 1 ;
1324+ prev . piece = new Piece (
1325+ prev . piece . bufferIndex ,
1326+ prev . piece . start ,
1327+ newEnd ,
1328+ prevNewLFCnt ,
1329+ prevNewLength
1330+ ) ;
12811331
12821332 updateTreeMetadata ( this , prev , - 1 , - 1 ) ;
12831333 if ( prev . piece . length === 0 ) {
@@ -1286,10 +1336,15 @@ export class PieceTreeBase {
12861336
12871337 // update nextNode
12881338 let newStart : BufferCursor = { line : next . piece . start . line + 1 , column : 0 } ;
1289- next . piece . start = newStart ;
1290- next . piece . length -= 1 ;
1291- next . piece . lineFeedCnt = this . getLineFeedCnt ( next . piece . bufferIndex , next . piece . start , next . piece . end ) ;
1292- // }
1339+ const newLength = next . piece . length - 1 ;
1340+ const newLineFeedCnt = this . getLineFeedCnt ( next . piece . bufferIndex , newStart , next . piece . end ) ;
1341+ next . piece = new Piece (
1342+ next . piece . bufferIndex ,
1343+ newStart ,
1344+ next . piece . end ,
1345+ newLineFeedCnt ,
1346+ newLength
1347+ ) ;
12931348
12941349 updateTreeMetadata ( this , next , - 1 , - 1 ) ;
12951350 if ( next . piece . length === 0 ) {
@@ -1317,11 +1372,18 @@ export class PieceTreeBase {
13171372 rbDelete ( this , nextNode ) ;
13181373 } else {
13191374
1320- let piece = nextNode . piece ;
1321- let newStart : BufferCursor = { line : piece . start . line + 1 , column : 0 } ;
1322- piece . start = newStart ;
1323- piece . length -= 1 ;
1324- piece . lineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , piece . start , piece . end ) ;
1375+ const piece = nextNode . piece ;
1376+ const newStart : BufferCursor = { line : piece . start . line + 1 , column : 0 } ;
1377+ const newLength = piece . length - 1 ;
1378+ const newLineFeedCnt = this . getLineFeedCnt ( piece . bufferIndex , newStart , piece . end ) ;
1379+ nextNode . piece = new Piece (
1380+ piece . bufferIndex ,
1381+ newStart ,
1382+ piece . end ,
1383+ newLineFeedCnt ,
1384+ newLength
1385+ ) ;
1386+
13251387 updateTreeMetadata ( this , nextNode , - 1 , - 1 ) ;
13261388 }
13271389 return true ;
@@ -1362,6 +1424,14 @@ export class PieceTreeBase {
13621424 return currentContent ;
13631425 }
13641426
1427+ getPieceContent ( piece : Piece ) {
1428+ let buffer = this . _buffers [ piece . bufferIndex ] ;
1429+ let startOffset = this . offsetInBuffer ( piece . bufferIndex , piece . start ) ;
1430+ let endOffset = this . offsetInBuffer ( piece . bufferIndex , piece . end ) ;
1431+ let currentContent = buffer . buffer . substring ( startOffset , endOffset ) ;
1432+ return currentContent ;
1433+ }
1434+
13651435 /**
13661436 * node node
13671437 * / \ / \
0 commit comments