1 19 20 package org.netbeans.lib.lexer.inc; 21 22 import org.netbeans.api.lexer.TokenId; 23 import org.netbeans.lib.lexer.EmbeddedTokenList; 24 import org.netbeans.lib.lexer.LanguageOperation; 25 import org.netbeans.lib.lexer.LexerInputOperation; 26 import org.netbeans.lib.lexer.LexerUtilsConstants; 27 import org.netbeans.lib.lexer.token.AbstractToken; 28 import org.netbeans.spi.lexer.TokenValidator; 29 30 31 85 86 public final class TokenListUpdater { 87 88 92 public static <T extends TokenId> void update(MutableTokenList<T> tokenList, 93 TokenHierarchyEventInfo eventInfo, TokenListChange<T> change) { 94 if (tokenList.getClass() == EmbeddedTokenList.class) { 96 ((EmbeddedTokenList<? extends TokenId>)tokenList).updateStartOffset(); 97 } 98 99 int modOffset = eventInfo.modificationOffset(); 101 LanguageOperation<T> languageOperation = LexerUtilsConstants.mostEmbeddedLanguageOperation( 102 tokenList.languagePath()); 103 104 int tokenCount = tokenList.tokenCountCurrent(); AbstractToken<T> modToken; 111 int modTokenOffset; 113 int index; 115 116 if (tokenCount == 0) { if (!tokenList.isFullyLexed()) { 118 return; } 121 assert (modOffset == 0); 123 modToken = null; 124 modTokenOffset = 0; 125 index = 0; 126 127 } else { index = tokenCount - 1; 132 modTokenOffset = tokenList.tokenOffset(index); 133 if (modOffset >= modTokenOffset) { modToken = token(tokenList, index); 135 int modTokenEndOffset = modTokenOffset + modToken.length(); 136 if (modOffset >= modTokenEndOffset) { if (!tokenList.isFullyLexed() 145 && modOffset >= modTokenEndOffset + tokenList.lookahead(index) 146 ) 147 return; 149 index++; 150 modToken = null; 151 modTokenOffset = modTokenEndOffset; 152 } 154 } else { int low = 0; while (low < index) { 158 int mid = (low + index) / 2; 159 int midStartOffset = tokenList.tokenOffset(mid); 160 161 if (midStartOffset < modOffset) { 162 low = mid + 1; 163 } else if (midStartOffset > modOffset) { 164 index = mid - 1 < 0 ? 0 : mid - 1; 165 } else { 166 index = mid; 168 modTokenOffset = midStartOffset; 169 break; 170 } 171 } 172 if (index <= low) { modTokenOffset = tokenList.tokenOffset(index); 174 } 175 modToken = token(tokenList, index); 176 } 177 } 178 179 change.setOffsetGapIndex(index); 184 185 int relexIndex; 187 int relexOffset; 188 boolean attemptValidation = false; 190 191 if (index == 0) { relexIndex = index; 193 relexOffset = modTokenOffset; 194 if (modToken != null && eventInfo.removedLength() < modToken.length()) { 196 attemptValidation = true; 197 } 198 199 } else { if (modOffset == modTokenOffset && eventInfo.removedLength() == 0) { 202 index--; modToken = token(tokenList, index); 204 modTokenOffset -= modToken.length(); 205 } 206 207 if (index == 0 || modTokenOffset + tokenList.lookahead(index - 1) <= modOffset) { 209 relexIndex = index; 211 relexOffset = modTokenOffset; 212 if (modOffset + eventInfo.removedLength() < modTokenOffset + modToken.length()) { 214 attemptValidation = true; 215 } 216 217 } else { relexOffset = modTokenOffset - token(tokenList, index - 1).length(); 219 relexIndex = index - 2; 221 while (relexIndex >= 0) { 223 AbstractToken<T> token = token(tokenList, relexIndex); 224 if (relexOffset + tokenList.lookahead(relexIndex) <= modOffset) { 226 break; 227 } 228 relexIndex--; 229 relexOffset -= token.length(); 230 } 231 relexIndex++; } 233 } 234 235 int matchOffset; 241 242 if (attemptValidation) { 245 matchOffset = modTokenOffset + modToken.length(); 246 TokenValidator tokenValidator = languageOperation.tokenValidator(modToken.id()); 247 if (tokenValidator != null 248 && (tokenList.getClass() != IncTokenList.class 249 || eventInfo.tokenHierarchyOperation().canModifyToken(index, modToken)) 250 ) { 251 252 258 } 261 262 } else { if (index < tokenCount) { 266 matchOffset = modTokenOffset + modToken.length(); 267 int removeEndOffset = modOffset + eventInfo.removedLength(); 268 while (matchOffset < removeEndOffset && index + 1 < tokenCount) { 269 index++; 270 matchOffset += token(tokenList, index).length(); 271 } 272 273 } else matchOffset = modTokenOffset; 275 } 276 277 Object relexState = (relexIndex > 0) ? tokenList.state(relexIndex - 1) : null; 279 matchOffset += eventInfo.insertedLength() - eventInfo.removedLength(); 282 change.setOffset(relexOffset); 283 284 295 boolean relex = (relexOffset != matchOffset) 303 || index >= tokenCount 304 || !LexerUtilsConstants.statesEqual(relexState, tokenList.state(index)); 305 306 int lookahead; 312 if (!relex && (lookahead = tokenList.lookahead(index)) > 1 && index + 1 < tokenCount) { 313 relex = (lookahead > token(tokenList, index + 1).length()); } 315 316 if (relex) { LexerInputOperation<T> lexerInputOperation 318 = tokenList.createLexerInputOperation(relexIndex, relexOffset, relexState); 319 320 do { AbstractToken<T> token = lexerInputOperation.nextToken(); 322 if (token == null) { 323 attemptValidation = false; 324 break; 325 } 326 327 lookahead = lexerInputOperation.lookahead(); 328 Object state = lexerInputOperation.lexerState(); 329 change.addToken(token, lookahead, state); 330 331 relexOffset += token.length(); 332 if (relexOffset > matchOffset && index < tokenCount) { 334 attemptValidation = false; 335 do { 336 index++; 337 if (index == tokenCount) { 338 modToken = null; 340 if (tokenList.isFullyLexed()) { 343 matchOffset = Integer.MAX_VALUE; 345 } else { 346 relex = false; 348 } 349 break; 350 } 351 matchOffset += token(tokenList, index).length(); 352 } while (relexOffset > matchOffset); 353 } 354 355 if (relexOffset == matchOffset 358 && (index < tokenCount) 359 && LexerUtilsConstants.statesEqual(state, tokenList.state(index)) 360 ) { 361 int matchTokenLookahead = tokenList.lookahead(index); 376 boolean lookaheadOK = true; 377 if (matchTokenLookahead > 1 || lookahead > 1) { 381 int laCheckIndex = index + 1; 382 int laCheckTokenOffset = matchOffset; 383 while (laCheckIndex < tokenCount) { 384 int laCheckTokenLength = token(tokenList, laCheckIndex).length(); 385 lookahead -= laCheckTokenLength; 386 matchTokenLookahead -= laCheckTokenLength; 387 laCheckTokenOffset += laCheckTokenLength; 388 if (lookahead <= 0 && matchTokenLookahead <=0) { 389 break; } 391 if (lookahead != tokenList.lookahead(laCheckIndex) 392 || matchTokenLookahead > 0 393 ) { 394 index = laCheckIndex; 396 matchOffset = laCheckTokenOffset; 397 lookaheadOK = false; 398 } 400 laCheckIndex++; 401 } 402 } 403 404 if (lookaheadOK) { 405 if (attemptValidation) { 406 attemptValidation = false; 421 } 422 break; 423 } 424 } 425 } while (relex); 426 lexerInputOperation.release(); 427 } 428 429 change.setIndex(relexIndex); 431 change.setAddedEndOffset(relexOffset); 432 tokenList.replaceTokens(eventInfo, change, 433 (modToken != null) ? (index - relexIndex + 1) : (index - relexIndex)); 434 } 435 436 private static <T extends TokenId> AbstractToken<T> token(MutableTokenList<T> tokenList, int index) { 437 Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainerUnsync(index); return LexerUtilsConstants.token(tokenOrEmbeddingContainer); 439 } 440 441 } 442 | Popular Tags |