KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > codeassist > complete > CompletionScanner


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.codeassist.complete;
12
13 /*
14  * Scanner aware of a cursor location so as to discard trailing portions of identifiers
15  * containing the cursor location.
16  *
17  * Cursor location denotes the position of the last character behind which completion
18  * got requested:
19  * -1 means completion at the very beginning of the source
20  * 0 means completion behind the first character
21  * n means completion behind the n-th character
22  */

23 import org.eclipse.jdt.core.compiler.*;
24 import org.eclipse.jdt.internal.compiler.parser.Scanner;
25 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
26
27 public class CompletionScanner extends Scanner {
28
29     public char[] completionIdentifier;
30     public int cursorLocation;
31     public int endOfEmptyToken = -1;
32         
33     /* Source positions of the completedIdentifier
34      * if inside actual identifier, end goes to the actual identifier
35      * end, in other words, beyond cursor location
36      */

37     public int completedIdentifierStart = 0;
38     public int completedIdentifierEnd = -1;
39     public int unicodeCharSize;
40
41     public static final char[] EmptyCompletionIdentifier = {};
42     
43 public CompletionScanner(long sourceLevel) {
44     super(
45         false /*comment*/,
46         false /*whitespace*/,
47         false /*nls*/,
48         sourceLevel,
49         null /*taskTags*/,
50         null/*taskPriorities*/,
51         true/*taskCaseSensitive*/);
52 }
53 /*
54  * Truncate the current identifier if it is containing the cursor location. Since completion is performed
55  * on an identifier prefix.
56  *
57  */

58 public char[] getCurrentIdentifierSource() {
59
60     if (this.completionIdentifier == null){
61         if (this.cursorLocation < this.startPosition && this.currentPosition == this.startPosition){ // fake empty identifier got issued
62
// remember actual identifier positions
63
this.completedIdentifierStart = this.startPosition;
64             this.completedIdentifierEnd = this.completedIdentifierStart - 1;
65             return this.completionIdentifier = EmptyCompletionIdentifier;
66         }
67         if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition){
68             // remember actual identifier positions
69
this.completedIdentifierStart = this.startPosition;
70             this.completedIdentifierEnd = this.currentPosition - 1;
71             if (this.withoutUnicodePtr != 0){ // check unicode scenario
72
int length = this.cursorLocation + 1 - this.startPosition - this.unicodeCharSize;
73                 System.arraycopy(this.withoutUnicodeBuffer, 1, this.completionIdentifier = new char[length], 0, length);
74             } else {
75                 // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
76
int length = this.cursorLocation + 1 - this.startPosition;
77                 System.arraycopy(this.source, this.startPosition, (this.completionIdentifier = new char[length]), 0, length);
78             }
79             return this.completionIdentifier;
80         }
81     }
82     return super.getCurrentIdentifierSource();
83 }
84
85 public char[] getCurrentTokenSourceString() {
86     if (this.completionIdentifier == null){
87         if (this.cursorLocation+1 >= this.startPosition && this.cursorLocation < this.currentPosition){
88             // remember actual identifier positions
89
this.completedIdentifierStart = this.startPosition;
90             this.completedIdentifierEnd = this.currentPosition - 1;
91             if (this.withoutUnicodePtr != 0){ // check unicode scenario
92
int length = this.cursorLocation - this.startPosition - this.unicodeCharSize;
93                 System.arraycopy(this.withoutUnicodeBuffer, 2, this.completionIdentifier = new char[length], 0, length);
94             } else {
95                 // no char[] sharing around completionIdentifier, we want it to be unique so as to use identity checks
96
int length = this.cursorLocation - this.startPosition;
97                 System.arraycopy(this.source, this.startPosition + 1, (this.completionIdentifier = new char[length]), 0, length);
98             }
99             return this.completionIdentifier;
100         }
101     }
102     return super.getCurrentTokenSourceString();
103 }
104 public int getNextToken() throws InvalidInputException {
105
106     this.wasAcr = false;
107     this.unicodeCharSize = 0;
108     if (this.diet) {
109         jumpOverMethodBody();
110         this.diet = false;
111         return this.currentPosition > this.eofPosition ? TokenNameEOF : TokenNameRBRACE;
112     }
113     int whiteStart = 0;
114     try {
115         while (true) { //loop for jumping over comments
116
this.withoutUnicodePtr = 0;
117             //start with a new token (even comment written with unicode )
118

119             // ---------Consume white space and handles start position---------
120
whiteStart = this.currentPosition;
121             boolean isWhiteSpace, hasWhiteSpaces = false;
122             int offset = 0;
123             do {
124                 this.startPosition = this.currentPosition;
125                 boolean checkIfUnicode = false;
126                 try {
127                     checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
128                         && (this.source[this.currentPosition] == 'u');
129                 } catch(IndexOutOfBoundsException JavaDoc e) {
130                     if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
131                         // reposition scanner in case we are interested by spaces as tokens
132
this.currentPosition--;
133                         this.startPosition = whiteStart;
134                         return TokenNameWHITESPACE;
135                     }
136                     if (this.currentPosition > this.eofPosition) {
137                         /* might be completing at eof (e.g. behind a dot) */
138                         if (this.completionIdentifier == null &&
139                             this.startPosition == this.cursorLocation + 1){
140                             this.currentPosition = this.startPosition; // for being detected as empty free identifier
141
return TokenNameIdentifier;
142                         }
143                         return TokenNameEOF;
144                     }
145                 }
146                 if (checkIfUnicode) {
147                     isWhiteSpace = jumpOverUnicodeWhiteSpace();
148                     offset = 6;
149                 } else {
150                     offset = 1;
151                     if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
152                         //checkNonExternalizedString();
153
if (this.recordLineSeparator) {
154                             pushLineSeparator();
155                         }
156                     }
157                     isWhiteSpace =
158                         (this.currentCharacter == ' ') || CharOperation.isWhitespace(this.currentCharacter);
159                 }
160                 if (isWhiteSpace) {
161                     hasWhiteSpaces = true;
162                 }
163                 /* completion requesting strictly inside blanks */
164                 if ((whiteStart != this.currentPosition)
165                     //&& (previousToken == TokenNameDOT)
166
&& (this.completionIdentifier == null)
167                     && (whiteStart <= this.cursorLocation+1)
168                     && (this.cursorLocation < this.startPosition)
169                     && !ScannerHelper.isJavaIdentifierStart(this.currentCharacter)){
170                     this.currentPosition = this.startPosition; // for next token read
171
return TokenNameIdentifier;
172                 }
173             } while (isWhiteSpace);
174             if (this.tokenizeWhiteSpace && hasWhiteSpaces) {
175                 // reposition scanner in case we are interested by spaces as tokens
176
this.currentPosition-=offset;
177                 this.startPosition = whiteStart;
178                 return TokenNameWHITESPACE;
179             }
180             //little trick to get out in the middle of a source computation
181
if (this.currentPosition > this.eofPosition){
182                 /* might be completing at eof (e.g. behind a dot) */
183                 if (this.completionIdentifier == null &&
184                     this.startPosition == this.cursorLocation + 1){
185                     // compute end of empty identifier.
186
// if the empty identifier is at the start of a next token the end of
187
// empty identifier is the end of the next token (eg. "<empty token>next").
188
int temp = this.eofPosition;
189                     this.eofPosition = this.source.length;
190                     while(getNextCharAsJavaIdentifierPart()){/*empty*/}
191                     this.eofPosition = temp;
192                     this.endOfEmptyToken = this.currentPosition - 1;
193                     this.currentPosition = this.startPosition; // for being detected as empty free identifier
194
return TokenNameIdentifier;
195                 }
196                 return TokenNameEOF;
197             }
198
199             // ---------Identify the next token-------------
200

201             switch (this.currentCharacter) {
202                 case '@' :
203                     return TokenNameAT;
204                 case '(' :
205                     return TokenNameLPAREN;
206                 case ')' :
207                     return TokenNameRPAREN;
208                 case '{' :
209                     return TokenNameLBRACE;
210                 case '}' :
211                     return TokenNameRBRACE;
212                 case '[' :
213                     return TokenNameLBRACKET;
214                 case ']' :
215                     return TokenNameRBRACKET;
216                 case ';' :
217                     return TokenNameSEMICOLON;
218                 case ',' :
219                     return TokenNameCOMMA;
220                 case '.' :
221                     if (this.startPosition <= this.cursorLocation
222                         && this.cursorLocation < this.currentPosition){
223                             return TokenNameDOT; // completion inside .<|>12
224
}
225                     if (getNextCharAsDigit()) {
226                         return scanNumber(true);
227                     }
228                     int temp = this.currentPosition;
229                     if (getNextChar('.')) {
230                         if (getNextChar('.')) {
231                             return TokenNameELLIPSIS;
232                         } else {
233                             this.currentPosition = temp;
234                             return TokenNameDOT;
235                         }
236                     } else {
237                         this.currentPosition = temp;
238                         return TokenNameDOT;
239                     }
240                 case '+' :
241                     {
242                         int test;
243                         if ((test = getNextChar('+', '=')) == 0)
244                             return TokenNamePLUS_PLUS;
245                         if (test > 0)
246                             return TokenNamePLUS_EQUAL;
247                         return TokenNamePLUS;
248                     }
249                 case '-' :
250                     {
251                         int test;
252                         if ((test = getNextChar('-', '=')) == 0)
253                             return TokenNameMINUS_MINUS;
254                         if (test > 0)
255                             return TokenNameMINUS_EQUAL;
256                         return TokenNameMINUS;
257                     }
258                 case '~' :
259                     return TokenNameTWIDDLE;
260                 case '!' :
261                     if (getNextChar('='))
262                         return TokenNameNOT_EQUAL;
263                     return TokenNameNOT;
264                 case '*' :
265                     if (getNextChar('='))
266                         return TokenNameMULTIPLY_EQUAL;
267                     return TokenNameMULTIPLY;
268                 case '%' :
269                     if (getNextChar('='))
270                         return TokenNameREMAINDER_EQUAL;
271                     return TokenNameREMAINDER;
272                 case '<' :
273                     {
274                         int test;
275                         if ((test = getNextChar('=', '<')) == 0)
276                             return TokenNameLESS_EQUAL;
277                         if (test > 0) {
278                             if (getNextChar('='))
279                                 return TokenNameLEFT_SHIFT_EQUAL;
280                             return TokenNameLEFT_SHIFT;
281                         }
282                         return TokenNameLESS;
283                     }
284                 case '>' :
285                     {
286                         int test;
287                         if (this.returnOnlyGreater) {
288                             return TokenNameGREATER;
289                         }
290                         if ((test = getNextChar('=', '>')) == 0)
291                             return TokenNameGREATER_EQUAL;
292                         if (test > 0) {
293                             if ((test = getNextChar('=', '>')) == 0)
294                                 return TokenNameRIGHT_SHIFT_EQUAL;
295                             if (test > 0) {
296                                 if (getNextChar('='))
297                                     return TokenNameUNSIGNED_RIGHT_SHIFT_EQUAL;
298                                 return TokenNameUNSIGNED_RIGHT_SHIFT;
299                             }
300                             return TokenNameRIGHT_SHIFT;
301                         }
302                         return TokenNameGREATER;
303                     }
304                 case '=' :
305                     if (getNextChar('='))
306                         return TokenNameEQUAL_EQUAL;
307                     return TokenNameEQUAL;
308                 case '&' :
309                     {
310                         int test;
311                         if ((test = getNextChar('&', '=')) == 0)
312                             return TokenNameAND_AND;
313                         if (test > 0)
314                             return TokenNameAND_EQUAL;
315                         return TokenNameAND;
316                     }
317                 case '|' :
318                     {
319                         int test;
320                         if ((test = getNextChar('|', '=')) == 0)
321                             return TokenNameOR_OR;
322                         if (test > 0)
323                             return TokenNameOR_EQUAL;
324                         return TokenNameOR;
325                     }
326                 case '^' :
327                     if (getNextChar('='))
328                         return TokenNameXOR_EQUAL;
329                     return TokenNameXOR;
330                 case '?' :
331                     return TokenNameQUESTION;
332                 case ':' :
333                     return TokenNameCOLON;
334                 case '\'' :
335                     {
336                         int test;
337                         if ((test = getNextChar('\n', '\r')) == 0) {
338                             throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
339                         }
340                         if (test > 0) {
341                             // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
342
for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
343                                 if (this.currentPosition + lookAhead == this.eofPosition)
344                                     break;
345                                 if (this.source[this.currentPosition + lookAhead] == '\n')
346                                     break;
347                                 if (this.source[this.currentPosition + lookAhead] == '\'') {
348                                     this.currentPosition += lookAhead + 1;
349                                     break;
350                                 }
351                             }
352                             throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
353                         }
354                     }
355                     if (getNextChar('\'')) {
356                         // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
357
for (int lookAhead = 0; lookAhead < 3; lookAhead++) {
358                             if (this.currentPosition + lookAhead == this.eofPosition)
359                                 break;
360                             if (this.source[this.currentPosition + lookAhead] == '\n')
361                                 break;
362                             if (this.source[this.currentPosition + lookAhead] == '\'') {
363                                 this.currentPosition += lookAhead + 1;
364                                 break;
365                             }
366                         }
367                         throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
368                     }
369                     if (getNextChar('\\')) {
370                         if (this.unicodeAsBackSlash) {
371                             // consume next character
372
this.unicodeAsBackSlash = false;
373                             if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
374                                 getNextUnicodeChar();
375                             } else {
376                                 if (this.withoutUnicodePtr != 0) {
377                                     unicodeStore();
378                                 }
379                             }
380                         } else {
381                             this.currentCharacter = this.source[this.currentPosition++];
382                         }
383                         scanEscapeCharacter();
384                     } else { // consume next character
385
this.unicodeAsBackSlash = false;
386                         boolean checkIfUnicode = false;
387                         try {
388                             checkIfUnicode = ((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
389                             && (this.source[this.currentPosition] == 'u');
390                         } catch(IndexOutOfBoundsException JavaDoc e) {
391                             this.currentPosition--;
392                             throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
393                         }
394                         if (checkIfUnicode) {
395                             getNextUnicodeChar();
396                         } else {
397                             if (this.withoutUnicodePtr != 0) {
398                                 this.unicodeStore();
399                             }
400                         }
401                     }
402                     if (getNextChar('\''))
403                         return TokenNameCharacterLiteral;
404                     // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
405
for (int lookAhead = 0; lookAhead < 20; lookAhead++) {
406                         if (this.currentPosition + lookAhead == this.eofPosition)
407                             break;
408                         if (this.source[this.currentPosition + lookAhead] == '\n')
409                             break;
410                         if (this.source[this.currentPosition + lookAhead] == '\'') {
411                             this.currentPosition += lookAhead + 1;
412                             break;
413                         }
414                     }
415                     throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
416                 case '"' :
417                     try {
418                         // consume next character
419
this.unicodeAsBackSlash = false;
420                         boolean isUnicode = false;
421                         if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
422                             && (this.source[this.currentPosition] == 'u')) {
423                             getNextUnicodeChar();
424                             isUnicode = true;
425                         } else {
426                             if (this.withoutUnicodePtr != 0) {
427                                 this.unicodeStore();
428                             }
429                         }
430
431                         while (this.currentCharacter != '"') {
432                             /**** \r and \n are not valid in string literals ****/
433                             if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
434                                 if (isUnicode) {
435                                     int start = this.currentPosition - 5;
436                                     while(this.source[start] != '\\') {
437                                         start--;
438                                     }
439                                     if(this.startPosition <= this.cursorLocation
440                                             && this.cursorLocation <= this.currentPosition-1) {
441                                         this.currentPosition = start;
442                                         // complete inside a string literal
443
return TokenNameStringLiteral;
444                                     }
445                                     start = this.currentPosition;
446                                     for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
447                                         if (this.currentPosition >= this.eofPosition) {
448                                             this.currentPosition = start;
449                                             break;
450                                         }
451                                         if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
452                                             isUnicode = true;
453                                             getNextUnicodeChar();
454                                         } else {
455                                             isUnicode = false;
456                                         }
457                                         if (!isUnicode && this.currentCharacter == '\n') {
458                                             this.currentPosition--; // set current position on new line character
459
break;
460                                         }
461                                         if (this.currentCharacter == '\"') {
462                                             throw new InvalidInputException(INVALID_CHAR_IN_STRING);
463                                         }
464                                     }
465                                 } else {
466                                     this.currentPosition--; // set current position on new line character
467
if(this.startPosition <= this.cursorLocation
468                                             && this.cursorLocation <= this.currentPosition-1) {
469                                         // complete inside a string literal
470
return TokenNameStringLiteral;
471                                     }
472                                 }
473                                 throw new InvalidInputException(INVALID_CHAR_IN_STRING);
474                             }
475                             if (this.currentCharacter == '\\') {
476                                 if (this.unicodeAsBackSlash) {
477                                     this.withoutUnicodePtr--;
478                                     // consume next character
479
this.unicodeAsBackSlash = false;
480                                     if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\') && (this.source[this.currentPosition] == 'u')) {
481                                         getNextUnicodeChar();
482                                         isUnicode = true;
483                                         this.withoutUnicodePtr--;
484                                     } else {
485                                         isUnicode = false;
486                                     }
487                                 } else {
488                                     if (this.withoutUnicodePtr == 0) {
489                                         unicodeInitializeBuffer(this.currentPosition - this.startPosition);
490                                     }
491                                     this.withoutUnicodePtr --;
492                                     this.currentCharacter = this.source[this.currentPosition++];
493                                 }
494                                 // we need to compute the escape character in a separate buffer
495
scanEscapeCharacter();
496                                 if (this.withoutUnicodePtr != 0) {
497                                     unicodeStore();
498                                 }
499                             }
500                             // consume next character
501
this.unicodeAsBackSlash = false;
502                             if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
503                                 && (this.source[this.currentPosition] == 'u')) {
504                                 getNextUnicodeChar();
505                                 isUnicode = true;
506                             } else {
507                                 isUnicode = false;
508                                 if (this.withoutUnicodePtr != 0) {
509                                     this.unicodeStore();
510                                 }
511                             }
512
513                         }
514                     } catch (IndexOutOfBoundsException JavaDoc e) {
515                         this.currentPosition--;
516                         if(this.startPosition <= this.cursorLocation
517                             && this.cursorLocation < this.currentPosition) {
518                             // complete inside a string literal
519
return TokenNameStringLiteral;
520                         }
521                         throw new InvalidInputException(UNTERMINATED_STRING);
522                     } catch (InvalidInputException e) {
523                         if (e.getMessage().equals(INVALID_ESCAPE)) {
524                             // relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
525
for (int lookAhead = 0; lookAhead < 50; lookAhead++) {
526                                 if (this.currentPosition + lookAhead == this.eofPosition)
527                                     break;
528                                 if (this.source[this.currentPosition + lookAhead] == '\n')
529                                     break;
530                                 if (this.source[this.currentPosition + lookAhead] == '\"') {
531                                     this.currentPosition += lookAhead + 1;
532                                     break;
533                                 }
534                             }
535
536                         }
537                         throw e; // rethrow
538
}
539                     return TokenNameStringLiteral;
540                 case '/' :
541                     {
542                         int test;
543                         if ((test = getNextChar('/', '*')) == 0) { //line comment
544
this.lastCommentLinePosition = this.currentPosition;
545                             try { //get the next char
546
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
547                                     && (this.source[this.currentPosition] == 'u')) {
548                                     //-------------unicode traitement ------------
549
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
550                                     this.currentPosition++;
551                                     while (this.source[this.currentPosition] == 'u') {
552                                         this.currentPosition++;
553                                     }
554                                     if ((c1 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
555                                         || c1 < 0
556                                         || (c2 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
557                                         || c2 < 0
558                                         || (c3 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
559                                         || c3 < 0
560                                         || (c4 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
561                                         || c4 < 0) {
562                                         throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
563                                     } else {
564                                         this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
565                                     }
566                                 }
567
568                                 //handle the \\u case manually into comment
569
if (this.currentCharacter == '\\') {
570                                     if (this.source[this.currentPosition] == '\\')
571                                         this.currentPosition++;
572                                 } //jump over the \\
573
boolean isUnicode = false;
574                                 while (this.currentCharacter != '\r' && this.currentCharacter != '\n') {
575                                     this.lastCommentLinePosition = this.currentPosition;
576                                     //get the next char
577
isUnicode = false;
578                                     if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
579                                         && (this.source[this.currentPosition] == 'u')) {
580                                         isUnicode = true;
581                                         //-------------unicode traitement ------------
582
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
583                                         this.currentPosition++;
584                                         while (this.source[this.currentPosition] == 'u') {
585                                             this.currentPosition++;
586                                         }
587                                         if ((c1 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
588                                             || c1 < 0
589                                             || (c2 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
590                                             || c2 < 0
591                                             || (c3 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
592                                             || c3 < 0
593                                             || (c4 = ScannerHelper.getNumericValue(this.source[this.currentPosition++])) > 15
594                                             || c4 < 0) {
595                                             throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
596                                         } else {
597                                             this.currentCharacter = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
598                                         }
599                                     }
600                                     //handle the \\u case manually into comment
601
if (this.currentCharacter == '\\') {
602                                         if (this.source[this.currentPosition] == '\\')
603                                             this.currentPosition++;
604                                     } //jump over the \\
605
}
606                                 /*
607                                  * We need to completely consume the line break
608                                  */

609                                 if (this.currentCharacter == '\r'
610                                    && this.eofPosition > this.currentPosition) {
611                                     if (this.source[this.currentPosition] == '\n') {
612                                         this.currentPosition++;
613                                         this.currentCharacter = '\n';
614                                     } else if ((this.source[this.currentPosition] == '\\')
615                                         && (this.source[this.currentPosition + 1] == 'u')) {
616                                         isUnicode = true;
617                                         char unicodeChar;
618                                         int index = this.currentPosition + 1;
619                                         index++;
620                                         while (this.source[index] == 'u') {
621                                             index++;
622                                         }
623                                         //-------------unicode traitement ------------
624
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
625                                         if ((c1 = ScannerHelper.getNumericValue(this.source[index++])) > 15
626                                             || c1 < 0
627                                             || (c2 = ScannerHelper.getNumericValue(this.source[index++])) > 15
628                                             || c2 < 0
629                                             || (c3 = ScannerHelper.getNumericValue(this.source[index++])) > 15
630                                             || c3 < 0
631                                             || (c4 = ScannerHelper.getNumericValue(this.source[index++])) > 15
632                                             || c4 < 0) {
633                                             this.currentPosition = index;
634                                             throw new InvalidInputException(INVALID_UNICODE_ESCAPE);
635                                         } else {
636                                             unicodeChar = (char) (((c1 * 16 + c2) * 16 + c3) * 16 + c4);
637                                         }
638                                         if (unicodeChar == '\n') {
639                                             this.currentPosition = index;
640                                             this.currentCharacter = '\n';
641                                         }
642                                     }
643                                 }
644                                 recordComment(TokenNameCOMMENT_LINE);
645                                 if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
646                                     throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
647                                 }
648                                 if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
649                                 if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
650                                     //checkNonExternalizedString();
651
if (this.recordLineSeparator) {
652                                         if (isUnicode) {
653                                             pushUnicodeLineSeparator();
654                                         } else {
655                                             pushLineSeparator();
656                                         }
657                                     }
658                                 }
659                                 if (this.tokenizeComments) {
660                                     return TokenNameCOMMENT_LINE;
661                                 }
662                             } catch (IndexOutOfBoundsException JavaDoc e) {
663                                 this.currentPosition--;
664                                 recordComment(TokenNameCOMMENT_LINE);
665                                 if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
666                                 if (this.tokenizeComments) {
667                                     return TokenNameCOMMENT_LINE;
668                                 } else {
669                                     this.currentPosition++;
670                                 }
671                             }
672                             break;
673                         }
674                         if (test > 0) { //traditional and javadoc comment
675
try { //get the next char
676
boolean isJavadoc = false, star = false;
677                                 boolean isUnicode = false;
678                                 // consume next character
679
this.unicodeAsBackSlash = false;
680                                 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
681                                     && (this.source[this.currentPosition] == 'u')) {
682                                     getNextUnicodeChar();
683                                     isUnicode = true;
684                                 } else {
685                                     isUnicode = false;
686                                     if (this.withoutUnicodePtr != 0) {
687                                         this.unicodeStore();
688                                     }
689                                 }
690     
691                                 if (this.currentCharacter == '*') {
692                                     isJavadoc = true;
693                                     star = true;
694                                 }
695                                 if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
696                                     //checkNonExternalizedString();
697
if (this.recordLineSeparator) {
698                                         if (!isUnicode) {
699                                             pushLineSeparator();
700                                         }
701                                     }
702                                 }
703                                 isUnicode = false;
704                                 if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
705                                     && (this.source[this.currentPosition] == 'u')) {
706                                     //-------------unicode traitement ------------
707
getNextUnicodeChar();
708                                     isUnicode = true;
709                                 } else {
710                                     isUnicode = false;
711                                 }
712                                 //handle the \\u case manually into comment
713
if (this.currentCharacter == '\\') {
714                                     if (this.source[this.currentPosition] == '\\')
715                                         this.currentPosition++;
716                                 } //jump over the \\
717
// empty comment is not a javadoc /**/
718
if (this.currentCharacter == '/') {
719                                     isJavadoc = false;
720                                 }
721                                 //loop until end of comment */
722
while ((this.currentCharacter != '/') || (!star)) {
723                                     if ((this.currentCharacter == '\r') || (this.currentCharacter == '\n')) {
724                                         //checkNonExternalizedString();
725
if (this.recordLineSeparator) {
726                                             if (!isUnicode) {
727                                                 pushLineSeparator();
728                                             }
729                                         }
730                                     }
731                                     star = this.currentCharacter == '*';
732                                     //get next char
733
if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
734                                         && (this.source[this.currentPosition] == 'u')) {
735                                         //-------------unicode traitement ------------
736
getNextUnicodeChar();
737                                         isUnicode = true;
738                                     } else {
739                                         isUnicode = false;
740                                     }
741                                     //handle the \\u case manually into comment
742
if (this.currentCharacter == '\\') {
743                                         if (this.source[this.currentPosition] == '\\')
744                                             this.currentPosition++;
745                                     } //jump over the \\
746
}
747                                 int token = isJavadoc ? TokenNameCOMMENT_JAVADOC : TokenNameCOMMENT_BLOCK;
748                                 recordComment(token);
749                                 if (!isJavadoc && this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition-1){
750                                     throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_COMMENT);
751                                 }
752                                 if (this.taskTags != null) checkTaskTag(this.startPosition, this.currentPosition);
753                                 if (this.tokenizeComments) {
754                                     /*
755                                     if (isJavadoc)
756                                         return TokenNameCOMMENT_JAVADOC;
757                                     return TokenNameCOMMENT_BLOCK;
758                                     */

759                                     return token;
760                                 }
761                             } catch (IndexOutOfBoundsException JavaDoc e) {
762                                 this.currentPosition--;
763                                 throw new InvalidInputException(UNTERMINATED_COMMENT);
764                             }
765                             break;
766                         }
767                         if (getNextChar('='))
768                             return TokenNameDIVIDE_EQUAL;
769                         return TokenNameDIVIDE;
770                     }
771                 case '\u001a' :
772                     if (atEnd())
773                         return TokenNameEOF;
774                     //the atEnd may not be <this.currentPosition == this.source.length> if source is only some part of a real (external) stream
775
throw new InvalidInputException("Ctrl-Z"); //$NON-NLS-1$
776

777                 default :
778                     if (ScannerHelper.isJavaIdentifierStart(this.currentCharacter))
779                         return scanIdentifierOrKeyword();
780                     if (ScannerHelper.isDigit(this.currentCharacter)) {
781                         return scanNumber(false);
782                     }
783                     return TokenNameERROR;
784             }
785         }
786     } //-----------------end switch while try--------------------
787
catch (IndexOutOfBoundsException JavaDoc e) {
788         if (this.tokenizeWhiteSpace && (whiteStart != this.currentPosition - 1)) {
789             // reposition scanner in case we are interested by spaces as tokens
790
this.currentPosition--;
791             this.startPosition = whiteStart;
792             return TokenNameWHITESPACE;
793         }
794     }
795     /* might be completing at very end of file (e.g. behind a dot) */
796     if (this.completionIdentifier == null &&
797         this.startPosition == this.cursorLocation + 1){
798         this.currentPosition = this.startPosition; // for being detected as empty free identifier
799
return TokenNameIdentifier;
800     }
801     return TokenNameEOF;
802 }
803 public final void getNextUnicodeChar() throws InvalidInputException {
804     int temp = this.currentPosition; // the \ is already read
805
super.getNextUnicodeChar();
806     if(this.cursorLocation > temp) {
807         this.unicodeCharSize += (this.currentPosition - temp);
808     }
809     if (temp < this.cursorLocation && this.cursorLocation < this.currentPosition-1){
810         throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_UNICODE);
811     }
812 }
813 public final void jumpOverBlock() {
814     this.jumpOverMethodBody();
815 }
816 ///*
817
// * In case we actually read a keyword, but the cursor is located inside,
818
// * we pretend we read an identifier.
819
// */
820
public int scanIdentifierOrKeyword() {
821     
822     int id = super.scanIdentifierOrKeyword();
823
824     if (this.startPosition <= this.cursorLocation+1
825             && this.cursorLocation < this.currentPosition){
826         
827         // extends the end of the completion token even if the end is after eofPosition
828
if (this.cursorLocation+1 == this.eofPosition) {
829             int temp = this.eofPosition;
830             this.eofPosition = this.source.length;
831             while(getNextCharAsJavaIdentifierPart()){/*empty*/}
832             this.eofPosition = temp;
833         }
834         // convert completed keyword into an identifier
835
return TokenNameIdentifier;
836     }
837     return id;
838 }
839
840 public int scanNumber(boolean dotPrefix) throws InvalidInputException {
841     
842     int token = super.scanNumber(dotPrefix);
843
844     // consider completion just before a number to be ok, will insert before it
845
if (this.startPosition <= this.cursorLocation && this.cursorLocation < this.currentPosition){
846         throw new InvalidCursorLocation(InvalidCursorLocation.NO_COMPLETION_INSIDE_NUMBER);
847     }
848     return token;
849 }
850 }
851
Popular Tags