66import * as arrays from 'vs/base/common/arrays' ;
77import { LineTokens } from 'vs/editor/common/core/lineTokens' ;
88import { Position } from 'vs/editor/common/core/position' ;
9- import { IRange } from 'vs/editor/common/core/range' ;
9+ import { IRange , Range } from 'vs/editor/common/core/range' ;
1010import { ColorId , FontStyle , LanguageId , MetadataConsts , StandardTokenType , TokenMetadata } from 'vs/editor/common/modes' ;
1111import { writeUInt32BE , readUInt32BE } from 'vs/base/common/buffer' ;
1212import { CharCode } from 'vs/base/common/charCode' ;
@@ -124,16 +124,7 @@ export class MultilineTokensBuilder {
124124 }
125125}
126126
127- export interface IEncodedTokens {
128- getMaxDeltaLine ( ) : number ;
129- getLineTokens ( deltaLine : number ) : LineTokens2 | null ;
130-
131- clear ( ) : void ;
132- acceptDeleteRange ( horizontalShiftForFirstLineTokens : number , startDeltaLine : number , startCharacter : number , endDeltaLine : number , endCharacter : number ) : void ;
133- acceptInsertText ( deltaLine : number , character : number , eolCount : number , firstLineLength : number , lastLineLength : number , firstCharCode : number ) : void ;
134- }
135-
136- export class SparseEncodedTokens implements IEncodedTokens {
127+ export class SparseEncodedTokens {
137128 /**
138129 * The encoding of tokens is:
139130 * 4*i deltaLine (from `startLineNumber`)
@@ -157,6 +148,17 @@ export class SparseEncodedTokens implements IEncodedTokens {
157148 return this . _getDeltaLine ( tokenCount - 1 ) ;
158149 }
159150
151+ public getRange ( ) : Range | null {
152+ const tokenCount = this . _getTokenCount ( ) ;
153+ if ( tokenCount === 0 ) {
154+ return null ;
155+ }
156+ const startChar = this . _getStartCharacter ( 0 ) ;
157+ const maxDeltaLine = this . _getDeltaLine ( tokenCount - 1 ) ;
158+ const endChar = this . _getEndCharacter ( tokenCount - 1 ) ;
159+ return new Range ( 0 , startChar + 1 , maxDeltaLine , endChar + 1 ) ;
160+ }
161+
160162 private _getTokenCount ( ) : number {
161163 return this . _tokenCount ;
162164 }
@@ -165,6 +167,18 @@ export class SparseEncodedTokens implements IEncodedTokens {
165167 return this . _tokens [ 4 * tokenIndex ] ;
166168 }
167169
170+ private _getStartCharacter ( tokenIndex : number ) : number {
171+ return this . _tokens [ 4 * tokenIndex + 1 ] ;
172+ }
173+
174+ private _getEndCharacter ( tokenIndex : number ) : number {
175+ return this . _tokens [ 4 * tokenIndex + 2 ] ;
176+ }
177+
178+ public isEmpty ( ) : boolean {
179+ return ( this . _getTokenCount ( ) === 0 ) ;
180+ }
181+
168182 public getLineTokens ( deltaLine : number ) : LineTokens2 | null {
169183 let low = 0 ;
170184 let high = this . _getTokenCount ( ) - 1 ;
@@ -201,6 +215,45 @@ export class SparseEncodedTokens implements IEncodedTokens {
201215 this . _tokenCount = 0 ;
202216 }
203217
218+ public removeTokens ( startDeltaLine : number , startChar : number , endDeltaLine : number , endChar : number ) : number {
219+ const tokens = this . _tokens ;
220+ const tokenCount = this . _tokenCount ;
221+ let newTokenCount = 0 ;
222+ let hasDeletedTokens = false ;
223+ let firstDeltaLine = 0 ;
224+ for ( let i = 0 ; i < tokenCount ; i ++ ) {
225+ const srcOffset = 4 * i ;
226+ const tokenDeltaLine = tokens [ srcOffset ] ;
227+ const tokenStartCharacter = tokens [ srcOffset + 1 ] ;
228+ const tokenEndCharacter = tokens [ srcOffset + 2 ] ;
229+ const tokenMetadata = tokens [ srcOffset + 3 ] ;
230+
231+ if (
232+ ( tokenDeltaLine > startDeltaLine || ( tokenDeltaLine === startDeltaLine && tokenStartCharacter >= startChar ) )
233+ && ( tokenDeltaLine < endDeltaLine || ( tokenDeltaLine === endDeltaLine && tokenEndCharacter <= endChar ) )
234+ ) {
235+ hasDeletedTokens = true ;
236+ } else {
237+ if ( newTokenCount === 0 ) {
238+ firstDeltaLine = tokenDeltaLine ;
239+ }
240+ if ( hasDeletedTokens ) {
241+ // must move the token to the left
242+ const destOffset = 4 * newTokenCount ;
243+ tokens [ destOffset ] = tokenDeltaLine - firstDeltaLine ;
244+ tokens [ destOffset + 1 ] = tokenStartCharacter ;
245+ tokens [ destOffset + 2 ] = tokenEndCharacter ;
246+ tokens [ destOffset + 3 ] = tokenMetadata ;
247+ }
248+ newTokenCount ++ ;
249+ }
250+ }
251+
252+ this . _tokenCount = newTokenCount ;
253+
254+ return firstDeltaLine ;
255+ }
256+
204257 public acceptDeleteRange ( horizontalShiftForFirstLineTokens : number , startDeltaLine : number , startCharacter : number , endDeltaLine : number , endCharacter : number ) : void {
205258 // This is a bit complex, here are the cases I used to think about this:
206259 //
@@ -457,9 +510,9 @@ export class MultilineTokens2 {
457510
458511 public startLineNumber : number ;
459512 public endLineNumber : number ;
460- public tokens : IEncodedTokens ;
513+ public tokens : SparseEncodedTokens ;
461514
462- constructor ( startLineNumber : number , tokens : IEncodedTokens ) {
515+ constructor ( startLineNumber : number , tokens : SparseEncodedTokens ) {
463516 this . startLineNumber = startLineNumber ;
464517 this . tokens = tokens ;
465518 this . endLineNumber = this . startLineNumber + this . tokens . getMaxDeltaLine ( ) ;
@@ -469,13 +522,33 @@ export class MultilineTokens2 {
469522 this . endLineNumber = this . startLineNumber + this . tokens . getMaxDeltaLine ( ) ;
470523 }
471524
525+ public isEmpty ( ) : boolean {
526+ return this . tokens . isEmpty ( ) ;
527+ }
528+
472529 public getLineTokens ( lineNumber : number ) : LineTokens2 | null {
473530 if ( this . startLineNumber <= lineNumber && lineNumber <= this . endLineNumber ) {
474531 return this . tokens . getLineTokens ( lineNumber - this . startLineNumber ) ;
475532 }
476533 return null ;
477534 }
478535
536+ public getRange ( ) : Range | null {
537+ const deltaRange = this . tokens . getRange ( ) ;
538+ if ( ! deltaRange ) {
539+ return deltaRange ;
540+ }
541+ return new Range ( this . startLineNumber + deltaRange . startLineNumber , deltaRange . startColumn , this . startLineNumber + deltaRange . endLineNumber , deltaRange . endColumn ) ;
542+ }
543+
544+ public removeTokens ( range : Range ) : void {
545+ const startLineIndex = range . startLineNumber - this . startLineNumber ;
546+ const endLineIndex = range . endLineNumber - this . startLineNumber ;
547+
548+ this . startLineNumber += this . tokens . removeTokens ( startLineIndex , range . startColumn - 1 , endLineIndex , range . endColumn - 1 ) ;
549+ this . _updateEndLineNumber ( ) ;
550+ }
551+
479552 public applyEdit ( range : IRange , text : string ) : void {
480553 const [ eolCount , firstLineLength , lastLineLength ] = countEOL ( text ) ;
481554 this . acceptEdit ( range , eolCount , firstLineLength , lastLineLength , text . length > 0 ? text . charCodeAt ( 0 ) : CharCode . Null ) ;
@@ -749,11 +822,50 @@ export class TokensStore2 {
749822 this . _isComplete = false ;
750823 }
751824
752- public set ( pieces : MultilineTokens2 [ ] | null , isComplete : boolean ) {
825+ public set ( pieces : MultilineTokens2 [ ] | null , isComplete : boolean ) : void {
753826 this . _pieces = pieces || [ ] ;
754827 this . _isComplete = isComplete ;
755828 }
756829
830+ public setPartial ( _range : Range , pieces : MultilineTokens2 [ ] ) : Range {
831+ if ( pieces . length === 0 ) {
832+ return _range ;
833+ }
834+ const _firstRange = pieces [ 0 ] . getRange ( ) ;
835+ const _lastRange = pieces [ pieces . length - 1 ] . getRange ( ) ;
836+ if ( ! _firstRange || ! _lastRange ) {
837+ return _range ;
838+ }
839+ const range = _range . plusRange ( _firstRange ) . plusRange ( _lastRange ) ;
840+ let insertIndex = this . _pieces . length ;
841+ for ( let i = 0 , len = this . _pieces . length ; i < len ; i ++ ) {
842+ const piece = this . _pieces [ i ] ;
843+ if ( piece . endLineNumber < range . startLineNumber ) {
844+ continue ;
845+ }
846+ if ( piece . startLineNumber > range . endLineNumber ) {
847+ insertIndex = Math . min ( i , insertIndex ) ;
848+ break ;
849+ }
850+ piece . removeTokens ( range ) ;
851+
852+ if ( piece . isEmpty ( ) ) {
853+ this . _pieces . splice ( i , 1 ) ;
854+ i -- ;
855+ len -- ;
856+ insertIndex -- ;
857+ continue ;
858+ }
859+
860+ if ( piece . startLineNumber >= range . endLineNumber ) {
861+ insertIndex = Math . min ( i , insertIndex ) ;
862+ }
863+ }
864+
865+ this . _pieces = arrays . arrayInsert ( this . _pieces , insertIndex , pieces ) ;
866+ return range ;
867+ }
868+
757869 public isComplete ( ) : boolean {
758870 return this . _isComplete ;
759871 }
@@ -766,7 +878,7 @@ export class TokensStore2 {
766878 }
767879
768880 const pieceIndex = TokensStore2 . _findFirstPieceWithLine ( pieces , lineNumber ) ;
769- const bTokens = this . _pieces [ pieceIndex ] . getLineTokens ( lineNumber ) ;
881+ const bTokens = pieces [ pieceIndex ] . getLineTokens ( lineNumber ) ;
770882
771883 if ( ! bTokens ) {
772884 return aTokens ;
0 commit comments