1 19 20 package org.netbeans.lib.lexer.inc; 21 22 import java.util.List ; 23 import java.util.Set ; 24 import org.netbeans.api.lexer.LanguagePath; 25 import org.netbeans.lib.lexer.LAState; 26 import org.netbeans.lib.lexer.LexerSpiPackageAccessor; 27 import org.netbeans.lib.lexer.TextLexerInputOperation; 28 import org.netbeans.lib.lexer.TokenList; 29 import org.netbeans.lib.editor.util.FlyOffsetGapList; 30 import org.netbeans.lib.lexer.EmbeddingContainer; 31 import org.netbeans.lib.lexer.LexerInputOperation; 32 import org.netbeans.lib.lexer.LexerUtilsConstants; 33 import org.netbeans.api.lexer.InputAttributes; 34 import org.netbeans.api.lexer.Token; 35 import org.netbeans.api.lexer.TokenId; 36 import org.netbeans.lib.lexer.TokenHierarchyOperation; 37 import org.netbeans.spi.lexer.MutableTextInput; 38 import org.netbeans.lib.lexer.token.AbstractToken; 39 import org.netbeans.lib.lexer.token.TextToken; 40 41 42 58 59 public final class IncTokenList<T extends TokenId> 60 extends FlyOffsetGapList<Object > implements MutableTokenList<T> { 61 62 private final TokenHierarchyOperation<?,T> tokenHierarchyOperation; 63 64 private final MutableTextInput<?> mutableTextInput; 65 66 private final LanguagePath languagePath; 67 68 private final InputAttributes inputAttributes; 69 70 private CharSequence text; 71 72 75 private LexerInputOperation<T> lexerInputOperation; 76 77 private int rootModCount; 78 79 private LAState laState; 80 81 82 public IncTokenList(TokenHierarchyOperation<?,T> tokenHierarchyOperation, 83 MutableTextInput<?> mutableTextInput) { 84 this.tokenHierarchyOperation = tokenHierarchyOperation; 85 this.mutableTextInput = mutableTextInput; 86 this.languagePath = LanguagePath.get( 87 LexerSpiPackageAccessor.get().language(mutableTextInput)); 88 this.inputAttributes = LexerSpiPackageAccessor.get().inputAttributes(mutableTextInput); 89 this.text = LexerSpiPackageAccessor.get().text(mutableTextInput); 90 this.laState = LAState.empty(); 91 initLexing(); 92 } 93 94 private void initLexing() { 95 this.lexerInputOperation = new TextLexerInputOperation<T>(this, text); 96 } 97 98 public LanguagePath languagePath() { 99 return languagePath; 100 } 101 102 public synchronized int tokenCount() { 103 if (lexerInputOperation != null) { tokenOrEmbeddingContainerImpl(Integer.MAX_VALUE); 105 } 106 return size(); 107 } 108 109 public char childTokenCharAt(int rawOffset, int index) { 110 return text.charAt(childTokenOffset(rawOffset) + index); 111 } 112 113 public int childTokenOffset(int rawOffset) { 114 return (rawOffset < offsetGapStart() 115 ? rawOffset 116 : rawOffset - offsetGapLength()); 117 } 118 119 public int tokenOffset(int index) { 120 return elementOffset(index); 121 } 122 123 public int existingTokensEndOffset() { 124 return elementOrEndOffset(tokenCountCurrent()); 125 } 126 127 131 public int modCount() { 132 return rootModCount; 133 } 134 135 public void incrementModCount() { 136 rootModCount++; 137 } 138 139 public synchronized Object tokenOrEmbeddingContainer(int index) { 140 return tokenOrEmbeddingContainerImpl(index); 141 } 142 143 private Object tokenOrEmbeddingContainerImpl(int index) { 144 while (lexerInputOperation != null && index >= size()) { 145 Token token = lexerInputOperation.nextToken(); 146 if (token != null) { updateElementOffsetAdd(token); 148 add(token); 149 laState = laState.add(lexerInputOperation.lookahead(), 150 lexerInputOperation.lexerState()); 151 } else { lexerInputOperation.release(); 153 lexerInputOperation = null; 154 trimToSize(); 155 laState.trimToSize(); 156 } 157 } 158 return (index < size()) ? get(index) : null; 159 } 160 161 public synchronized AbstractToken<T> replaceFlyToken( 162 int index, AbstractToken<T> flyToken, int offset) { 163 TextToken<T> nonFlyToken = ((TextToken<T>)flyToken).createCopy(this, offset2Raw(offset)); 164 set(index, nonFlyToken); 165 return nonFlyToken; 166 } 167 168 public synchronized void wrapToken(int index, EmbeddingContainer embeddingContainer) { 169 set(index, embeddingContainer); 170 } 171 172 public InputAttributes inputAttributes() { 173 return inputAttributes; 174 } 175 176 protected int elementRawOffset(Object elem) { 177 return LexerUtilsConstants.token(elem).rawOffset(); 178 } 179 180 protected void setElementRawOffset(Object elem, int rawOffset) { 181 LexerUtilsConstants.token(elem).setRawOffset(rawOffset); 182 } 183 184 protected boolean isElementFlyweight(Object elem) { 185 return (elem.getClass() != EmbeddingContainer.class) 187 && ((AbstractToken)elem).isFlyweight(); 188 } 189 190 protected int elementLength(Object elem) { 191 return LexerUtilsConstants.token(elem).length(); 192 } 193 194 private AbstractToken<T> existingToken(int index) { 195 return LexerUtilsConstants.token(tokenOrEmbeddingContainer(index)); 198 } 199 200 public Object tokenOrEmbeddingContainerUnsync(int index) { 201 return get(index); 204 } 205 206 public int lookahead(int index) { 207 return laState.lookahead(index); 208 } 209 210 public Object state(int index) { 211 return laState.state(index); 212 } 213 214 public int tokenCountCurrent() { 215 return size(); 216 } 217 218 public TokenList<? extends TokenId> root() { 219 return this; 220 } 221 222 public TokenHierarchyOperation<?,? extends TokenId> tokenHierarchyOperation() { 223 return tokenHierarchyOperation; 224 } 225 226 public LexerInputOperation<T> createLexerInputOperation( 227 int tokenIndex, int relexOffset, Object relexState) { 228 return new TextLexerInputOperation<T>(this, tokenIndex, relexState, 230 text, 0, relexOffset, text.length()); 231 } 232 233 public boolean isFullyLexed() { 234 return (lexerInputOperation == null); 235 } 236 237 public void replaceTokens(TokenHierarchyEventInfo eventInfo, 238 TokenListChange<T> change, int removeTokenCount) { 239 int index = change.index(); 240 Object [] removedTokensOrBranches = new Object [removeTokenCount]; 242 copyElements(index, index + removeTokenCount, removedTokensOrBranches, 0); 243 int offset = change.offset(); 244 for (int i = 0; i < removeTokenCount; i++) { 245 Object tokenOrEmbeddingContainer = removedTokensOrBranches[i]; 246 AbstractToken<T> token = LexerUtilsConstants.token(tokenOrEmbeddingContainer); 247 if (!token.isFlyweight()) { 248 updateElementOffsetRemove(token); 249 token.setTokenList(null); 250 } 251 offset += token.length(); 252 } 253 remove(index, removeTokenCount); laState.remove(index, removeTokenCount); change.setRemovedTokens(removedTokensOrBranches); 256 change.setRemovedEndOffset(offset); 257 258 int diffLength = eventInfo.insertedLength() - eventInfo.removedLength(); 260 if (offsetGapStart() != change.offset()) { 261 moveOffsetGap(change.offset(), Math.min(index, change.offsetGapIndex())); 263 } 264 updateOffsetGapLength(-diffLength); 265 266 List <AbstractToken<T>> addedTokens = change.addedTokens(); 268 if (addedTokens != null) { 269 for (int i = 0; i < addedTokens.size(); i++) { 270 AbstractToken<T> token = addedTokens.get(i); 271 updateElementOffsetAdd(token); 272 } 273 addAll(index, addedTokens); 274 laState = laState.addAll(index, change.laState()); 275 change.syncAddedTokenCount(); 276 } 277 } 278 279 private void releaseLexerInputOperation() { 280 if (lexerInputOperation != null) 281 lexerInputOperation.release(); 282 } 283 284 public void refreshLexerInputOperation() { 285 releaseLexerInputOperation(); 286 int lastTokenIndex = tokenCountCurrent() - 1; 287 lexerInputOperation = createLexerInputOperation( 288 lastTokenIndex + 1, 289 existingTokensEndOffset(), 290 (lastTokenIndex >= 0) ? state(lastTokenIndex) : null 291 ); 292 } 293 294 public void restartLexing() { 295 releaseLexerInputOperation(); 297 initLexing(); 298 } 299 300 public boolean isContinuous() { 301 return true; 302 } 303 304 public Set <T> skipTokenIds() { 305 return null; 306 } 307 308 public String toString() { 309 return LexerUtilsConstants.appendTokenList(null, this, -1).toString(); 310 } 311 312 } 313 | Popular Tags |