This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 90796
Collapse All | Expand All

(-)html/editor/lib/src/org/netbeans/editor/ext/html/HTMLSyntaxSupport.java (-1 / +2 lines)
Lines 133-139 Link Here
133
            
133
            
134
            // if the carret is after HTML tag ( after char '>' ), ship inside the tag
134
            // if the carret is after HTML tag ( after char '>' ), ship inside the tag
135
            if (token.id() == HTMLTokenId.TAG_CLOSE_SYMBOL) {
135
            if (token.id() == HTMLTokenId.TAG_CLOSE_SYMBOL) {
136
                if(ts.moveIndex(ts.index() - 2)) {
136
                ts.moveIndex(ts.index() - 2);
137
                if(ts.moveNext()) {
137
                    token = ts.token();
138
                    token = ts.token();
138
                }
139
                }
139
            }
140
            }
(-)java/editor/src/org/netbeans/modules/editor/java/JavaCompletionProvider.java (-8 / +11 lines)
Lines 1101-1109 Link Here
1101
            int openLtNum = 0;
1101
            int openLtNum = 0;
1102
            JavaTokenId lastNonWhitespaceTokenId = null;
1102
            JavaTokenId lastNonWhitespaceTokenId = null;
1103
            TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
1103
            TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
1104
            if (ts.move(expEndPos) > 0)
1104
            ts.move(expEndPos);
1105
                ts.moveNext();
1105
            while (ts.moveNext()) {
1106
            do {
1107
                if (ts.offset() >= offset) {
1106
                if (ts.offset() >= offset) {
1108
                    break;
1107
                    break;
1109
                }
1108
                }
Lines 1136-1142 Link Here
1136
                    default:
1135
                    default:
1137
                        lastNonWhitespaceTokenId = ts.token().id();
1136
                        lastNonWhitespaceTokenId = ts.token().id();
1138
                }
1137
                }
1139
            } while (ts.moveNext());
1138
            }
1140
            if (!afterDot) {
1139
            if (!afterDot) {
1141
                if (expEndPos <= offset)
1140
                if (expEndPos <= offset)
1142
                    insideExpression(env, new TreePath(path, fa.getExpression()));
1141
                    insideExpression(env, new TreePath(path, fa.getExpression()));
Lines 3403-3410 Link Here
3403
        
3402
        
3404
        private TokenSequence<JavaTokenId> findLastNonWhitespaceToken(Env env, int startPos, int endPos) {
3403
        private TokenSequence<JavaTokenId> findLastNonWhitespaceToken(Env env, int startPos, int endPos) {
3405
            TokenSequence<JavaTokenId> ts = env.getController().getTokenHierarchy().tokenSequence(JavaTokenId.language());
3404
            TokenSequence<JavaTokenId> ts = env.getController().getTokenHierarchy().tokenSequence(JavaTokenId.language());
3406
            if (ts.move(endPos) == 0)
3405
            if (ts.move(endPos) == 0) // When right at the token end
3407
                ts.movePrevious();
3406
                ts.movePrevious(); // move to previous token
3407
            else
3408
                ts.moveNext(); // otherwise move to the token that "contains" the offset
3408
            do {
3409
            do {
3409
                int offset = ts.offset();
3410
                int offset = ts.offset();
3410
                if (offset < startPos)
3411
                if (offset < startPos)
Lines 3541-3548 Link Here
3541
            if (upToOffset) {
3542
            if (upToOffset) {
3542
                TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
3543
                TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
3543
                if (ts.moveNext()) { //check for empty file
3544
                if (ts.moveNext()) { //check for empty file
3544
                    if (ts.move(offset) == 0)
3545
                    if (ts.move(offset) == 0) // When right at the token end
3545
                        ts.movePrevious();
3546
                        ts.movePrevious(); // Move to previous token
3547
                    else
3548
                        ts.moveNext(); // otherwise move to the token that "contains" the offset
3546
                    if (ts.offset() < offset && (ts.token().id() == JavaTokenId.IDENTIFIER || "keyword".equals(ts.token().id().primaryCategory()))) { //TODO: Use isKeyword(...) when available
3549
                    if (ts.offset() < offset && (ts.token().id() == JavaTokenId.IDENTIFIER || "keyword".equals(ts.token().id().primaryCategory()))) { //TODO: Use isKeyword(...) when available
3547
                        prefix = ts.token().toString().substring(0, offset - ts.offset());
3550
                        prefix = ts.token().toString().substring(0, offset - ts.offset());
3548
                        offset = ts.offset();
3551
                        offset = ts.offset();
(-)java/editor/src/org/netbeans/modules/editor/java/Utilities.java (+2 lines)
Lines 98-103 Link Here
98
            return false;
98
            return false;
99
        if (!ts.moveNext() || ts.move(offset) == 0)
99
        if (!ts.moveNext() || ts.move(offset) == 0)
100
            return true;
100
            return true;
101
        ts.moveNext();
101
        switch(ts.token().id()) {
102
        switch(ts.token().id()) {
102
            case DOUBLE_LITERAL:
103
            case DOUBLE_LITERAL:
103
                if (ts.token().text().charAt(0) == '.')
104
                if (ts.token().text().charAt(0) == '.')
Lines 127-132 Link Here
127
            TokenSequence<? extends TokenId> ts = hierarchy.tokenSequence();
128
            TokenSequence<? extends TokenId> ts = hierarchy.tokenSequence();
128
            while(ts != null && ts.moveNext()) {
129
            while(ts != null && ts.moveNext()) {
129
                ts.move(offset);
130
                ts.move(offset);
131
                ts.moveNext();
130
                if (ts.language() == JavaTokenId.language())
132
                if (ts.language() == JavaTokenId.language())
131
                    return (TokenSequence<JavaTokenId>)ts;
133
                    return (TokenSequence<JavaTokenId>)ts;
132
                ts = ts.embedded();
134
                ts = ts.embedded();
(-)java/hints/src/org/netbeans/modules/java/hints/JavaHintsProvider.java (-13 / +13 lines)
Lines 175-197 Link Here
175
        TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence();
175
        TokenSequence<JavaTokenId> ts = info.getTokenHierarchy().tokenSequence();
176
        
176
        
177
        ts.move(offset);
177
        ts.move(offset);
178
        
178
        if (ts.moveNext()) {
179
        Token t = ts.token();
179
            Token t = ts.token();
180
        
180
181
        if (t.id() == JavaTokenId.DOT) {
181
            if (t.id() == JavaTokenId.DOT) {
182
            ts.moveNext();
183
            t = ts.token();
184
        } else {
185
            if (t.id() == JavaTokenId.LT) {
186
                ts.moveNext();
182
                ts.moveNext();
187
                t = ts.token();
183
                t = ts.token();
184
            } else {
185
                if (t.id() == JavaTokenId.LT) {
186
                    ts.moveNext();
187
                    t = ts.token();
188
                }
189
            }
190
191
            if (t.id() == JavaTokenId.IDENTIFIER) {
192
                return ts.offsetToken();
188
            }
193
            }
189
        }
194
        }
190
        
191
        if (t.id() == JavaTokenId.IDENTIFIER) {
192
            return ts.offsetToken();
193
        }
194
        
195
        return null;
195
        return null;
196
    }
196
    }
197
    
197
    
(-)java/source/src/org/netbeans/api/java/source/TreeUtilities.java (-1 / +2 lines)
Lines 158-164 Link Here
158
            return path;
158
            return path;
159
        
159
        
160
        TokenSequence<JavaTokenId> tokenList = tokensFor(path.getLeaf(), sourcePositions);
160
        TokenSequence<JavaTokenId> tokenList = tokensFor(path.getLeaf(), sourcePositions);
161
        if (tokenList.moveLast() && tokenList.offset() < pos) {
161
        tokenList.moveEnd();
162
        if (tokenList.movePrevious() && tokenList.offset() < pos) {
162
            switch (tokenList.token().id()) {
163
            switch (tokenList.token().id()) {
163
                case GTGTGT:
164
                case GTGTGT:
164
                case GTGT:
165
                case GTGT:
(-)java/source/src/org/netbeans/modules/java/source/save/CasualDiff.java (-3 / +9 lines)
Lines 317-322 Link Here
317
        // skip the section when printing anonymous class
317
        // skip the section when printing anonymous class
318
        if (anonClass == false) {
318
        if (anonClass == false) {
319
        tokenSequence.move(oldT.pos);
319
        tokenSequence.move(oldT.pos);
320
        tokenSequence.moveNext(); // First skip as move() does not position to token directly
320
        tokenSequence.moveNext();
321
        tokenSequence.moveNext();
321
        insertHint = TokenUtilities.moveNext(tokenSequence, tokenSequence.offset());
322
        insertHint = TokenUtilities.moveNext(tokenSequence, tokenSequence.offset());
322
        localPointer = diffModifiers(oldT.mods, newT.mods, oldT, localPointer);
323
        localPointer = diffModifiers(oldT.mods, newT.mods, oldT, localPointer);
Lines 510-515 Link Here
510
            // there was not any parameter in original tree.
511
            // there was not any parameter in original tree.
511
            int startOffset = oldT.restype != null ? oldT.restype.getStartPosition() : oldT.getStartPosition();
512
            int startOffset = oldT.restype != null ? oldT.restype.getStartPosition() : oldT.getStartPosition();
512
            
513
            
514
            // Extra move()? - performed in moveFwdToToken()
513
            tokenSequence.move(startOffset);
515
            tokenSequence.move(startOffset);
514
            TokenUtilities.moveFwdToToken(tokenSequence, startOffset, JavaTokenId.RPAREN);
516
            TokenUtilities.moveFwdToToken(tokenSequence, startOffset, JavaTokenId.RPAREN);
515
            posHint = tokenSequence.offset();
517
            posHint = tokenSequence.offset();
Lines 529-534 Link Here
529
            // now check, that there is a whitespace. It is not mandatory, we
531
            // now check, that there is a whitespace. It is not mandatory, we
530
            // have to ensure. If whitespace is not present, take body beginning
532
            // have to ensure. If whitespace is not present, take body beginning
531
            tokenSequence.move(posHint);
533
            tokenSequence.move(posHint);
534
            tokenSequence.moveNext();
532
            if (tokenSequence.token().id() != JavaTokenId.WHITESPACE) {
535
            if (tokenSequence.token().id() != JavaTokenId.WHITESPACE) {
533
                ++posHint;
536
                ++posHint;
534
            }
537
            }
Lines 1411-1417 Link Here
1411
            ResultItem<JCTree> item = result[j];
1414
            ResultItem<JCTree> item = result[j];
1412
            switch (item.operation) {
1415
            switch (item.operation) {
1413
                case MODIFY: {
1416
                case MODIFY: {
1414
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1417
                    tokenSequence.moveIndex(matrix[i][4]);
1418
                    if (tokenSequence.moveNext()) {
1415
                        testPos = tokenSequence.offset();
1419
                        testPos = tokenSequence.offset();
1416
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1420
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1417
                            testPos += JavaTokenId.COMMA.fixedText().length();
1421
                            testPos += JavaTokenId.COMMA.fixedText().length();
Lines 1454-1460 Link Here
1454
                    assert startOffset != -1 && endOffset != -1 : "Invalid offset!";
1458
                    assert startOffset != -1 && endOffset != -1 : "Invalid offset!";
1455
                    //printer.print(origText.substring(lastOldPos, startOffset));
1459
                    //printer.print(origText.substring(lastOldPos, startOffset));
1456
                    //append(Diff.delete(startOffset, endOffset));
1460
                    //append(Diff.delete(startOffset, endOffset));
1457
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1461
                    tokenSequence.moveIndex(matrix[i][4]);
1462
                    if (tokenSequence.moveNext()) {
1458
                        testPos = tokenSequence.offset();
1463
                        testPos = tokenSequence.offset();
1459
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1464
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1460
                            testPos += JavaTokenId.COMMA.fixedText().length();
1465
                            testPos += JavaTokenId.COMMA.fixedText().length();
Lines 1468-1474 Link Here
1468
                    break;
1473
                    break;
1469
                }
1474
                }
1470
                case NOCHANGE: {
1475
                case NOCHANGE: {
1471
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1476
                    tokenSequence.moveIndex(matrix[i][4]);
1477
                    if (tokenSequence.moveNext()) {
1472
                        testPos = tokenSequence.offset();
1478
                        testPos = tokenSequence.offset();
1473
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1479
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1474
                            testPos += JavaTokenId.COMMA.fixedText().length();
1480
                            testPos += JavaTokenId.COMMA.fixedText().length();
(-)java/source/src/org/netbeans/modules/java/source/save/PositionEstimator.java (+11 lines)
Lines 139-144 Link Here
139
                int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
139
                int treeEnd = (int) positions.getEndPosition(compilationUnit, item);
140
                
140
                
141
                seq.move(treeStart);
141
                seq.move(treeStart);
142
                // seq.index() set (no seq.moveNext() necessary)
142
                int startIndex = seq.index();
143
                int startIndex = seq.index();
143
                
144
                
144
                // go back to opening/closing curly, semicolon or other
145
                // go back to opening/closing curly, semicolon or other
Lines 147-155 Link Here
147
                seq.moveNext();
148
                seq.moveNext();
148
                int start = seq.index();
149
                int start = seq.index();
149
                seq.move(treeEnd);
150
                seq.move(treeEnd);
151
                // seq.index() set (no seq.moveNext() necessary)
150
                matrix[i++] = new int[] { start, startIndex, seq.index() };
152
                matrix[i++] = new int[] { start, startIndex, seq.index() };
151
                if (i == size) {
153
                if (i == size) {
152
                    seq.move(treeEnd);
154
                    seq.move(treeEnd);
155
                    // seq.index() set (no seq.moveNext() necessary)
153
                    matrix[i][0] = seq.index();
156
                    matrix[i][0] = seq.index();
154
                }
157
                }
155
            }
158
            }
Lines 163-168 Link Here
163
            // to decide.
166
            // to decide.
164
            if (tokenIndex == -1) return -1;
167
            if (tokenIndex == -1) return -1;
165
            seq.moveIndex(tokenIndex);
168
            seq.moveIndex(tokenIndex);
169
            seq.moveNext();
166
            return index == 0 ? goAfterLastNewLine(seq) : goAfterFirstNewLine(seq);
170
            return index == 0 ? goAfterLastNewLine(seq) : goAfterFirstNewLine(seq);
167
        }
171
        }
168
172
Lines 210-217 Link Here
210
        public int[] getPositions(int index) {
214
        public int[] getPositions(int index) {
211
            int tokenIndex = matrix[index][0];
215
            int tokenIndex = matrix[index][0];
212
            seq.moveIndex(tokenIndex);
216
            seq.moveIndex(tokenIndex);
217
            seq.moveNext();
213
            int begin = goAfterLastNewLine(seq);
218
            int begin = goAfterLastNewLine(seq);
214
            seq.moveIndex(matrix[index][2]);
219
            seq.moveIndex(matrix[index][2]);
220
            seq.moveNext();
215
            int end = goAfterFirstNewLine(seq);
221
            int end = goAfterFirstNewLine(seq);
216
            return new int [] { begin, end };
222
            return new int [] { begin, end };
217
        }
223
        }
Lines 285-290 Link Here
285
            // to decide.
291
            // to decide.
286
            if (tokenIndex == -1) return -1;
292
            if (tokenIndex == -1) return -1;
287
            seq.moveIndex(tokenIndex);
293
            seq.moveIndex(tokenIndex);
294
            seq.moveNext();
288
            return goAfterFirstNewLine(seq);
295
            return goAfterFirstNewLine(seq);
289
        }
296
        }
290
        
297
        
Lines 297-302 Link Here
297
        public int[] getPositions(int index) {
304
        public int[] getPositions(int index) {
298
            int begin = getInsertPos(index);
305
            int begin = getInsertPos(index);
299
            seq.moveIndex(matrix[index][4]);
306
            seq.moveIndex(matrix[index][4]);
307
            seq.moveNext();
300
            int end = goAfterFirstNewLine(seq);
308
            int end = goAfterFirstNewLine(seq);
301
            return new int [] { begin, end };
309
            return new int [] { begin, end };
302
        }
310
        }
Lines 360-365 Link Here
360
            // to decide.
368
            // to decide.
361
            if (tokenIndex == -1) return -1;
369
            if (tokenIndex == -1) return -1;
362
            seq.moveIndex(tokenIndex);
370
            seq.moveIndex(tokenIndex);
371
            seq.moveNext();
363
            int off = goAfterFirstNewLine(seq);
372
            int off = goAfterFirstNewLine(seq);
364
            return off;
373
            return off;
365
        }
374
        }
Lines 373-378 Link Here
373
        public int[] getPositions(int index) {
382
        public int[] getPositions(int index) {
374
            int begin = getInsertPos(index);
383
            int begin = getInsertPos(index);
375
            seq.moveIndex(matrix[index][4]);
384
            seq.moveIndex(matrix[index][4]);
385
            seq.moveNext();
376
            int end = goAfterFirstNewLine(seq);
386
            int end = goAfterFirstNewLine(seq);
377
            return new int [] { begin, end };
387
            return new int [] { begin, end };
378
        }
388
        }
Lines 502-507 Link Here
502
                String s = "(nothing)";
512
                String s = "(nothing)";
503
                if (item > -1) {
513
                if (item > -1) {
504
                    seq.moveIndex(item);
514
                    seq.moveIndex(item);
515
                    seq.moveNext();
505
                    s = "'" + seq.token().text();
516
                    s = "'" + seq.token().text();
506
                }
517
                }
507
                s += "'                                           ";
518
                s += "'                                           ";
(-)java/source/src/org/netbeans/modules/java/source/save/TokenUtilities.java (+5 lines)
Lines 65-70 Link Here
65
     */
65
     */
66
    static int moveNext(TokenSequence<JavaTokenId> tokenSequence, final int pos) {
66
    static int moveNext(TokenSequence<JavaTokenId> tokenSequence, final int pos) {
67
        tokenSequence.move(pos);
67
        tokenSequence.move(pos);
68
        tokenSequence.moveNext(); // Assumes the pos is located within input bounds
68
        JavaTokenId type = tokenSequence.token().id();
69
        JavaTokenId type = tokenSequence.token().id();
69
        while (JavaTokenId.WHITESPACE.equals(type) ||
70
        while (JavaTokenId.WHITESPACE.equals(type) ||
70
               JavaTokenId.BLOCK_COMMENT.equals(type) ||
71
               JavaTokenId.BLOCK_COMMENT.equals(type) ||
Lines 82-87 Link Here
82
            JavaTokenId id)
83
            JavaTokenId id)
83
    {
84
    {
84
        tokenSequence.move(pos);
85
        tokenSequence.move(pos);
86
        tokenSequence.moveNext(); // Assumes the pos is located within input bounds
85
        while (!id.equals(tokenSequence.token().id())) {
87
        while (!id.equals(tokenSequence.token().id())) {
86
            if (!tokenSequence.moveNext())
88
            if (!tokenSequence.moveNext())
87
                return -1;
89
                return -1;
Lines 94-99 Link Here
94
            JavaTokenId id)
96
            JavaTokenId id)
95
    {
97
    {
96
        tokenSequence.move(pos);
98
        tokenSequence.move(pos);
99
        tokenSequence.moveNext(); // Assumes the pos is located within input bounds
97
        while (!id.equals(tokenSequence.token().id())) {
100
        while (!id.equals(tokenSequence.token().id())) {
98
            if (!tokenSequence.movePrevious())
101
            if (!tokenSequence.movePrevious())
99
                return -1;
102
                return -1;
Lines 106-111 Link Here
106
            String text)
109
            String text)
107
    {
110
    {
108
        tokenSequence.move(pos);
111
        tokenSequence.move(pos);
112
        tokenSequence.moveNext(); // Assumes the pos is located within input bounds
109
        while (!text.equals(tokenSequence.token().text())) {
113
        while (!text.equals(tokenSequence.token().text())) {
110
            if (!tokenSequence.moveNext())
114
            if (!tokenSequence.moveNext())
111
                return -1;
115
                return -1;
Lines 118-123 Link Here
118
            String text)
122
            String text)
119
    {
123
    {
120
        tokenSequence.move(pos);
124
        tokenSequence.move(pos);
125
        tokenSequence.moveNext(); // Assumes the pos is located within input bounds
121
        while (!text.equals(tokenSequence.token().text())) {
126
        while (!text.equals(tokenSequence.token().text())) {
122
            if (!tokenSequence.movePrevious())
127
            if (!tokenSequence.movePrevious())
123
                return -1;
128
                return -1;
(-)java/source/src/org/netbeans/modules/java/source/save/TreeDiff.java (-3 / +6 lines)
Lines 1247-1253 Link Here
1247
            ResultItem<JCTree> item = result[j];
1247
            ResultItem<JCTree> item = result[j];
1248
            switch (item.operation) {
1248
            switch (item.operation) {
1249
                case MODIFY: {
1249
                case MODIFY: {
1250
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1250
                    tokenSequence.moveIndex(matrix[i][4]);
1251
                    if (tokenSequence.moveNext()) {
1251
                        testPos = tokenSequence.offset();
1252
                        testPos = tokenSequence.offset();
1252
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1253
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1253
                            testPos += JavaTokenId.COMMA.fixedText().length();
1254
                            testPos += JavaTokenId.COMMA.fixedText().length();
Lines 1283-1289 Link Here
1283
                    int endOffset = toOff(s.tail(j) || s.next(j) ? matrix[i+1][2] : matrix[i][4]);
1284
                    int endOffset = toOff(s.tail(j) || s.next(j) ? matrix[i+1][2] : matrix[i][4]);
1284
                    assert startOffset != -1 && endOffset != -1 : "Invalid offset!";
1285
                    assert startOffset != -1 && endOffset != -1 : "Invalid offset!";
1285
                    append(Diff.delete(startOffset, endOffset));
1286
                    append(Diff.delete(startOffset, endOffset));
1286
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1287
                    tokenSequence.moveIndex(matrix[i][4]);
1288
                    if (tokenSequence.moveNext()) {
1287
                        testPos = tokenSequence.offset();
1289
                        testPos = tokenSequence.offset();
1288
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1290
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1289
                            testPos += JavaTokenId.COMMA.fixedText().length();
1291
                            testPos += JavaTokenId.COMMA.fixedText().length();
Lines 1293-1299 Link Here
1293
                    break;
1295
                    break;
1294
                }
1296
                }
1295
                case NOCHANGE: {
1297
                case NOCHANGE: {
1296
                    if (tokenSequence.moveIndex(matrix[i][4])) {
1298
                    tokenSequence.moveIndex(matrix[i][4]);
1299
                    if (tokenSequence.moveNext()) {
1297
                        testPos = tokenSequence.offset();
1300
                        testPos = tokenSequence.offset();
1298
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1301
                        if (JavaTokenId.COMMA == tokenSequence.token().id())
1299
                            testPos += JavaTokenId.COMMA.fixedText().length();
1302
                            testPos += JavaTokenId.COMMA.fixedText().length();
(-)lexer/arch.xml (-13 / +11 lines)
Lines 300-319 Link Here
300
        TokenHierarchy hi = TokenHierarchy.get(document);
300
        TokenHierarchy hi = TokenHierarchy.get(document);
301
        TokenSequence ts = hi.tokenSequence();
301
        TokenSequence ts = hi.tokenSequence();
302
        // If necessary move ts to the requested offset
302
        // If necessary move ts to the requested offset
303
        int diff = ts.move(offset);
303
        ts.move(offset);
304
        if (diff != Integer.MAX_VALUE)) { // Some tokens exist
304
        while (ts.moveNext()) {
305
            do {
305
            Token t = ts.token();
306
                Token t = ts.token();
306
            if (t.id() == ...) { ... }
307
                if (t.id() == ...) { ... }
307
            if (TokenUtilities.equals(t.text(), "mytext")) { ... }
308
                if (TokenUtilities.equals(t.text(), "mytext")) { ... }
308
            if (ts.offset() == ...) { ... }
309
                if (ts.offset() == ...) { ... }
310
309
311
                // Possibly retrieve embedded token sequence
310
            // Possibly retrieve embedded token sequence
312
                TokenSequence embedded = ts.embedded();
311
            TokenSequence embedded = ts.embedded();
313
                if (embedded != null) { // Token has a valid language embedding
312
            if (embedded != null) { // Token has a valid language embedding
314
                    ...
313
                ...
315
                }
314
            }
316
            } while (ts.moveNext());
317
        }
315
        }
318
    } finally {
316
    } finally {
319
        document.readUnlock();
317
        document.readUnlock();
(-)lexer/manifest.mf (-1 / +1 lines)
Lines 1-4 Link Here
1
OpenIDE-Module: org.netbeans.modules.lexer/2
1
OpenIDE-Module: org.netbeans.modules.lexer/2
2
OpenIDE-Module-Localizing-Bundle: org/netbeans/lib/lexer/Bundle.properties
2
OpenIDE-Module-Localizing-Bundle: org/netbeans/lib/lexer/Bundle.properties
3
OpenIDE-Module-Specification-Version: 1.12.0
3
OpenIDE-Module-Specification-Version: 1.13.0
4
OpenIDE-Module-Recommends: org.netbeans.spi.lexer.LanguageProvider
4
OpenIDE-Module-Recommends: org.netbeans.spi.lexer.LanguageProvider
(-)lexer/api/apichanges.xml (+26 lines)
Lines 91-96 Link Here
91
<!-- ACTUAL CHANGES BEGIN HERE: -->
91
<!-- ACTUAL CHANGES BEGIN HERE: -->
92
92
93
  <changes>
93
  <changes>
94
  <change id="api.tokensequence.move">
95
      <api name="api"/>
96
      <summary>Changed TokenSequence.move() and moveIndex() use</summary>
97
      <version major="1" minor="13"/>
98
      <date day="16" month="1" year="2007"/>
99
      <author login="mmetelka"/>
100
      <compatibility source="incompatible" deletion="yes" addition="yes" modification="yes"/>
101
      <description>
102
        <p>
103
            Changed the <code>TokenSequence.move()</code> to position <b>before</b> the particular token
104
            that "contains" the token (or after the last token if the given offset
105
            is too high). Additional <code>moveNext()</code> is necessary
106
            to actually move to the next token.
107
            <br/>
108
            <code>TokenSequence.moveIndex()</code> was modified in a similar way
109
            (see javadocs).
110
            <br/>
111
            <code>TokenSequence.moveFirst()</code> and <code>moveLast()</code>
112
            were replaced by <code>moveStart()</code> that positionins before
113
            the first token and by <code>moveEnd()</code> that positions
114
            after the last token.
115
            <code>
116
        </p>
117
      </description>
118
  </change>
119
94
  <change id="api.lexer.release">
120
  <change id="api.lexer.release">
95
      <api name="api"/>
121
      <api name="api"/>
96
      <summary>Added Lexer.release()</summary>
122
      <summary>Added Lexer.release()</summary>
(-)lexer/editorbridge/src/org/netbeans/modules/lexer/editorbridge/LexerLayer.java (-3 / +4 lines)
Lines 108-115 Link Here
108
        if (active) {
108
        if (active) {
109
            pastSequences = new Stack<TokenSequence>();
109
            pastSequences = new Stack<TokenSequence>();
110
            tokenSequence = hi.tokenSequence();
110
            tokenSequence = hi.tokenSequence();
111
            int relOffset = tokenSequence.move(startOffset);
111
            tokenSequence.move(startOffset);
112
            if (relOffset != Integer.MAX_VALUE) {
112
            if (tokenSequence.moveNext()) {
113
                updateTokenEndOffsetAndColoring(startOffset);
113
                updateTokenEndOffsetAndColoring(startOffset);
114
            } else { // no tokens
114
            } else { // no tokens
115
                active = false;
115
                active = false;
Lines 178-184 Link Here
178
                        break;
178
                        break;
179
                    }
179
                    }
180
                } else {
180
                } else {
181
                    if (embed.move(offset) != Integer.MAX_VALUE) {
181
                    embed.move(offset);
182
                    if (embed.moveNext()) {
182
                        pastSequences.push(tokenSequence);
183
                        pastSequences.push(tokenSequence);
183
                        tokenSequence = embed;
184
                        tokenSequence = embed;
184
                    } else {
185
                    } else {
(-)lexer/nbbridge/test/unit/src/org/netbeans/modules/lexer/nbbridge/test/MimeLookupLanguageProviderTest.java (-5 / +8 lines)
Lines 75-81 Link Here
75
        assertEquals("Wrong language", "text/x-simple-plain", lang.mimeType());
75
        assertEquals("Wrong language", "text/x-simple-plain", lang.mimeType());
76
        
76
        
77
        for(int i = 0; i < seq.tokenCount(); i++) {
77
        for(int i = 0; i < seq.tokenCount(); i++) {
78
            seq.move(i);
78
            seq.moveIndex(i);
79
            assertTrue(seq.moveNext());
79
            Token token = seq.token();
80
            Token token = seq.token();
80
            
81
            
81
            if (token.id() == SimplePlainTokenId.WORD) {
82
            if (token.id() == SimplePlainTokenId.WORD) {
Lines 86-96 Link Here
86
                assertNotNull("Can't find language of the embedded sequence", embeddedLang);
87
                assertNotNull("Can't find language of the embedded sequence", embeddedLang);
87
                assertEquals("Wrong language of the embedded sequence", "text/x-simple-char", embeddedLang.mimeType());
88
                assertEquals("Wrong language of the embedded sequence", "text/x-simple-char", embeddedLang.mimeType());
88
                
89
                
89
                assertTrue("Embedded sequence has no tokens (moveFirst)", embeddedSeq.moveFirst());
90
                embeddedSeq.moveStart();
90
                assertEquals("Wrong startSkipLenght", 1, embeddedSeq.offset() - seq.offset());
91
                assertTrue("Embedded sequence has no tokens (moveFirst)", embeddedSeq.moveNext());
92
                assertEquals("Wrong startSkipLength", 1, embeddedSeq.offset() - seq.offset());
91
                
93
                
92
                assertTrue("Embedded sequence has no tokens (moveLast)", embeddedSeq.moveLast());
94
                embeddedSeq.moveEnd();
93
                assertEquals("Wrong endSkipLenght", 2, 
95
                assertTrue("Embedded sequence has no tokens (moveLast)", embeddedSeq.movePrevious());
96
                assertEquals("Wrong endSkipLength", 2, 
94
                    (seq.offset() + seq.token().length()) - (embeddedSeq.offset() + embeddedSeq.token().length()));
97
                    (seq.offset() + seq.token().length()) - (embeddedSeq.offset() + embeddedSeq.token().length()));
95
            }
98
            }
96
        }
99
        }
(-)lexer/src/org/netbeans/api/lexer/TokenSequence.java (-143 / +151 lines)
Lines 38-44 Link Here
38
 * A typical use is a forward iteration through the tokens:
38
 * A typical use is a forward iteration through the tokens:
39
 * <pre>
39
 * <pre>
40
 *   TokenSequence ts = tokenHierarchy.tokenSequence();
40
 *   TokenSequence ts = tokenHierarchy.tokenSequence();
41
 *   // Possible positioning by ts.move()
41
 *   // Possible positioning by ts.move(offset);
42
 *   while (ts.moveNext()) {
42
 *   while (ts.moveNext()) {
43
 *       Token t = ts.token();
43
 *       Token t = ts.token();
44
 *       if (t.id() == ...) { ... }
44
 *       if (t.id() == ...) { ... }
Lines 65-71 Link Here
65
    
65
    
66
    private AbstractToken<T> token; // 16 bytes
66
    private AbstractToken<T> token; // 16 bytes
67
    
67
    
68
    private int tokenIndex = -1; // 20 bytes
68
    private int tokenIndex; // 20 bytes
69
    
69
    
70
    /**
70
    /**
71
     * Offset in the input at which the current token is located
71
     * Offset in the input at which the current token is located
Lines 115-123 Link Here
115
    /**
115
    /**
116
     * Get instance of current token to which this token sequence points to.
116
     * Get instance of current token to which this token sequence points to.
117
     * <br/>
117
     * <br/>
118
     * It is necessary to call {@link #moveNext()} before first calling this method.
118
     * A typical iteration usage:
119
     * <pre>
120
     *   TokenSequence ts = tokenHierarchy.tokenSequence();
121
     *   // Possible positioning by ts.move(offset);
122
     *   while (ts.moveNext()) {
123
     *       Token t = ts.token();
124
     *       if (t.id() == ...) { ... }
125
     *       if (TokenUtilities.equals(t.text(), "mytext")) { ... }
126
     *       if (ts.offset() == ...) { ... }
127
     *   }
128
     * </pre>
119
     *
129
     *
120
     * <p>
121
     * The returned token instance may be flyweight
130
     * The returned token instance may be flyweight
122
     * (returns true from {@link Token#isFlyweight()})
131
     * (returns true from {@link Token#isFlyweight()})
123
     * which means that its {@link Token#offset(TokenHierarchy)} will return -1.
132
     * which means that its {@link Token#offset(TokenHierarchy)} will return -1.
Lines 133-145 Link Here
133
     * The token instance should not be held across the input source modifications.
142
     * The token instance should not be held across the input source modifications.
134
     * </p>
143
     * </p>
135
     *
144
     *
136
     * @return non-null token instance.
145
     * @return token instance to which this token sequence is currently positioned
146
     *  or null if this token sequence is not positioned to any token which may
147
     *  happen after TS creation or after use of {@link #move(int)} or {@link moveIndex(int)}.
148
     * 
137
     * @see #offsetToken()
149
     * @see #offsetToken()
138
     * @throws IllegalStateException if this token sequence was not positioned
139
     *  to any token yet.
140
     */
150
     */
141
    public Token<T> token() {
151
    public Token<T> token() {
142
        checkToken();
143
        return token;
152
        return token;
144
    }
153
    }
145
    
154
    
Lines 160-166 Link Here
160
     *  to any token yet.
169
     *  to any token yet.
161
     */
170
     */
162
    public Token<T> offsetToken() {
171
    public Token<T> offsetToken() {
163
        checkToken();
172
        checkTokenNotNull();
164
        if (token.isFlyweight()) {
173
        if (token.isFlyweight()) {
165
            token = tokenList.replaceFlyToken(tokenIndex, token, offset());
174
            token = tokenList.replaceFlyToken(tokenIndex, token, offset());
166
        }
175
        }
Lines 183-189 Link Here
183
     *  to any token yet.
192
     *  to any token yet.
184
     */
193
     */
185
    public int offset() {
194
    public int offset() {
186
        checkToken();
195
        checkTokenNotNull();
187
        if (tokenOffset == -1) {
196
        if (tokenOffset == -1) {
188
            tokenOffset = tokenList.tokenOffset(tokenIndex);
197
            tokenOffset = tokenList.tokenOffset(tokenIndex);
189
        }
198
        }
Lines 191-200 Link Here
191
    }
200
    }
192
    
201
    
193
    /**
202
    /**
194
     * Get the index of the current token in the complete list of tokens.
203
     * Get an index of token to which (or before which) this TS is currently positioned.
204
     * <br/>
205
     * Zero is returned after TS creation.
195
     *
206
     *
196
     * @return &gt;=0 index of the current token or <code>-1</code>
207
     * @return &gt;=0 index of the current token.
197
     *  if this token sequence is initially located in front of the first token.
198
     */
208
     */
199
    public int index() {
209
    public int index() {
200
        return tokenIndex;
210
        return tokenIndex;
Lines 216-222 Link Here
216
     *  to any token yet.
226
     *  to any token yet.
217
     */
227
     */
218
    public TokenSequence<? extends TokenId> embedded() {
228
    public TokenSequence<? extends TokenId> embedded() {
219
        checkToken();
229
        checkTokenNotNull();
220
        return embeddedImpl(null);
230
        return embeddedImpl(null);
221
    }
231
    }
222
    
232
    
Lines 249-255 Link Here
249
     * has a language embedding.
259
     * has a language embedding.
250
     */
260
     */
251
    public <ET extends TokenId> TokenSequence<ET> embedded(Language<ET> embeddedLanguage) {
261
    public <ET extends TokenId> TokenSequence<ET> embedded(Language<ET> embeddedLanguage) {
252
        checkToken();
262
        checkTokenNotNull();
253
        return embeddedImpl(embeddedLanguage);
263
        return embeddedImpl(embeddedLanguage);
254
    }
264
    }
255
265
Lines 294-300 Link Here
294
     */
304
     */
295
    public boolean createEmbedding(Language<? extends TokenId> embeddedLanguage,
305
    public boolean createEmbedding(Language<? extends TokenId> embeddedLanguage,
296
    int startSkipLength, int endSkipLength, boolean joinSections) {
306
    int startSkipLength, int endSkipLength, boolean joinSections) {
297
        checkToken();
307
        checkTokenNotNull();
298
        return EmbeddingContainer.createEmbedding(tokenList, tokenIndex,
308
        return EmbeddingContainer.createEmbedding(tokenList, tokenIndex,
299
                embeddedLanguage, startSkipLength, endSkipLength, joinSections);
309
                embeddedLanguage, startSkipLength, endSkipLength, joinSections);
300
    }
310
    }
Lines 302-349 Link Here
302
    /**
312
    /**
303
     * Move to the next token in this token sequence.
313
     * Move to the next token in this token sequence.
304
     * <br/>
314
     * <br/>
315
     * This method can be used in case when TS is positioned before a token
316
     * (after its creation or after use of {@link #move(int)} or {@link #moveIndex(int)})
317
     * or in case the TS already points to a concrete token <code>{@link #token()} != null</code>
318
     * - in such case it moves to next token and {@link #index()} gets increased by one.
319
     * <br/>
305
     * The next token may not necessarily start at the offset where
320
     * The next token may not necessarily start at the offset where
306
     * the current token ends (there may be gaps between tokens
321
     * the previous token ends (there may be gaps between tokens
307
     * caused by use of a token id filter).
322
     * caused by token filtering).
308
     *
323
     *
309
     * @return true if the sequence was successfully moved to the next token
324
     * @return true if the sequence was successfully moved to the next token
310
     *  or false if stays on the original token because there are no more tokens
325
     *  or false if it was not moved before there are no more tokens
311
     *  in the forward direction.
326
     *  in the forward direction.
312
     * @throws ConcurrentModificationException if this token sequence
327
     * @throws ConcurrentModificationException if this token sequence
313
     *  is no longer valid because of an underlying mutable input source modification.
328
     *  is no longer valid because of an underlying mutable input source modification.
314
     */
329
     */
315
    public boolean moveNext() {
330
    public boolean moveNext() {
316
        checkModCount();
331
        checkModCount();
317
        tokenIndex++;
332
        if (token != null) // Token already fetched
333
            tokenIndex++;
318
        Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(tokenIndex);
334
        Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(tokenIndex);
319
        if (tokenOrEmbeddingContainer != null) {
335
        if (tokenOrEmbeddingContainer != null) {
320
            AbstractToken origToken = token;
336
            AbstractToken origToken = token;
321
            assignToken(tokenOrEmbeddingContainer);
337
            token = LexerUtilsConstants.token(tokenOrEmbeddingContainer);
338
            // If origToken == null then the right offset might already be pre-computed from move()
322
            if (tokenOffset != -1) {
339
            if (tokenOffset != -1) {
323
                // If the token list is continuous or the fetched token
340
                if (origToken != null) {
324
                // is flyweight (there cannot be a gap before flyweight token)
341
                    // If the token list is continuous or the fetched token
325
                // the original offset can be just increased
342
                    // is flyweight (there cannot be a gap before flyweight token)
326
                // by the original token's length.
343
                    // the original offset can be just increased
327
                if (tokenList.isContinuous() || token.isFlyweight()) {
344
                    // by the original token's length.
328
                    tokenOffset += origToken.length(); // advance by previous token's length
345
                    if (tokenList.isContinuous() || token.isFlyweight()) {
329
                } else // Offset must be recomputed
346
                        tokenOffset += origToken.length(); // advance by previous token's length
330
                    tokenOffset = -1; // mark the offset to be recomputed
347
                    } else // Offset must be recomputed
348
                        tokenOffset = -1; // mark the offset to be recomputed
349
                } else // Not valid token previously
350
                    tokenOffset = -1;
331
            }
351
            }
332
            return true;
352
            return true;
333
        }
353
        }
334
        tokenIndex--;
354
        if (token != null) // Unsuccessful move from existing token
355
            tokenIndex--;
335
        return false;
356
        return false;
336
    }
357
    }
337
358
338
    /**
359
    /**
339
     * Move to the previous token in this token sequence.
360
     * Move to a previous token in this token sequence.
361
     * <br/>
362
     * This method can be used in case when TS is positioned after a token
363
     * (after its creation or after use of {@link #move(int)} or {@link #moveIndex(int)})
364
     * or in case the TS already points to a concrete token <code>{@link #token()} != null</code>.
365
     * <br/>
366
     * In both cases {@link #index()} gets decreased by one.
340
     * <br/>
367
     * <br/>
341
     * The next token may not necessarily end at the offset where
342
     * the present token starts (there may be gaps between tokens
343
     * caused by use of a token id filter).
344
     *
368
     *
345
     * @return true if the sequence was successfully moved to the previous token
369
     * @return true if the sequence was successfully moved to the previous token
346
     *  or false if stayed on the original token because there are no more tokens
370
     *  or false if it was not moved because there are no more tokens
347
     *  in the backward direction.
371
     *  in the backward direction.
348
     * @throws ConcurrentModificationException if this token sequence
372
     * @throws ConcurrentModificationException if this token sequence
349
     *  is no longer valid because of an underlying mutable input source modification.
373
     *  is no longer valid because of an underlying mutable input source modification.
Lines 353-359 Link Here
353
        if (tokenIndex > 0) {
377
        if (tokenIndex > 0) {
354
            AbstractToken origToken = token;
378
            AbstractToken origToken = token;
355
            tokenIndex--;
379
            tokenIndex--;
356
            assignToken();
380
            token = LexerUtilsConstants.token(tokenList.tokenOrEmbeddingContainer(tokenIndex));
357
            if (tokenOffset != -1) {
381
            if (tokenOffset != -1) {
358
                // If the token list is continuous or the original token
382
                // If the token list is continuous or the original token
359
                // is flyweight (there cannot be a gap before flyweight token)
383
                // is flyweight (there cannot be a gap before flyweight token)
Lines 364-371 Link Here
364
                } else { // mark the offset to be computed upon call to offset()
388
                } else { // mark the offset to be computed upon call to offset()
365
                    tokenOffset = -1;
389
                    tokenOffset = -1;
366
                }
390
                }
367
            } else {
368
                tokenOffset = -1; // mark the offset to be computed upon call to offset()
369
            }
391
            }
370
            return true;
392
            return true;
371
393
Lines 374-465 Link Here
374
    }
396
    }
375
397
376
    /**
398
    /**
377
     * Move the token sequence to point to the token with the given index.
399
     * Move TS to be positioned before a token with the given index.
400
     * <br/>
401
     * Example: Fetching tokens starting at the given index:
402
     * <pre>
403
     * TokenSequence ts = tokenHierarchy.tokenSequence();
404
     * ts.moveIndex(index);
405
     * while (ts.moveNext()) {
406
     *     Token t = ts.token();
407
     *     ...
408
     * }
409
     * </pre>
378
     *
410
     *
379
     * @param index index of the token to which this sequence
411
     * @param index index of the token to which this sequence
380
     *   should be positioned.
412
     *   should be positioned.
381
     * @return <code>true</code> if the sequence was moved to the token
413
     *   <br/>
382
     *   with the given index. Returns <code>false</code>
414
     *   If <code>index >= {@link #tokenCount()}</code>
383
     *   if <code>index < 0</code> or <code>index < tokenCount</code>.
415
     *   then the TS will be positioned after the last token.
384
     *   In such case the current token sequence's position stays unchanged.
416
     *   <br/>
417
     *   If <code>index < 0</code>
418
     *   then the TS will be positioned before first token (at index 0).
419
     * @return difference between requested index and the index to which TS
420
     *   is really set.
385
     * @throws ConcurrentModificationException if this token sequence
421
     * @throws ConcurrentModificationException if this token sequence
386
     *  is no longer valid because of an underlying mutable input source modification.
422
     *  is no longer valid because of an underlying mutable input source modification.
387
     */
423
     */
388
    public boolean moveIndex(int index) {
424
    public int moveIndex(int index) {
389
        checkModCount();
425
        checkModCount();
390
        if (index < 0) {
426
        if (index >= 0) {
391
            return false;
427
            Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index);
392
        }
428
            if (tokenOrEmbeddingContainer != null) { // enough tokens
393
        Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(index);
429
                resetTokenIndex(index);
394
        if (tokenOrEmbeddingContainer != null) { // enough tokens
430
            } else // Token at the requested index does not exist - leave orig. index
395
            this.tokenIndex = index;
431
                resetTokenIndex(tokenCount());
396
            assignToken(tokenOrEmbeddingContainer);
432
        } else // index < 0
397
            tokenOffset = -1;
433
            resetTokenIndex(0);
398
            return true;
434
        return index - tokenIndex;
399
435
    }
400
        } else // Token at the requested index does not exist - leave orig. index
436
    
401
            return false;
437
    /**
438
     * Move the token sequence to be positioned before the first token.
439
     * <br/>
440
     * This is equivalent to <code>moveIndex(0)</code>.
441
     */
442
    public void moveStart() {
443
        moveIndex(0);
402
    }
444
    }
403
    
445
    
404
    /**
446
    /**
405
     * Move the token sequence to be positioned to the token
447
     * Move the token sequence to be positioned after the last token.
448
     * <br/>
449
     * This is equivalent to <code>moveIndex(tokenCount())</code>.
450
     */
451
    public void moveEnd() {
452
        moveIndex(tokenCount());
453
    }
454
    
455
    /**
456
     * Move the token sequence to be positioned before the token
406
     * that "contains" the requested offset (the offset is at the begining
457
     * that "contains" the requested offset (the offset is at the begining
407
     * or inside of the token).
458
     * or inside of the token).
408
     * <br>
459
     * <br/>
409
     * If the offset is too big the token sequence will be positioned
460
     * Typical usage pattern:
410
     * to the last token and the return value will
461
     * <pre>
411
     * be the distance between the requested offset
462
     * TokenSequence ts = ...
412
     * and the start offset of the token to which the token sequence
463
     * ts.move(offset);
413
     * will be positioned..
464
     * while (ts.moveNext()) {
414
     * <br>
465
     *     Token t = ts.token();
415
     * If there are no tokens in the sequence then {@link Integer#MAX_VALUE}
466
     *     ...
416
     * will be returned.
467
     * }
417
     *
468
     * </pre>
469
     * 
470
     * If the offset is too big then the token sequence will be positioned
471
     * behind the last token.
418
     * <p>
472
     * <p>
419
     * The underlying token list may contain gaps that are not covered
473
     * If token filtering is used there may be gaps that are not covered
420
     * by any tokens and if the offset is contained in such gap then
474
     * by any tokens and if the offset is contained in such gap then
421
     * the token sequence will be positioned to the token that precedes the gap.
475
     * the token sequence will be positioned before the token that follows the gap.
422
     * </p>
476
     * </p>
423
     *
477
     *
424
     * Example:
425
     * <pre>
426
     *   int diff = tokenSequence.move(targetOffset);
427
     *   // diff equals to (targetOffset - tokenSequence.token().offset())
428
     *   if (diff >= 0 && diff < tokenSequence.token().length()) {
429
     *       // Within token bounds - tokenSequence.token() starts at or "contains" targetOffset
430
     *
431
     *   } else if (diff == Integer.MAX_VALUE) {
432
     *       // No tokens in the token sequence at all.
433
     *       // Token sequence is not positioned to any token.
434
     *
435
     *   } else {
436
     *       // 1. diff >= tokenSequence.token().length()
437
     *       //   a) targetOffset is above the end of the last token in the sequence.
438
     *       //     Token sequence is positioned to the last token in the sequence.
439
     *       //   b) there are text areas not covered by any tokens
440
     *       //     due to skipped tokens (skipTokenIds was used
441
     *       //     in TokenHierarchy.create()) and the targetOffset points to such gap.
442
     *       //     Token sequence is positioned to the preceding token.
443
     *       // 
444
     *       // 2. diff < 0
445
     *       //   a) targetOffset < 0
446
     *       //   b) targetOffset >= 0 but there is a text area
447
     *       //     at the begining that is not covered by any tokens
448
     *       //     (skipTokenIds was used in TokenHierarchy.create())
449
     *       //     Token sequence is positioned to the first token in the sequence.
450
     *   }
451
     * </pre>
452
     * 
453
     *
478
     *
454
     * @param offset absolute offset in the input to which
479
     * @param offset absolute offset in the input to which
455
     *  the token sequence should be moved.
480
     *  the token sequence should be moved.
456
     *
481
     *
457
     * @return difference between the reqeuested offset
482
     * @return difference between the reqeuested offset
458
     *  and the absolute starting offset of the token
483
     *  and the start offset of the token
459
     *  to which the the token sequence gets moved.
484
     *  before which the the token sequence gets positioned.
460
     *  <br>
485
     *  <br/>
461
     *  Returns {@link Integer#MAX_VALUE} if there are no tokens in the sequence.
486
     *  If the TS is positioned after the last token the difference is computed
462
     *  In such case there is no active token.
487
     *  against the end offset of the last token.
463
     * 
488
     * 
464
     * @throws ConcurrentModificationException if this token sequence
489
     * @throws ConcurrentModificationException if this token sequence
465
     *  is no longer valid because of an underlying mutable input source modification.
490
     *  is no longer valid because of an underlying mutable input source modification.
Lines 474-480 Link Here
474
            if (tokenList.tokenOrEmbeddingContainer(0) == null) { // really no tokens at all
499
            if (tokenList.tokenOrEmbeddingContainer(0) == null) { // really no tokens at all
475
                // In this case the token sequence could not be positioned yet
500
                // In this case the token sequence could not be positioned yet
476
                // so no need to reset "index" or other vars
501
                // so no need to reset "index" or other vars
477
                return Integer.MAX_VALUE;
502
                resetTokenIndex(0);
503
                return offset;
478
            }
504
            }
479
            // Re-get the present token count (could be created a chunk of tokens at once)
505
            // Re-get the present token count (could be created a chunk of tokens at once)
480
            tokenCount = tokenList.tokenCountCurrent();
506
            tokenCount = tokenList.tokenCountCurrent();
Lines 499-512 Link Here
499
                    tokenLength = t.length();
525
                    tokenLength = t.length();
500
                    tokenCount++;
526
                    tokenCount++;
501
527
502
                } else { // no more tokens => break
528
                } else { // no more tokens => position after last token
503
                    break;
529
                    resetTokenIndex(tokenCount);
530
                    tokenOffset = prevTokenOffset + tokenLength; // May assign the token's offset in advance
531
                    return offset - tokenOffset;
504
                }
532
                }
505
            }
533
            }
506
            tokenIndex = tokenCount - 1;
534
            resetTokenIndex(tokenCount - 1);
507
            // Absolute token's start offset 
535
            tokenOffset = prevTokenOffset; // May assign the token's offset in advance
508
            tokenOffset = prevTokenOffset;
509
            assignToken();
510
            return offset - prevTokenOffset;
536
            return offset - prevTokenOffset;
511
        }
537
        }
512
        
538
        
Lines 525-574 Link Here
525
                high = mid - 1;
551
                high = mid - 1;
526
            } else {
552
            } else {
527
                // Token starting exactly at offset found
553
                // Token starting exactly at offset found
528
                tokenIndex = mid;
554
                resetTokenIndex(mid);
529
                tokenOffset = midStartOffset;
555
                tokenOffset = midStartOffset;
530
                assignToken();
531
                return 0; // right at the token begining
556
                return 0; // right at the token begining
532
            }
557
            }
533
        }
558
        }
534
        
559
        
535
        // Not found exactly and high + 1 == low => high < low
560
        // Not found exactly and high + 1 == low => high < low
536
        // Check whether the token at "high" contains the offset
561
        // BTW there may be gaps between tokens; if offset is in gap then position to higher token
537
        if (high >= 0) { // could be -1
562
        if (high >= 0) { // could be -1
538
            AbstractToken t = LexerUtilsConstants.token(tokenList, high);
563
            AbstractToken t = LexerUtilsConstants.token(tokenList, high);
539
            prevTokenOffset = tokenList.tokenOffset(high);
564
            prevTokenOffset = tokenList.tokenOffset(high);
565
            // If gaps allowed check whether the token at "high" contains the offset
566
            if (!tokenList.isContinuous() && offset > prevTokenOffset + t.length()) {
567
                // Offset in the gap above the "high" token
568
                high++;
569
                prevTokenOffset += t.length();
570
            }
540
        } else { // at least one token exists => use token at index 0
571
        } else { // at least one token exists => use token at index 0
541
            high = 0;
572
            high = 0;
542
            prevTokenOffset = tokenList.tokenOffset(0); // result may differ from 0
573
            prevTokenOffset = tokenList.tokenOffset(0); // result may differ from 0
543
        }
574
        }
544
575
        resetTokenIndex(high);
545
        tokenIndex = high;
546
        tokenOffset = prevTokenOffset;
576
        tokenOffset = prevTokenOffset;
547
        assignToken();
548
        return offset - prevTokenOffset;
577
        return offset - prevTokenOffset;
549
    }
578
    }
550
579
551
    /**
580
    /**
552
     * Move to the first token in this token sequence.
553
     *
554
     * @return true if the sequence was positioned on the first token
555
     *  or false if there are no tokens in the sequence.
556
     */
557
    public boolean moveFirst() {
558
        return moveIndex(0);
559
    }
560
    
561
    /**
562
     * Move to the last token in this token sequence.
563
     *
564
     * @return true if the sequence was positioned on the last token
565
     *  or false if there are no tokens in the sequence.
566
     */
567
    public boolean moveLast() {
568
        return moveIndex(tokenCount() - 1); // Can be -1 but handled in move(index)
569
    }
570
571
    /**
572
     * Return total count of tokens in this sequence.
581
     * Return total count of tokens in this sequence.
573
     * <br>
582
     * <br>
574
     * <b>Note:</b> Calling this method will lead
583
     * <b>Note:</b> Calling this method will lead
Lines 628-642 Link Here
628
        return parentTokenIndexes;
637
        return parentTokenIndexes;
629
    }
638
    }
630
639
631
    private void assignToken(Object tokenOrEmbeddingContainer) {
640
    private void resetTokenIndex(int index) {
632
        token = LexerUtilsConstants.token(tokenOrEmbeddingContainer);
641
        // Position to the given index e.g. by move() and moveIndex()
633
    }
642
        tokenIndex = index;
634
    
643
        token = null;
635
    private void assignToken() {
644
        tokenOffset = -1;
636
        assignToken(tokenList.tokenOrEmbeddingContainer(tokenIndex));
637
    }
645
    }
638
646
639
    private void checkToken() {
647
    private void checkTokenNotNull() {
640
        if (token == null) {
648
        if (token == null) {
641
            throw new IllegalStateException(
649
            throw new IllegalStateException(
642
                "No token fetched by moveNext() from token sequence yet: index=" + tokenIndex
650
                "No token fetched by moveNext() from token sequence yet: index=" + tokenIndex
(-)lexer/src/org/netbeans/lib/lexer/LexerUtilsConstants.java (+10 lines)
Lines 237-242 Link Here
237
            sb.append(": ");
237
            sb.append(": ");
238
            AbstractToken token = token(tokenOrEmbeddingContainer);
238
            AbstractToken token = token(tokenOrEmbeddingContainer);
239
            sb.append(token.dumpInfo(tokenHierarchy));
239
            sb.append(token.dumpInfo(tokenHierarchy));
240
            int la = tokenList.lookahead(i);
241
            if (la != 0) {
242
                sb.append(", la=");
243
                sb.append(la);
244
            }
245
            Object state= tokenList.state(i);
246
            if (state != null) {
247
                sb.append(", s=");
248
                sb.append(state);
249
            }
240
            sb.append('\n');
250
            sb.append('\n');
241
        }
251
        }
242
        return sb;
252
        return sb;
(-)lexer/src/org/netbeans/lib/lexer/SubSequenceTokenList.java (-1 / +1 lines)
Lines 92-98 Link Here
92
        if (limitStartOffset > 0) {
92
        if (limitStartOffset > 0) {
93
            int diff = move(limitStartOffset);
93
            int diff = move(limitStartOffset);
94
            if (diff != Integer.MAX_VALUE) { // some tokens exist
94
            if (diff != Integer.MAX_VALUE) { // some tokens exist
95
                if (diff >= lastToken.length()) {
95
                if (diff >= lastToken.length()) { // lastToken initialized in move()
96
                    lastTokenIndex++;
96
                    lastTokenIndex++;
97
                    Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(lastTokenIndex);
97
                    Object tokenOrEmbeddingContainer = tokenList.tokenOrEmbeddingContainer(lastTokenIndex);
98
                    if (tokenOrEmbeddingContainer != null &&
98
                    if (tokenOrEmbeddingContainer != null &&
(-)lexer/test/unit/src/org/netbeans/api/lexer/TokenSequenceTest.java (-41 / +65 lines)
Lines 48-60 Link Here
48
        TokenHierarchy<?> hi = TokenHierarchy.create(text, SimpleTokenId.language());
48
        TokenHierarchy<?> hi = TokenHierarchy.create(text, SimpleTokenId.language());
49
        TokenSequence<? extends TokenId> ts = hi.tokenSequence();
49
        TokenSequence<? extends TokenId> ts = hi.tokenSequence();
50
        
50
        
51
        // Fail if no "move*" method called yet
51
        assertNull(ts.token());
52
        try {
53
            ts.token(); // should throw exception
54
            fail("IllegalStateException expecxted");
55
        } catch (IllegalStateException e) {
56
            // expected
57
        }
58
52
59
        assertTrue(ts.moveNext());
53
        assertTrue(ts.moveNext());
60
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
54
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
Lines 69-88 Link Here
69
        assertEquals(ts.tokenCount(), 3);
63
        assertEquals(ts.tokenCount(), 3);
70
        
64
        
71
        assertEquals(0, ts.move(0));
65
        assertEquals(0, ts.move(0));
66
        assertNull(ts.token());
67
        assertTrue(ts.moveNext());
72
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
68
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
73
        assertEquals(2, ts.move(2));
69
        assertEquals(2, ts.move(2));
70
        assertNull(ts.token());
71
        assertTrue(ts.moveNext());
74
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
72
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
75
        assertEquals(-1, ts.move(-1));
73
        assertEquals(-1, ts.move(-1));
74
        assertNull(ts.token());
75
        assertTrue(ts.moveNext());
76
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
76
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
77
        assertEquals(0, ts.move(3));
77
        assertEquals(0, ts.move(3));
78
        assertNull(ts.token());
79
        assertTrue(ts.moveNext());
78
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.PLUS, "+", 3);
80
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.PLUS, "+", 3);
79
        assertEquals(0, ts.move(4));
81
        assertEquals(0, ts.move(4));
82
        assertNull(ts.token());
83
        assertTrue(ts.moveNext());
80
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
84
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
81
        assertEquals(1, ts.move(5));
85
        assertEquals(1, ts.move(5));
86
        assertNull(ts.token());
87
        assertTrue(ts.moveNext());
82
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
88
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
83
        assertEquals(5, ts.move(9));
89
        assertEquals(1, ts.move(9));
90
        assertNull(ts.token());
91
        assertFalse(ts.moveNext());
92
        assertTrue(ts.movePrevious());
84
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
93
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
85
        assertEquals(96, ts.move(100));
94
        assertEquals(92, ts.move(100));
95
        assertNull(ts.token());
96
        assertFalse(ts.moveNext());
97
        assertTrue(ts.movePrevious());
86
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
98
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 4);
87
99
88
        
100
        
Lines 122-133 Link Here
122
        TokenSequence<? extends TokenId> ts = hi.tokenSequence();
134
        TokenSequence<? extends TokenId> ts = hi.tokenSequence();
123
        
135
        
124
        // Fail if no "move*" method called yet
136
        // Fail if no "move*" method called yet
125
        try {
137
        assertNull(ts.token());
126
            ts.token(); // should throw exception
127
            fail("IllegalStateException expecxted");
128
        } catch (IllegalStateException e) {
129
            // expected
130
        }
131
138
132
        assertTrue(ts.moveNext());
139
        assertTrue(ts.moveNext());
133
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
140
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
Lines 137-146 Link Here
137
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
144
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
138
        assertFalse(ts.moveNext());
145
        assertFalse(ts.moveNext());
139
        assertEquals(3, ts.tokenCount());
146
        assertEquals(3, ts.tokenCount());
140
        assertTrue(ts.moveFirst());
147
        assertEquals(0, ts.moveIndex(0));
148
        assertTrue(ts.moveNext());
141
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
149
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
142
        assertTrue(ts.moveNext());
150
        assertTrue(ts.moveNext());
143
        assertTrue(ts.moveLast());
151
        assertEquals(0, ts.moveIndex(ts.tokenCount()));
152
        assertTrue(ts.movePrevious());
144
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
153
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
145
        assertFalse(ts.moveNext());
154
        assertFalse(ts.moveNext());
146
155
Lines 151-166 Link Here
151
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
160
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
152
        
161
        
153
        assertEquals(-1, ts.move(0)); // below filtered-out token
162
        assertEquals(-1, ts.move(0)); // below filtered-out token
163
        assertNull(ts.token());
164
        assertTrue(ts.moveNext());
154
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
165
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
155
        assertEquals(0, ts.move(1));
166
        assertEquals(0, ts.move(1));
167
        assertNull(ts.token());
168
        assertTrue(ts.moveNext());
156
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
169
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
157
        assertEquals(1, ts.move(2));
170
        assertEquals(1, ts.move(2));
171
        assertNull(ts.token());
172
        assertTrue(ts.moveNext());
158
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
173
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
159
        assertEquals(3, ts.move(4));
174
        assertEquals(3, ts.move(4));
175
        assertNull(ts.token());
176
        assertTrue(ts.moveNext());
160
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
177
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 1);
161
        assertEquals(0, ts.move(5));
178
        assertEquals(0, ts.move(5));
179
        assertNull(ts.token());
180
        assertTrue(ts.moveNext());
162
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 5);
181
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "defg", 5);
163
        assertEquals(1, ts.move(12));
182
        assertEquals(1, ts.move(12));
183
        assertNull(ts.token());
184
        assertTrue(ts.moveNext());
164
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
185
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
165
        
186
        
166
        
187
        
Lines 172-219 Link Here
172
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
193
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
173
        assertFalse(sub.moveNext());
194
        assertFalse(sub.moveNext());
174
        
195
        
175
        // Test moveFirst() and moveLast() on subsequence
196
        // Test moves to first and last tokens on subsequence
176
        sub = ts.subSequence(1, 6);
197
        sub = ts.subSequence(1, 6);
177
        assertTrue(sub.moveLast());
198
        assertEquals(0, sub.moveIndex(sub.tokenCount()));
199
        assertEquals(2, sub.tokenCount()); // "abc" and "defg" (others filtered out
200
        assertTrue(sub.movePrevious());
178
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
201
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
179
        assertTrue(sub.moveFirst());
202
        assertEquals(0, sub.moveIndex(0));
203
        assertTrue(sub.moveNext());
180
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "abc", 1);
204
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "abc", 1);
181
        
205
        
182
        sub = ts.subSequence(4);
206
        sub = ts.subSequence(4);
183
        assertTrue(sub.moveNext());
207
        assertTrue(sub.moveNext());
184
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
208
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "defg", 5);
185
        assertTrue(sub.moveNext());
209
        assertTrue(sub.moveNext());
186
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
210
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "hi", 11);
187
        assertFalse(sub.moveNext());
211
        assertFalse(sub.moveNext());
188
212
189
        sub = ts.subSequence(12, 15);
213
        sub = ts.subSequence(12, 15);
190
        assertTrue(sub.moveNext());
214
        assertTrue(sub.moveNext());
191
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
215
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "hi", 11);
192
216
193
        sub = ts.subSequence(12, 15);
217
        sub = ts.subSequence(12, 15);
194
        assertEquals(-2, sub.move(9));
218
        assertEquals(-2, sub.move(9));
195
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "hi", 11);
219
        assertNull(sub.token());
220
        assertTrue(sub.moveNext());
221
        LexerTestUtilities.assertTokenEquals(sub, SimpleTokenId.IDENTIFIER, "hi", 11);
196
222
197
        sub = ts.subSequence(13, 15);
223
        sub = ts.subSequence(13, 15);
198
        assertFalse(sub.moveNext());
224
        assertFalse(sub.moveNext());
199
        assertFalse(sub.moveFirst());
225
        assertEquals(0, sub.moveIndex(0));
200
        assertFalse(sub.moveLast());
226
        assertNull(sub.token());
227
        assertFalse(sub.moveNext());
228
        assertEquals(0, sub.moveIndex(sub.tokenCount()));
229
        assertNull(sub.token());
201
        assertEquals(0, sub.tokenCount());
230
        assertEquals(0, sub.tokenCount());
202
231
203
        sub = ts.subSequence(-3, 1);
232
        sub = ts.subSequence(-3, 1);
204
        assertFalse(sub.moveNext());
233
        assertFalse(sub.moveNext());
205
234
206
        sub = ts.subSequence(13, 15);
235
        sub = ts.subSequence(13, 15);
207
        assertEquals(Integer.MAX_VALUE, sub.move(5));
236
        assertEquals(5, sub.move(5));
208
237
209
        sub = ts.subSequence(-3, 1);
238
        sub = ts.subSequence(-3, 1);
210
        assertEquals(Integer.MAX_VALUE, sub.move(1));
239
        assertEquals(1, sub.move(1));
211
240
212
        // Reversed bounds => should be empty token sequence
241
        // Reversed bounds => should be empty token sequence
213
        sub = ts.subSequence(6, 1);
242
        sub = ts.subSequence(6, 1);
214
        assertFalse(sub.moveNext());
243
        assertFalse(sub.moveNext());
215
        sub = ts.subSequence(6, 1);
244
        sub = ts.subSequence(6, 1);
216
        assertEquals(Integer.MAX_VALUE, sub.move(6));
245
        assertEquals(6, sub.move(6));
217
    }
246
    }
218
247
219
    public void DtestMoveSkipTokens2() throws IOException {
248
    public void DtestMoveSkipTokens2() throws IOException {
Lines 244-275 Link Here
244
273
245
        // Expect no tokens
274
        // Expect no tokens
246
        assertFalse(ts.moveNext());
275
        assertFalse(ts.moveNext());
247
        // Exception if ts.token() called
276
        assertNull(ts.token());
248
        try {
249
            ts.token(); // should throw exception
250
            fail("IllegalStateException expecxted");
251
        } catch (IllegalStateException e) {
252
            // expected
253
        }
254
        
277
        
255
        assertEquals(ts.move(0), Integer.MAX_VALUE);
278
        assertEquals(0, ts.move(0));
256
        assertEquals(ts.move(10), Integer.MAX_VALUE);
279
        assertEquals(10, ts.move(10));
257
        
280
        
258
        // Test subsequences
281
        // Test subsequences
259
        TokenSequence<? extends TokenId> sub = ts.subSequence(1, 6);
282
        TokenSequence<? extends TokenId> sub = ts.subSequence(1, 6);
260
        assertFalse(sub.moveNext());
283
        assertFalse(sub.moveNext());
261
        sub = ts.subSequence(1, 6);
284
        sub = ts.subSequence(1, 6);
262
        assertEquals(Integer.MAX_VALUE, sub.move(1));
285
        assertEquals(1, sub.move(1));
263
        
286
        
264
        sub = ts.subSequence(0);
287
        sub = ts.subSequence(0);
265
        assertFalse(sub.moveNext());
288
        assertFalse(sub.moveNext());
266
        sub = ts.subSequence(0);
289
        sub = ts.subSequence(0);
267
        assertEquals(Integer.MAX_VALUE, sub.move(0));
290
        assertEquals(0, sub.move(0));
268
291
269
        sub = ts.subSequence(1);
292
        sub = ts.subSequence(1);
270
        assertFalse(sub.moveNext());
293
        assertFalse(sub.moveNext());
271
        sub = ts.subSequence(1);
294
        sub = ts.subSequence(1);
272
        assertEquals(Integer.MAX_VALUE, sub.move(0));
295
        assertEquals(0, sub.move(0));
273
    }
296
    }
274
    
297
    
275
    public void testTokenSize() {
298
    public void testTokenSize() {
Lines 284-290 Link Here
284
        assertFalse(ts.moveNext());
307
        assertFalse(ts.moveNext());
285
        
308
        
286
        TokenList tokenList = LexerTestUtilities.tokenList(ts);
309
        TokenList tokenList = LexerTestUtilities.tokenList(ts);
287
        ts.moveIndex(0); // move to "abc"
310
        ts.moveIndex(0); // move before "abc"
311
        assertTrue(ts.moveNext());
288
        // Test DefaultToken size
312
        // Test DefaultToken size
289
        assertSame(DefaultToken.class, ts.token().getClass());
313
        assertSame(DefaultToken.class, ts.token().getClass());
290
        assertSize("Token instance too big", Collections.singletonList(ts.token()), 24,
314
        assertSize("Token instance too big", Collections.singletonList(ts.token()), 24,
(-)lexer/test/unit/src/org/netbeans/lib/lexer/LanguageManagerTest.java (-3 / +6 lines)
Lines 130-136 Link Here
130
    public void testCachingE() {
130
    public void testCachingE() {
131
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
131
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
132
        TokenSequence tokens = th.tokenSequence();
132
        TokenSequence tokens = th.tokenSequence();
133
        tokens.moveFirst();
133
        tokens.moveStart();
134
        assertEquals(true, tokens.moveNext());
134
        
135
        
135
        TokenSequence embeddedA = tokens.embedded();
136
        TokenSequence embeddedA = tokens.embedded();
136
        assertNotNull("There should be an embedded language", embeddedA);
137
        assertNotNull("There should be an embedded language", embeddedA);
Lines 144-150 Link Here
144
    public void testGCedE() {
145
    public void testGCedE() {
145
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
146
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
146
        TokenSequence tokens = th.tokenSequence();
147
        TokenSequence tokens = th.tokenSequence();
147
        tokens.moveFirst();
148
        tokens.moveStart();
149
        assertEquals(true, tokens.moveNext());
148
        
150
        
149
        TokenSequence embedded = tokens.embedded();
151
        TokenSequence embedded = tokens.embedded();
150
        assertNotNull("There should be an embedded language", embedded);
152
        assertNotNull("There should be an embedded language", embedded);
Lines 164-170 Link Here
164
    public void testCacheRefreshedE() {
166
    public void testCacheRefreshedE() {
165
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
167
        TokenHierarchy th = TokenHierarchy.create("abc", SimplePlainTokenId.language());
166
        TokenSequence tokens = th.tokenSequence();
168
        TokenSequence tokens = th.tokenSequence();
167
        tokens.moveFirst();
169
        tokens.moveStart();
170
        assertEquals(true, tokens.moveNext());
168
        
171
        
169
        TokenSequence embeddedA = tokens.embedded();
172
        TokenSequence embeddedA = tokens.embedded();
170
        assertNotNull("There should be an embedded language", embeddedA);
173
        assertNotNull("There should be an embedded language", embeddedA);
(-)lexer/test/unit/src/org/netbeans/lib/lexer/test/LexerTestUtilities.java (-2 / +7 lines)
Lines 70-75 Link Here
70
    public static void assertTokenEquals(String message, TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset) {
70
    public static void assertTokenEquals(String message, TokenSequence<? extends TokenId> ts, TokenId id, String text, int offset) {
71
        message = messagePrefix(message);
71
        message = messagePrefix(message);
72
        Token<? extends TokenId> t = ts.token();
72
        Token<? extends TokenId> t = ts.token();
73
        TestCase.assertNotNull("Token is null", t);
73
        TokenId tId = t.id();
74
        TokenId tId = t.id();
74
        TestCase.assertEquals(message + "Invalid token.id()", id, tId);
75
        TestCase.assertEquals(message + "Invalid token.id()", id, tId);
75
        CharSequence tText = t.text();
76
        CharSequence tText = t.text();
Lines 312-328 Link Here
312
        }
313
        }
313
        TokenHierarchy<?> thBatch = TokenHierarchy.create(docText, language);
314
        TokenHierarchy<?> thBatch = TokenHierarchy.create(docText, language);
314
        boolean success = false;
315
        boolean success = false;
316
        TokenSequence<?> batchTS = thBatch.tokenSequence();
315
        try {
317
        try {
316
            // Compare lookaheads and states as well
318
            // Compare lookaheads and states as well
317
            assertTokenSequencesEqual(thBatch.tokenSequence(), thBatch,
319
            assertTokenSequencesEqual(batchTS, thBatch,
318
                    thInc.tokenSequence(), thInc, true);
320
                    thInc.tokenSequence(), thInc, true);
319
            success = true;
321
            success = true;
320
        } finally {
322
        } finally {
321
            if (!success) {
323
            if (!success) {
324
                // Go forward two tokens to have an extra tokens context
325
                batchTS.moveNext();
326
                batchTS.moveNext();
322
                System.err.println("BATCH token sequence dump:\n" + thBatch.tokenSequence());
327
                System.err.println("BATCH token sequence dump:\n" + thBatch.tokenSequence());
323
                TokenHierarchy<?> lastHi = (TokenHierarchy<?>)doc.getProperty(LAST_TOKEN_HIERARCHY);
328
                TokenHierarchy<?> lastHi = (TokenHierarchy<?>)doc.getProperty(LAST_TOKEN_HIERARCHY);
324
                if (lastHi != null) {
329
                if (lastHi != null) {
325
                    System.err.println("PREVIOUS token sequence dump:\n" + lastHi.tokenSequence());
330
                    System.err.println("PREVIOUS batch token sequence dump:\n" + lastHi.tokenSequence());
326
                }
331
                }
327
            }
332
            }
328
        }
333
        }
(-)lexer/test/unit/src/org/netbeans/lib/lexer/test/inc/TokenHierarchySnapshotTest.java (-3 / +6 lines)
Lines 76-82 Link Here
76
76
77
        // Check that all the non-fly tokens are mutable
77
        // Check that all the non-fly tokens are mutable
78
        ts = snapshot1.tokenSequence();
78
        ts = snapshot1.tokenSequence();
79
        assertTrue(ts.moveIndex(0));
79
        assertEquals(0, ts.moveIndex(0));
80
        assertTrue(ts.moveNext());
80
        
81
        
81
        LexerTestUtilities.assertTokenSequencesEqual(hi1.tokenSequence(), hi1,
82
        LexerTestUtilities.assertTokenSequencesEqual(hi1.tokenSequence(), hi1,
82
                snapshot1.tokenSequence(), snapshot1, false);
83
                snapshot1.tokenSequence(), snapshot1, false);
Lines 84-90 Link Here
84
        doc.insertString(4, "+", null);
85
        doc.insertString(4, "+", null);
85
86
86
        // Check that the snapshot token sequence can be further operated.
87
        // Check that the snapshot token sequence can be further operated.
87
        assertTrue(ts.moveIndex(0));
88
        assertEquals(0, ts.moveIndex(0));
89
        assertTrue(ts.moveNext());
88
        assertNotNull(ts.token());
90
        assertNotNull(ts.token());
89
91
90
        // Check that the tokens except '+' are live
92
        // Check that the tokens except '+' are live
Lines 101-107 Link Here
101
103
102
        // Check that all the non-fly tokens are mutable
104
        // Check that all the non-fly tokens are mutable
103
        ts = snapshot2.tokenSequence();
105
        ts = snapshot2.tokenSequence();
104
        assertTrue(ts.moveIndex(0));
106
        assertEquals(0, ts.moveIndex(0));
107
        assertTrue(ts.moveNext());
105
108
106
        LexerTestUtilities.assertTokenSequencesEqual(hi2.tokenSequence(), hi2,
109
        LexerTestUtilities.assertTokenSequencesEqual(hi2.tokenSequence(), hi2,
107
                snapshot2.tokenSequence(), snapshot2, false);
110
                snapshot2.tokenSequence(), snapshot2, false);
(-)lexer/test/unit/src/org/netbeans/lib/lexer/test/simple/SimpleLexerBatchTest.java (-1 / +2 lines)
Lines 81-87 Link Here
81
        assertFalse(ts.moveNext());
81
        assertFalse(ts.moveNext());
82
82
83
        // Go back to block comment
83
        // Go back to block comment
84
        assertTrue(ts.moveIndex(commentIndex));
84
        assertEquals(0, ts.moveIndex(commentIndex));
85
        assertTrue(ts.moveNext());
85
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.BLOCK_COMMENT, commentText, commentTextStartOffset);
86
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.BLOCK_COMMENT, commentText, commentTextStartOffset);
86
87
87
        // Test embedded token sequence
88
        // Test embedded token sequence
(-)lexer/test/unit/src/org/netbeans/lib/lexer/test/simple/SimpleLexerIncTest.java (-1 / +5 lines)
Lines 90-108 Link Here
90
        
90
        
91
        // Check TokenSequence.move()
91
        // Check TokenSequence.move()
92
        int relOffset = ts.move(50); // past the end of all tokens
92
        int relOffset = ts.move(50); // past the end of all tokens
93
        assertEquals(relOffset, 50 - offset);
93
        assertEquals(relOffset, 50 - (offset + 3));
94
        assertTrue(ts.movePrevious());
94
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "def", offset);
95
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "def", offset);
95
96
96
        relOffset = ts.move(6); // right at begining of "-"
97
        relOffset = ts.move(6); // right at begining of "-"
97
        assertEquals(relOffset, 0);
98
        assertEquals(relOffset, 0);
99
        assertTrue(ts.moveNext());
98
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.MINUS, "-", 6);
100
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.MINUS, "-", 6);
99
101
100
        relOffset = ts.move(-5); // to first token "abc"
102
        relOffset = ts.move(-5); // to first token "abc"
101
        assertEquals(relOffset, -5);
103
        assertEquals(relOffset, -5);
104
        assertTrue(ts.moveNext());
102
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
105
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "abc", 0);
103
106
104
        relOffset = ts.move(5); // to first token "abc"
107
        relOffset = ts.move(5); // to first token "abc"
105
        assertEquals(relOffset, 1);
108
        assertEquals(relOffset, 1);
109
        assertTrue(ts.moveNext());
106
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "uv", 4);
110
        LexerTestUtilities.assertTokenEquals(ts, SimpleTokenId.IDENTIFIER, "uv", 4);
107
111
108
112
(-)openide/text/src/org/openide/text/CloneableEditorSupport.java (+1 lines)
Lines 1-3 Link Here
1
1
/*
2
/*
2
 * The contents of this file are subject to the terms of the Common Development
3
 * The contents of this file are subject to the terms of the Common Development
3
 * and Distribution License (the License). You may not use this file except in
4
 * and Distribution License (the License). You may not use this file except in
(-)web/jspsyntax/src/org/netbeans/modules/web/core/syntax/SimplifiedJSPServlet.java (-1 / +1 lines)
Lines 97-103 Link Here
97
        TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc);
97
        TokenHierarchy tokenHierarchy = TokenHierarchy.get(doc);
98
        TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); //get top level token sequence
98
        TokenSequence tokenSequence = tokenHierarchy.tokenSequence(); //get top level token sequence
99
        
99
        
100
        if(!tokenSequence.moveFirst()) {
100
        if(!tokenSequence.moveNext()) {
101
            return ; //no tokens in token sequence
101
            return ; //no tokens in token sequence
102
        }
102
        }
103
        
103
        
(-)xml/tageditorsupport/src/org/netbeans/modules/editor/structure/formatting/TagBasedLexerFormatter.java (-13 / +18 lines)
Lines 86-102 Link Here
86
         * e.g. <tag   |attr=
86
         * e.g. <tag   |attr=
87
         * 
87
         * 
88
         */
88
         */
89
        do {
89
        while (tokenSequence.moveNext()) {
90
            tokenSequence.moveNext();
91
            token = tokenSequence.token();
90
            token = tokenSequence.token();
92
            tokenOffset = token.offset(tokenHierarchy);
91
            tokenOffset = tokenSequence.offset();
93
        } while (token != null && isWSTag(token) 
92
            if (!isWSTag(token) || tagStartLine != Utilities.getLineOffset(doc, tokenOffset)) {
94
                && tagStartLine == Utilities.getLineOffset(doc, tokenOffset));
93
                if (!isWSTag(token) && tagStartLine == Utilities.getLineOffset(doc, tokenOffset)){
95
        
94
                    return tokenOffset - Utilities.getRowIndent(doc, tokenOffset) - Utilities.getRowStart(doc, tokenOffset);
96
        if (!isWSTag(token) && tagStartLine == Utilities.getLineOffset(doc, tokenOffset)){
95
                }
97
            return tokenOffset - Utilities.getRowIndent(doc, tokenOffset) - Utilities.getRowStart(doc, tokenOffset);
96
                break;
97
            }
98
        }
98
        }
99
        
99
        
100
        
100
        return getShiftWidth(); // default;
101
        return getShiftWidth(); // default;
101
    }
102
    }
102
    
103
    
Lines 122-128 Link Here
122
            int indentsWithinTags[] = new int[lastLine + 1];
123
            int indentsWithinTags[] = new int[lastLine + 1];
123
            
124
            
124
            TokenSequence tokenSequence = tokenHierarchy.tokenSequence();
125
            TokenSequence tokenSequence = tokenHierarchy.tokenSequence();
125
            boolean thereAreMoreTokens = tokenSequence.moveFirst();
126
            tokenSequence.moveStart();
127
            boolean thereAreMoreTokens = tokenSequence.moveNext();
128
            
126
            
129
            
127
            if (tokenSequence != null){
130
            if (tokenSequence != null){
128
                // calc line indents - pass 1
131
                // calc line indents - pass 1
Lines 435-448 Link Here
435
        tokenSequence.move(offset);
438
        tokenSequence.move(offset);
436
        int currentOffset;
439
        int currentOffset;
437
        
440
        
438
        do{
441
        while (tokenSequence.moveNext()) {
439
            currentOffset = tokenSequence.offset();
442
            currentOffset = tokenSequence.offset();
440
            
443
            
441
            if (isClosingTag(tokenHierarchy, currentOffset)){
444
            if (isClosingTag(tokenHierarchy, currentOffset)){
442
                return currentOffset;
445
                return currentOffset;
443
            }
446
            }
444
            
447
            
445
        } while (tokenSequence.moveNext());
448
        }
446
449
447
        return -1;
450
        return -1;
448
    }
451
    }
Lines 459-466 Link Here
459
    protected Token getTokenAtOffset(TokenHierarchy tokenHierarchy, int tagTokenOffset){
462
    protected Token getTokenAtOffset(TokenHierarchy tokenHierarchy, int tagTokenOffset){
460
        TokenSequence tokenSequence = tokenHierarchy.tokenSequence();
463
        TokenSequence tokenSequence = tokenHierarchy.tokenSequence();
461
        
464
        
462
        if (tokenSequence != null && tokenSequence.move(tagTokenOffset) != Integer.MAX_VALUE){
465
        if (tokenSequence != null) {
463
            return tokenSequence.token();
466
            tokenSequence.move(tagTokenOffset);
467
            if (tokenSequence.moveNext())
468
                return tokenSequence.token();
464
        }
469
        }
465
        
470
        
466
        return null;
471
        return null;

Return to bug 90796