55'use strict' ;
66
77import * as editorCommon from 'vs/editor/common/editorCommon' ;
8- import { Token } from 'vs/editor/common/core/token' ;
9- import { LineTokens } from 'vs/editor/common/core/lineTokens' ;
10-
11- export class TokenIterator implements editorCommon . ITokenIterator {
8+ import { LineToken } from 'vs/editor/common/core/lineTokens' ;
9+ import { Position } from 'vs/editor/common/core/position' ;
10+
11+ class TokenInfo implements editorCommon . ITokenInfo {
12+ _tokenInfoBrand : void ;
13+
14+ _actual : LineToken ;
15+ public lineNumber : number ;
16+ public startColumn : number ;
17+ public endColumn : number ;
18+ public type : string ;
19+
20+ constructor ( actual :LineToken , lineNumber :number ) {
21+ this . _actual = actual ;
22+ this . lineNumber = lineNumber ;
23+ this . startColumn = this . _actual . startOffset + 1 ;
24+ this . endColumn = this . _actual . endOffset + 1 ;
25+ this . type = this . _actual . type ;
26+ }
27+ }
1228
13- private _model :editorCommon . ITokenizedModel ;
14- private _currentLineNumber :number ;
15- private _currentTokenIndex :number ;
16- private _currentLineTokens :LineTokens ;
17- private _next :editorCommon . ITokenInfo ;
18- private _prev :editorCommon . ITokenInfo ;
29+ function findClosestNonEmptyLine ( model :editorCommon . ITokenizedModel , position :Position ) : Position {
30+ const lineNumber = position . lineNumber ;
31+ if ( model . getLineMaxColumn ( lineNumber ) !== 1 ) {
32+ return position ;
33+ }
1934
20- constructor ( model :editorCommon . ITokenizedModel , position :editorCommon . IPosition ) {
21- this . _model = model ;
22- this . _currentLineNumber = position . lineNumber ;
23- this . _currentTokenIndex = 0 ;
24- this . _readLineTokens ( this . _currentLineNumber ) ;
25- this . _next = null ;
26- this . _prev = null ;
35+ const lineCount = model . getLineCount ( ) ;
2736
28- // start with a position to next/prev run
29- var columnIndex = position . column - 1 , tokenEndIndex = Number . MAX_VALUE ;
37+ // we need to go up or down
38+ let distance = 1 ;
39+ while ( true ) {
40+ let aboveLineNumber = lineNumber - distance ;
41+ let belowLineNumber = lineNumber + distance ;
3042
31- for ( var i = this . _currentLineTokens . getTokenCount ( ) - 1 ; i >= 0 ; i -- ) {
32- let tokenStartIndex = this . _currentLineTokens . getTokenStartOffset ( i ) ;
43+ if ( aboveLineNumber < 1 && belowLineNumber > lineCount ) {
44+ // No more lines above or below
45+ break ;
46+ }
3347
34- if ( tokenStartIndex <= columnIndex && columnIndex <= tokenEndIndex ) {
48+ if ( aboveLineNumber >= 1 ) {
49+ let aboveMaxColumn = model . getLineMaxColumn ( aboveLineNumber ) ;
50+ if ( aboveMaxColumn !== 1 ) {
51+ // bingo!
52+ return new Position ( aboveLineNumber , aboveMaxColumn ) ;
53+ }
54+ }
3555
36- this . _currentTokenIndex = i ;
37- this . _next = this . _current ( ) ;
38- this . _prev = this . _current ( ) ;
39- break ;
56+ if ( belowLineNumber <= lineCount ) {
57+ let belowMaxColumn = model . getLineMaxColumn ( belowLineNumber ) ;
58+ if ( belowMaxColumn !== 1 ) {
59+ // bingo!
60+ return new Position ( belowLineNumber , 1 ) ;
4061 }
41- tokenEndIndex = tokenStartIndex ;
4262 }
43- }
4463
45- private _readLineTokens ( lineNumber :number ) : void {
46- this . _currentLineTokens = this . _model . getLineTokens ( lineNumber , false ) ;
64+ distance ++ ;
4765 }
66+ return null ;
67+ }
4868
49- private _advanceNext ( ) {
50- this . _prev = this . _next ;
69+ export class TokenIterator implements editorCommon . ITokenIterator {
70+
71+ private _model :editorCommon . ITokenizedModel ;
72+ private _lineCount :number ;
73+ private _prev :TokenInfo ;
74+ private _next :TokenInfo ;
75+
76+ constructor ( model :editorCommon . ITokenizedModel , position :Position ) {
77+ this . _model = model ;
78+ this . _lineCount = this . _model . getLineCount ( ) ;
79+ this . _prev = null ;
5180 this . _next = null ;
52- if ( this . _currentTokenIndex + 1 < this . _currentLineTokens . getTokenCount ( ) ) {
53- // There are still tokens on current line
54- this . _currentTokenIndex ++ ;
55- this . _next = this . _current ( ) ;
5681
57- } else {
58- // find the next line with tokens
59- while ( this . _currentLineNumber + 1 <= this . _model . getLineCount ( ) ) {
60- this . _currentLineNumber ++ ;
61- this . _readLineTokens ( this . _currentLineNumber ) ;
62- if ( this . _currentLineTokens . getTokenCount ( ) > 0 ) {
63- this . _currentTokenIndex = 0 ;
64- this . _next = this . _current ( ) ;
65- break ;
66- }
67- }
68- if ( this . _next === null ) {
69- // prepare of a previous run
70- this . _readLineTokens ( this . _currentLineNumber ) ;
71- this . _currentTokenIndex = this . _currentLineTokens . getTokenCount ( ) ;
72- this . _advancePrev ( ) ;
73- this . _next = null ;
82+ position = findClosestNonEmptyLine ( model , position ) ;
83+ if ( position ) {
84+ let lineTokens = this . _model . getLineTokens ( position . lineNumber ) ;
85+ let currentToken = lineTokens . findTokenAtOffset ( position . column - 1 ) ;
86+ if ( currentToken ) {
87+ this . _prev = this . _next = new TokenInfo ( currentToken , position . lineNumber ) ;
7488 }
7589 }
7690 }
7791
78- private _advancePrev ( ) {
79- this . _next = this . _prev ;
80- this . _prev = null ;
81- if ( this . _currentTokenIndex > 0 ) {
82- // There are still tokens on current line
83- this . _currentTokenIndex -- ;
84- this . _prev = this . _current ( ) ;
92+ private _advanceNext ( ) : void {
93+ if ( ! this . _next ) {
94+ return ;
95+ }
96+
97+ let lineNumber = this . _next . lineNumber ;
98+ let next = this . _next . _actual . next ( ) ;
99+ while ( ! next && lineNumber < this . _lineCount ) {
100+ lineNumber ++ ;
101+ let currentLineTokens = this . _model . getLineTokens ( lineNumber ) ;
102+ next = currentLineTokens . firstToken ( ) ;
103+ }
85104
105+ this . _prev = this . _next ;
106+ if ( next ) {
107+ this . _next = new TokenInfo ( next , lineNumber ) ;
86108 } else {
87- // find previous line with tokens
88- while ( this . _currentLineNumber > 1 ) {
89- this . _currentLineNumber -- ;
90- this . _readLineTokens ( this . _currentLineNumber ) ;
91- if ( this . _currentLineTokens . getTokenCount ( ) > 0 ) {
92- this . _currentTokenIndex = this . _currentLineTokens . getTokenCount ( ) - 1 ;
93- this . _prev = this . _current ( ) ;
94- break ;
95- }
96- }
109+ this . _next = null ;
97110 }
98111 }
99112
100- private _current ( ) : editorCommon . ITokenInfo {
101- let startIndex = this . _currentLineTokens . getTokenStartOffset ( this . _currentTokenIndex ) ;
102- let type = this . _currentLineTokens . getTokenType ( this . _currentTokenIndex ) ;
103- let endIndex = this . _currentLineTokens . getTokenEndOffset ( this . _currentTokenIndex ) ;
113+ private _advancePrev ( ) : void {
114+ if ( ! this . _prev ) {
115+ return ;
116+ }
104117
105- return {
106- token : new Token ( startIndex , type ) ,
107- lineNumber : this . _currentLineNumber ,
108- startColumn : startIndex + 1 ,
109- endColumn : endIndex + 1
110- } ;
118+ let lineNumber = this . _prev . lineNumber ;
119+ let prev = this . _prev . _actual . prev ( ) ;
120+ while ( ! prev && lineNumber > 1 ) {
121+ lineNumber -- ;
122+ let currentLineTokens = this . _model . getLineTokens ( lineNumber ) ;
123+ prev = currentLineTokens . lastToken ( ) ;
124+ }
125+
126+ this . _next = this . _prev ;
127+ if ( prev ) {
128+ this . _prev = new TokenInfo ( prev , lineNumber ) ;
129+ } else {
130+ this . _prev = null ;
131+ }
111132 }
112133
113134 public hasNext ( ) : boolean {
114135 return this . _next !== null ;
115136 }
116137
117138 public next ( ) : editorCommon . ITokenInfo {
118- var result = this . _next ;
139+ const result = this . _next ;
119140 this . _advanceNext ( ) ;
120141 return result ;
121142 }
@@ -125,7 +146,7 @@ export class TokenIterator implements editorCommon.ITokenIterator {
125146 }
126147
127148 public prev ( ) : editorCommon . ITokenInfo {
128- var result = this . _prev ;
149+ const result = this . _prev ;
129150 this . _advancePrev ( ) ;
130151 return result ;
131152 }
0 commit comments