@@ -106,14 +106,28 @@ export class CodeMirrorExtension extends CodeMirrorTokensProvider implements IEd
106106
107107 let cellTokens = this . editor . getTokens ( ) ;
108108
109- let usagesBeforeTarget = CodeMirrorExtension . _countUsagesBefore ( lookupName , target ) ;
109+ let typeFilterOn = (
110+ target . className . includes ( 'cm-variable' )
111+ ||
112+ target . className . includes ( 'cm-property' )
113+ ) ;
114+
115+ let lookupType = (
116+ target . className . indexOf ( 'cm-variable' ) !== - 1
117+ ? 'variable'
118+ : 'property'
119+ ) ;
120+
121+ let classFilter = 'cm-' + lookupType ;
122+
123+ let usagesBeforeTarget = CodeMirrorExtension . _countUsagesBefore ( lookupName , target , classFilter , typeFilterOn ) ;
110124
111125 // select relevant token
112126 let token = null ;
113127 let matchedTokensCount = 0 ;
114128 for ( let j = 0 ; j < cellTokens . length ; j ++ ) {
115129 let testedToken = cellTokens [ j ] ;
116- if ( testedToken . value === lookupName ) {
130+ if ( testedToken . value === lookupName && ( ! typeFilterOn || lookupType === testedToken . type ) ) {
117131 matchedTokensCount += 1 ;
118132 if ( matchedTokensCount - 1 === usagesBeforeTarget ) {
119133 token = testedToken ;
@@ -131,48 +145,63 @@ export class CodeMirrorExtension extends CodeMirrorTokensProvider implements IEd
131145 token = {
132146 value : lookupName ,
133147 offset : 0 , // dummy offset
134- type :
135- target . className . indexOf ( 'cm-variable' ) !== - 1
136- ? 'variable'
137- : 'property'
148+ type : lookupType
138149 } ;
139150 }
140151
141152 return token ;
142153 }
143154
144- static _countUsagesBefore ( lookupName : string , target : Node ) {
155+ static _countUsagesBefore ( lookupName : string , target : Node , classFilter : string , classFilterOn : boolean ) {
145156
146157 // count tokens with same value that occur before
147158 // (not all the tokens - to reduce the hurdle of
148159 // mapping DOM into tokens)
149160 let usagesBeforeTarget = - 1 ;
150161 let sibling = target as Node ;
151162
152- while ( sibling != null ) {
153- if ( sibling . textContent === lookupName ) {
163+ const root = sibling . getRootNode ( ) ;
164+
165+ // usually should not exceed that level, but to prevent huge files from trashing the UI...
166+ let max_iter = 10000 ;
167+
168+ function stop_condition ( node : Node ) {
169+ return ! node || ( node . nodeType == 1 && ( node as HTMLElement ) . className . includes ( 'CodeMirror-lines' ) )
170+ }
171+
172+ while ( ! stop_condition ( sibling ) && ! sibling . isEqualNode ( root ) && max_iter ) {
173+
174+ if (
175+ sibling . textContent === lookupName &&
176+ (
177+ ! classFilterOn ||
178+ (
179+ sibling . nodeType === 1 &&
180+ ( sibling as HTMLElement ) . className . includes ( classFilter )
181+ )
182+ )
183+ ) {
154184 usagesBeforeTarget += 1 ;
155185 }
156186
157187 let nextSibling = sibling . previousSibling ;
158188
159- if ( nextSibling == null ) {
160- // Try to traverse to previous line (if there is one).
161-
162- // The additional parent (child) which is traversed
163- // both ways is a non-relevant presentation container.
164- let thisLine = sibling . parentNode . parentNode as HTMLElement ;
165- let previousLine = thisLine . previousElementSibling ;
166-
167- // is is really a line?
168- if (
169- previousLine &&
170- previousLine . className . indexOf ( 'CodeMirror-line' ) !== - 1
171- ) {
172- nextSibling = previousLine . firstChild . lastChild ;
189+ while ( nextSibling == null ) {
190+ while ( ! sibling . previousSibling ) {
191+ sibling = sibling . parentNode ;
192+ if ( stop_condition ( sibling ) ) {
193+ return usagesBeforeTarget ;
194+ }
195+ }
196+ sibling = sibling . previousSibling ;
197+ while ( sibling . lastChild && sibling . textContent != lookupName ) {
198+ sibling = sibling . lastChild ;
173199 }
200+ nextSibling = sibling ;
174201 }
175202 sibling = nextSibling ;
203+
204+ max_iter -= 1 ;
176205 }
177206
178207 return usagesBeforeTarget ;
0 commit comments