1 19 20 package org.netbeans.lib.lexer; 21 22 import java.util.List ; 23 import java.util.Set ; 24 import org.netbeans.api.lexer.LanguagePath; 25 import org.netbeans.lib.editor.util.FlyOffsetGapList; 26 import org.netbeans.lib.lexer.inc.MutableTokenList; 27 import org.netbeans.api.lexer.InputAttributes; 28 import org.netbeans.api.lexer.Token; 29 import org.netbeans.api.lexer.TokenId; 30 import org.netbeans.lib.lexer.inc.TokenHierarchyEventInfo; 31 import org.netbeans.lib.lexer.inc.TokenListChange; 32 import org.netbeans.spi.lexer.LanguageEmbedding; 33 import org.netbeans.lib.lexer.token.AbstractToken; 34 import org.netbeans.lib.lexer.token.TextToken; 35 36 37 53 54 public final class EmbeddedTokenList<T extends TokenId> 55 extends FlyOffsetGapList<Object > implements MutableTokenList<T> { 56 57 58 private static final boolean testing = Boolean.getBoolean("netbeans.debug.lexer.test"); 59 60 64 private final EmbeddingContainer<? extends TokenId> embeddingContainer; 66 69 private final LanguageEmbedding<T> embedding; 71 74 private final LanguagePath languagePath; 76 82 private LAState laState; 84 87 private EmbeddedTokenList<? extends TokenId> nextEmbedding; 89 public EmbeddedTokenList(EmbeddingContainer<? extends TokenId> embeddingContainer, 90 LanguagePath languagePath, LanguageEmbedding<T> embedding, 91 EmbeddedTokenList<? extends TokenId> nextEmbedding) { 92 this.embeddingContainer = embeddingContainer; 93 this.languagePath = languagePath; 94 this.embedding = embedding; 95 this.nextEmbedding = nextEmbedding; 96 97 if (embeddingContainer.rootTokenList().modCount() != -1 || testing) { 98 this.laState = LAState.empty(); } 100 101 init(); 102 } 103 104 private void init() { 105 LexerInputOperation<T> lexerInputOperation = createLexerInputOperation( 107 0, startOffset(), null); 108 AbstractToken<T> token = lexerInputOperation.nextToken(); 109 while (token != null) { 110 updateElementOffsetAdd(token); add(token); 112 if (laState != null) { 113 laState = laState.add(lexerInputOperation.lookahead(), 114 lexerInputOperation.lexerState()); 115 } 116 token = lexerInputOperation.nextToken(); 117 } 118 lexerInputOperation.release(); 119 lexerInputOperation = null; 120 121 trimToSize(); if (laState != null) 123 laState.trimToSize(); 124 } 125 126 EmbeddedTokenList<? extends TokenId> nextEmbedding() { 127 return nextEmbedding; 128 } 129 130 void setNextEmbedding(EmbeddedTokenList<? extends TokenId> nextEmbedding) { 131 this.nextEmbedding = nextEmbedding; 132 } 133 134 public LanguagePath languagePath() { 135 return languagePath; 136 } 137 138 public int tokenCount() { 139 return size(); 141 } 142 143 public synchronized Object tokenOrEmbeddingContainer(int index) { 144 return (index < size()) ? get(index) : null; 146 } 147 148 private Token existingToken(int index) { 149 return LexerUtilsConstants.token(tokenOrEmbeddingContainer(index)); 151 } 152 153 public int lookahead(int index) { 154 return (laState != null) ? laState.lookahead(index) : -1; 155 } 156 157 public Object state(int index) { 158 return (laState != null) ? laState.state(index) : null; 159 } 160 161 168 public int tokenOffset(int index) { 169 return elementOffset(index); 170 } 171 172 public int childTokenOffset(int rawOffset) { 173 embeddingContainer.updateOffsets(); 175 return embeddingContainer.tokenStartOffset() + embedding.startSkipLength() 176 + childTokenRelOffset(rawOffset); 177 } 178 179 183 public int childTokenOffsetShift(int rawOffset) { 184 updateStartOffset(); 186 return embeddingContainer.rootTokenOffsetShift() + childTokenRelOffset(rawOffset); 187 } 188 189 193 private int childTokenRelOffset(int rawOffset) { 194 return (rawOffset < offsetGapStart()) 195 ? rawOffset 196 : rawOffset - offsetGapLength(); 197 } 198 199 public char childTokenCharAt(int rawOffset, int index) { 200 return embeddingContainer.charAt( 205 embedding.startSkipLength() + childTokenRelOffset(rawOffset) + index); 206 } 207 208 public int modCount() { 209 return root().modCount(); 211 } 212 213 protected int startOffset() { return embeddingContainer.tokenStartOffset() + embedding.startSkipLength(); 215 } 216 217 public void updateStartOffset() { 218 embeddingContainer.updateOffsets(); 219 } 220 221 public TokenList<? extends TokenId> root() { 222 return embeddingContainer.rootTokenList(); 223 } 224 225 public TokenHierarchyOperation<?,? extends TokenId> tokenHierarchyOperation() { 226 return root().tokenHierarchyOperation(); 227 } 228 229 public AbstractToken<? extends TokenId> rootToken() { 230 return embeddingContainer.rootToken(); 231 } 232 233 protected int elementRawOffset(Object elem) { 234 return (elem.getClass() == EmbeddingContainer.class) 235 ? ((EmbeddingContainer)elem).token().rawOffset() 236 : ((AbstractToken<? extends TokenId>)elem).rawOffset(); 237 } 238 239 protected void setElementRawOffset(Object elem, int rawOffset) { 240 if (elem.getClass() == EmbeddingContainer.class) 241 ((EmbeddingContainer)elem).token().setRawOffset(rawOffset); 242 else 243 ((AbstractToken<? extends TokenId>)elem).setRawOffset(rawOffset); 244 } 245 246 protected boolean isElementFlyweight(Object elem) { 247 return (elem.getClass() != EmbeddingContainer.class) 249 && ((AbstractToken<? extends TokenId>)elem).isFlyweight(); 250 } 251 252 protected int elementLength(Object elem) { 253 return LexerUtilsConstants.token(elem).length(); 254 } 255 256 public synchronized AbstractToken<T> replaceFlyToken( 257 int index, AbstractToken<T> flyToken, int offset) { 258 TextToken<T> nonFlyToken = ((TextToken<T>)flyToken).createCopy(this, offset2Raw(offset)); 259 set(index, nonFlyToken); 260 return nonFlyToken; 261 } 262 263 public synchronized void wrapToken(int index, EmbeddingContainer embeddingContainer) { 264 set(index, embeddingContainer); 265 } 266 267 public InputAttributes inputAttributes() { 268 return root().inputAttributes(); 269 } 270 271 public Object tokenOrEmbeddingContainerUnsync(int index) { 273 return get(index); 274 } 275 276 public int tokenCountCurrent() { 277 return size(); 278 } 279 280 public LexerInputOperation<T> createLexerInputOperation( 281 int tokenIndex, int relexOffset, Object relexState) { 282 CharSequence tokenText = embeddingContainer.token().text(); 283 int tokenStartOffset = embeddingContainer.tokenStartOffset(); 284 int endOffset = tokenStartOffset + tokenText.length() 285 - embedding.endSkipLength(); 286 return new TextLexerInputOperation<T>(this, tokenIndex, relexState, tokenText, 290 tokenStartOffset, relexOffset, endOffset); 291 } 292 293 public boolean isFullyLexed() { 294 return true; 295 } 296 297 public void replaceTokens(TokenHierarchyEventInfo eventInfo, 298 TokenListChange<T> change, int removeTokenCount) { 299 int index = change.index(); 300 Object [] removedTokensOrEmbeddingContainers = new Object [removeTokenCount]; 302 copyElements(index, index + removeTokenCount, removedTokensOrEmbeddingContainers, 0); 303 int offset = change.offset(); 304 for (int i = 0; i < removeTokenCount; i++) { 305 Object tokenOrEmbeddingContainer = removedTokensOrEmbeddingContainers[i]; 306 AbstractToken<T> token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 307 if (!token.isFlyweight()) { 308 updateElementOffsetRemove(token); 309 token.setTokenList(null); 310 } 311 offset += token.length(); 312 } 313 remove(index, removeTokenCount); laState.remove(index, removeTokenCount); change.setRemovedTokens(removedTokensOrEmbeddingContainers); 316 change.setRemovedEndOffset(offset); 317 318 int diffLength = eventInfo.insertedLength() - eventInfo.removedLength(); 320 if (offsetGapStart() != change.offset()) { 321 moveOffsetGap(change.offset(), Math.min(index, change.offsetGapIndex())); 323 } 324 updateOffsetGapLength(-diffLength); 325 326 List <AbstractToken<T>> addedTokens = change.addedTokens(); 328 if (addedTokens != null) { 329 for (Token token : addedTokens) { 330 updateElementOffsetAdd(token); 331 } 332 addAll(index, addedTokens); 333 laState = laState.addAll(index, change.laState()); 334 change.syncAddedTokenCount(); 335 } 336 } 337 338 public boolean isContinuous() { 339 return true; 340 } 341 342 public Set <T> skipTokenIds() { 343 return null; 344 } 345 346 public String toString() { 347 return LexerUtilsConstants.appendTokenList(null, this, -1).toString(); 348 } 349 350 } 351 | Popular Tags |