1 11 package org.eclipse.jdt.internal.codeassist.complete; 12 13 import java.util.ArrayList ; 14 import java.util.List ; 15 16 import org.eclipse.jdt.core.compiler.CharOperation; 17 import org.eclipse.jdt.core.compiler.InvalidInputException; 18 import org.eclipse.jdt.internal.codeassist.CompletionEngine; 19 import org.eclipse.jdt.internal.compiler.ast.*; 20 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 21 import org.eclipse.jdt.internal.compiler.parser.JavadocParser; 22 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper; 23 import org.eclipse.jdt.internal.compiler.parser.TerminalTokens; 24 25 28 public class CompletionJavadocParser extends JavadocParser { 29 30 public final static int INLINE_ALL_TAGS_LENGTH; 32 public final static int BLOCK_ALL_TAGS_LENGTH; 33 static { 34 int length = 0; 35 for (int i=0; i<INLINE_TAGS_LENGTH; i++) { 36 length += INLINE_TAGS[i].length; 37 } 38 INLINE_ALL_TAGS_LENGTH = length; 39 length = 0; 40 for (int i=0; i<BLOCK_TAGS_LENGTH; i++) { 41 length += BLOCK_TAGS[i].length; 42 } 43 BLOCK_ALL_TAGS_LENGTH = length; 44 } 45 46 char[][][] levelTags = new char[2][][]; 48 int[] levelTagsLength = new int[2]; 49 50 int cursorLocation; 52 CompletionOnJavadoc completionNode = null; 53 boolean pushText = false; 54 boolean allPossibleTags = false; 55 56 public CompletionJavadocParser(CompletionParser sourceParser) { 57 super(sourceParser); 58 this.scanner = new CompletionScanner(ClassFileConstants.JDK1_3); 59 this.kind = COMPLETION_PARSER | TEXT_PARSE; 60 this.reportProblems = false; 61 initLevelTags(); 62 } 63 64 67 public boolean checkDeprecation(int commentPtr) { 68 this.cursorLocation = ((CompletionParser)sourceParser).cursorLocation; 69 CompletionScanner completionScanner = (CompletionScanner)this.scanner; 70 completionScanner.cursorLocation = this.cursorLocation; 71 this.javadocStart = this.sourceParser.scanner.commentStarts[commentPtr]; 72 this.javadocEnd = this.sourceParser.scanner.commentStops[commentPtr]; 73 if (this.javadocStart <= this.cursorLocation && this.cursorLocation <= this.javadocEnd) { 74 if (CompletionEngine.DEBUG) { 75 System.out.println("COMPLETION in Javadoc:"); } 77 completionScanner.completionIdentifier = null; 78 this.firstTagPosition = 1; 79 super.checkDeprecation(commentPtr); 80 } else { 81 this.docComment = null; 82 } 83 return false; 84 } 85 86 89 protected boolean commentParse() { 90 this.docComment = new CompletionJavadoc(this.javadocStart, this.javadocEnd); 91 return super.commentParse(); 92 } 93 94 97 protected Object createArgumentReference(char[] name, int dim, boolean isVarargs, Object typeRef, long[] dimPositions, long argNamePos) throws InvalidInputException { 98 char[] argName = name==null ? CharOperation.NO_CHAR : name; 100 Expression expression = (Expression) super.createArgumentReference(argName, dim, isVarargs, typeRef, dimPositions, argNamePos); 101 int refStart = ((TypeReference)typeRef).sourceStart; 103 int refEnd = ((TypeReference)typeRef).sourceEnd; 104 boolean inCompletion = (refStart <= this.cursorLocation && this.cursorLocation <= refEnd) || ((refStart == (refEnd+1) && refEnd == this.cursorLocation)); if (this.completionNode == null && inCompletion) { 107 JavadocArgumentExpression javadocArgument = (JavadocArgumentExpression) expression; 108 TypeReference expressionType = javadocArgument.argument.type; 109 if (expressionType instanceof JavadocSingleTypeReference) { 110 this.completionNode = new CompletionOnJavadocSingleTypeReference((JavadocSingleTypeReference) expressionType); 111 } else if (expressionType instanceof JavadocQualifiedTypeReference) { 112 this.completionNode = new CompletionOnJavadocQualifiedTypeReference((JavadocQualifiedTypeReference) expressionType); 113 } 114 if (CompletionEngine.DEBUG) { 115 System.out.println(" completion argument="+completionNode); } 117 return this.completionNode; 118 } 119 return expression; 120 } 121 122 125 protected Object createFieldReference(Object receiver) throws InvalidInputException { 126 int refStart = (int) (this.identifierPositionStack[0] >>> 32); 127 int refEnd = (int) this.identifierPositionStack[0]; 128 boolean inCompletion = (refStart <= (this.cursorLocation+1) && this.cursorLocation <= refEnd) || ((refStart == (refEnd+1) && refEnd == this.cursorLocation)) || (this.memberStart == this.cursorLocation); if (inCompletion) { 132 JavadocFieldReference fieldRef = (JavadocFieldReference) super.createFieldReference(receiver); 133 char[] name = this.sourceParser.compilationUnit.getMainTypeName(); 134 TypeDeclaration typeDecl = getParsedTypeDeclaration(); 135 if (typeDecl != null) { 136 name = typeDecl.name; 137 } 138 this.completionNode = new CompletionOnJavadocFieldReference(fieldRef, this.memberStart, name); 139 if (CompletionEngine.DEBUG) { 140 System.out.println(" completion field="+completionNode); } 142 return this.completionNode; 143 } 144 return super.createFieldReference(receiver); 145 } 146 147 152 protected Object createMethodReference(Object receiver, List arguments) throws InvalidInputException { 153 int memberPtr = this.identifierLengthStack[0] - 1; int refStart = (int) (this.identifierPositionStack[memberPtr] >>> 32); 155 int refEnd = (int) this.identifierPositionStack[memberPtr]; 156 boolean inCompletion = (refStart <= (this.cursorLocation+1) && this.cursorLocation <= refEnd) || ((refStart == (refEnd+1) && refEnd == this.cursorLocation)) || (this.memberStart == this.cursorLocation); if (inCompletion) { 160 ASTNode node = (ASTNode) super.createMethodReference(receiver, arguments); 161 if (node instanceof JavadocMessageSend) { 162 JavadocMessageSend messageSend = (JavadocMessageSend) node; 163 int nameStart = (int) (messageSend.nameSourcePosition >>> 32); 164 int nameEnd = (int) messageSend.nameSourcePosition; 165 if ((nameStart <= (this.cursorLocation+1) && this.cursorLocation <= nameEnd)) { 166 this.completionNode = new CompletionOnJavadocFieldReference(messageSend, this.memberStart); 167 } else { 168 this.completionNode = new CompletionOnJavadocMessageSend(messageSend, this.memberStart); 169 } 170 } else if (node instanceof JavadocAllocationExpression) { 171 this.completionNode = new CompletionOnJavadocAllocationExpression((JavadocAllocationExpression)node, this.memberStart); 172 } 173 if (CompletionEngine.DEBUG) { 174 System.out.println(" completion method="+completionNode); } 176 return this.completionNode; 177 } 178 return super.createMethodReference(receiver, arguments); 179 } 180 181 184 protected Object createTypeReference(int primitiveToken) { 185 int nbIdentifiers = this.identifierLengthStack[this.identifierLengthPtr]; 187 int startPtr = this.identifierPtr - (nbIdentifiers-1); 188 int refStart = (int) (this.identifierPositionStack[startPtr] >>> 32); 189 int refEnd = (int) this.identifierPositionStack[this.identifierPtr]; 190 boolean inCompletion = (refStart <= (this.cursorLocation+1) && this.cursorLocation <= refEnd) || ((refStart == (refEnd+1) && refEnd == this.cursorLocation)); if (!inCompletion) { 193 return super.createTypeReference(primitiveToken); 194 } 195 this.identifierLengthPtr--; 196 if (nbIdentifiers == 1) { this.completionNode = new CompletionOnJavadocSingleTypeReference( 198 this.identifierStack[this.identifierPtr], 199 this.identifierPositionStack[this.identifierPtr], 200 this.tagSourceStart, 201 this.tagSourceEnd); 202 } else if (nbIdentifiers > 1) { for (int i=startPtr; i<this.identifierPtr; i++) { 204 int start = (int) (this.identifierPositionStack[i] >>> 32); 205 int end = (int) this.identifierPositionStack[i]; 206 if (start <= this.cursorLocation && this.cursorLocation <= end) { 207 if (i == startPtr) { 208 this.completionNode = new CompletionOnJavadocSingleTypeReference( 209 this.identifierStack[startPtr], 210 this.identifierPositionStack[startPtr], 211 this.tagSourceStart, 212 this.tagSourceEnd); 213 } else { 214 char[][] tokens = new char[i][]; 215 System.arraycopy(this.identifierStack, startPtr, tokens, 0, i); 216 long[] positions = new long[i+1]; 217 System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, i+1); 218 this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, this.identifierStack[i], positions, this.tagSourceStart, this.tagSourceEnd); 219 } 220 break; 221 } 222 } 223 if (this.completionNode == null) { 224 char[][] tokens = new char[nbIdentifiers-1][]; 225 System.arraycopy(this.identifierStack, startPtr, tokens, 0, nbIdentifiers-1); 226 long[] positions = new long[nbIdentifiers]; 227 System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, nbIdentifiers); 228 this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, this.identifierStack[this.identifierPtr], positions, this.tagSourceStart, this.tagSourceEnd); 229 } 230 } 231 232 if (CompletionEngine.DEBUG) { 233 System.out.println(" completion partial qualified type="+completionNode); } 235 return this.completionNode; 236 } 237 238 241 private char[][][] possibleTags(char[] prefix, boolean newLine) { 242 char[][][] possibleTags = new char[2][][]; 243 if (newLine) { 244 System.arraycopy(this.levelTags[BLOCK_IDX], 0, possibleTags[BLOCK_IDX] = new char[this.levelTagsLength[BLOCK_IDX]][], 0, this.levelTagsLength[BLOCK_IDX]); 245 } else { 246 possibleTags[BLOCK_IDX] = CharOperation.NO_CHAR_CHAR; 247 } 248 System.arraycopy(this.levelTags[INLINE_IDX], 0, possibleTags[INLINE_IDX] = new char[this.levelTagsLength[INLINE_IDX]][], 0, this.levelTagsLength[INLINE_IDX]); 249 if (prefix == null || prefix.length == 0) return possibleTags; 250 int kinds = levelTags.length; 251 for (int k=0; k<kinds; k++) { 252 int length = possibleTags[k].length, size = 0; 253 int indexes[] = new int[length]; 254 for (int i=0; i<length; i++) { 255 if (CharOperation.prefixEquals(prefix, possibleTags[k][i], false)) { 256 indexes[size++] = i; 257 } 258 } 259 char[][] tags = new char[size][]; 260 for (int i=0; i<size; i++) { 261 tags[i] = possibleTags[k][indexes[i]]; 262 } 263 possibleTags[k] = tags; 264 } 265 return possibleTags; 266 } 267 268 private CompletionJavadoc getCompletionJavadoc() { 269 return (CompletionJavadoc)this.docComment; 270 } 271 272 private CompletionParser getCompletionParser() { 273 return (CompletionParser)this.sourceParser; 274 } 275 276 279 private void initLevelTags() { 280 int level = ((int)(this.complianceLevel >>> 16)) - ClassFileConstants.MAJOR_VERSION_1_1 + 1; 281 this.levelTags[BLOCK_IDX] = new char[BLOCK_ALL_TAGS_LENGTH][]; 283 this.levelTagsLength[BLOCK_IDX] = 0; 284 for (int i=0; i<=level; i++) { 285 int length = BLOCK_TAGS[i].length; 286 System.arraycopy(BLOCK_TAGS[i], 0, this.levelTags[BLOCK_IDX], this.levelTagsLength[BLOCK_IDX], length); 287 this.levelTagsLength[BLOCK_IDX] += length; 288 } 289 if (this.levelTagsLength[BLOCK_IDX] < BLOCK_ALL_TAGS_LENGTH) { 290 System.arraycopy(this.levelTags[BLOCK_IDX], 0, this.levelTags[BLOCK_IDX] = new char[this.levelTagsLength[BLOCK_IDX]][], 0, this.levelTagsLength[BLOCK_IDX]); 291 } 292 this.levelTags[INLINE_IDX] = new char[INLINE_ALL_TAGS_LENGTH][]; 294 this.levelTagsLength[INLINE_IDX]= 0; 295 for (int i=0; i<=level; i++) { 296 int length = INLINE_TAGS[i].length; 297 System.arraycopy(INLINE_TAGS[i], 0, this.levelTags[INLINE_IDX], this.levelTagsLength[INLINE_IDX], length); 298 this.levelTagsLength[INLINE_IDX] += length; 299 } 300 if (this.levelTagsLength[INLINE_IDX] < INLINE_ALL_TAGS_LENGTH) { 301 System.arraycopy(this.levelTags[INLINE_IDX], 0, this.levelTags[INLINE_IDX] = new char[this.levelTagsLength[INLINE_IDX]][], 0, this.levelTagsLength[INLINE_IDX]); 302 } 303 } 304 307 protected Object parseArguments(Object receiver) throws InvalidInputException { 308 309 if (this.tagSourceStart>this.cursorLocation) { 310 return super.parseArguments(receiver); 311 } 312 313 int modulo = 0; int iToken = 0; 316 char[] argName = null; 317 List arguments = new ArrayList (10); 318 Object typeRef = null; 319 int dim = 0; 320 boolean isVarargs = false; 321 long[] dimPositions = new long[20]; char[] name = null; 323 long argNamePos = -1; 324 325 nextArg : while (this.index < this.scanner.eofPosition) { 327 328 try { 330 typeRef = parseQualifiedName(false); 331 if (this.abort) return null; } catch (InvalidInputException e) { 333 break nextArg; 334 } 335 boolean firstArg = modulo == 0; 336 if (firstArg) { if (iToken != 0) 338 break nextArg; 339 } else if ((iToken % modulo) != 0) { 340 break nextArg; 341 } 342 if (typeRef == null) { 343 if (firstArg && getCurrentTokenType() == TerminalTokens.TokenNameRPAREN) { 344 this.lineStarted = true; 345 return createMethodReference(receiver, null); 346 } 347 Object methodRef = createMethodReference(receiver, arguments); 348 return syntaxRecoverEmptyArgumentType(methodRef); 349 } 350 if (this.index >= this.scanner.eofPosition) { 351 int argumentStart = ((ASTNode)typeRef).sourceStart; 352 Object argument = createArgumentReference(this.scanner.getCurrentIdentifierSource(), 0, false, typeRef, null, (((long)argumentStart)<<32)+this.tokenPreviousPosition-1); 353 return syntaxRecoverArgumentType(receiver, arguments, argument); 354 } 355 if (this.index >= this.cursorLocation) { 356 if (this.completionNode instanceof CompletionOnJavadocSingleTypeReference) { 357 CompletionOnJavadocSingleTypeReference singleTypeReference = (CompletionOnJavadocSingleTypeReference) this.completionNode; 358 if (singleTypeReference.token == null || singleTypeReference.token.length == 0) { 359 Object methodRef = createMethodReference(receiver, arguments); 360 return syntaxRecoverEmptyArgumentType(methodRef); 361 } 362 } 363 if (this.completionNode instanceof CompletionOnJavadocQualifiedTypeReference) { 364 CompletionOnJavadocQualifiedTypeReference qualifiedTypeReference = (CompletionOnJavadocQualifiedTypeReference) this.completionNode; 365 if (qualifiedTypeReference.tokens == null || qualifiedTypeReference.tokens.length < qualifiedTypeReference.sourcePositions.length) { 366 Object methodRef = createMethodReference(receiver, arguments); 367 return syntaxRecoverEmptyArgumentType(methodRef); 368 } 369 } 370 } 371 iToken++; 372 373 dim = 0; 375 isVarargs = false; 376 if (readToken() == TerminalTokens.TokenNameLBRACKET) { 377 int dimStart = this.scanner.getCurrentTokenStartPosition(); 379 while (readToken() == TerminalTokens.TokenNameLBRACKET) { 380 consumeToken(); 381 if (readToken() != TerminalTokens.TokenNameRBRACKET) { 382 break nextArg; 383 } 384 consumeToken(); 385 dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition(); 386 } 387 } else if (readToken() == TerminalTokens.TokenNameELLIPSIS) { 388 int dimStart = this.scanner.getCurrentTokenStartPosition(); 390 dimPositions[dim++] = (((long) dimStart) << 32) + this.scanner.getCurrentTokenEndPosition(); 391 consumeToken(); 392 isVarargs = true; 393 } 394 395 argNamePos = -1; 397 if (readToken() == TerminalTokens.TokenNameIdentifier) { 398 consumeToken(); 399 if (firstArg) { if (iToken != 1) 401 break nextArg; 402 } else if ((iToken % modulo) != 1) { 403 break nextArg; 404 } 405 if (argName == null) { if (!firstArg) { 407 break nextArg; 408 } 409 } 410 argName = this.scanner.getCurrentIdentifierSource(); 411 argNamePos = (((long)this.scanner.getCurrentTokenStartPosition())<<32)+this.scanner.getCurrentTokenEndPosition(); 412 iToken++; 413 } else if (argName != null) { break nextArg; 415 } 416 417 if (firstArg) { 419 modulo = iToken + 1; 420 } else { 421 if ((iToken % modulo) != (modulo - 1)) { 422 break nextArg; 423 } 424 } 425 426 int token = readToken(); 428 name = argName == null ? CharOperation.NO_CHAR : argName; 429 if (token == TerminalTokens.TokenNameCOMMA) { 430 Object argument = createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos); 432 if (this.abort) return null; arguments.add(argument); 434 consumeToken(); 435 iToken++; 436 } else if (token == TerminalTokens.TokenNameRPAREN) { 437 Object argument = createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos); 439 if (this.abort) return null; arguments.add(argument); 441 consumeToken(); 442 return createMethodReference(receiver, arguments); 443 } else { 444 Object argument = createArgumentReference(name, dim, isVarargs, typeRef, dimPositions, argNamePos); 445 return syntaxRecoverArgumentType(receiver, arguments, argument); 446 } 447 } 448 449 throw new InvalidInputException(); 451 } 452 453 protected boolean parseParam() throws InvalidInputException { 454 int startPosition = this.index; 455 int endPosition = this.index; 456 long namePosition = (((long)startPosition)<<32) + endPosition; 457 this.identifierPtr = -1; 458 boolean valid = super.parseParam(); 459 if (this.identifierPtr > 2) return valid; 460 char[] name = null; 462 CompletionScanner completionScanner = (CompletionScanner) this.scanner; 463 boolean isTypeParam = false; 464 if (this.identifierPtr >= 0) { 465 char[] identifier = null; 466 switch (this.identifierPtr) { 467 case 2: 468 if (!valid && completionScanner.completionIdentifier != null && completionScanner.completionIdentifier.length == 0) { 469 valid = pushParamName(true); 470 } 471 case 1: 472 isTypeParam = this.identifierStack[0][0] == '<'; 473 identifier = this.identifierStack[1]; 474 namePosition = this.identifierPositionStack[1]; 475 break; 476 case 0: 477 identifier = this.identifierStack[0]; 478 namePosition = this.identifierPositionStack[0]; 479 isTypeParam = identifier.length > 0 && identifier[0] == '<'; 480 break; 481 } 482 if (identifier != null && identifier.length > 0 && ScannerHelper.isJavaIdentifierPart(identifier[0])) { 483 name = identifier; 484 } 485 startPosition = (int)(this.identifierPositionStack[0]>>32); 486 endPosition = (int)this.identifierPositionStack[this.identifierPtr]; 487 } 488 boolean inCompletion = (startPosition <= (this.cursorLocation+1) && this.cursorLocation <= endPosition) || ((startPosition == (endPosition+1) && endPosition == this.cursorLocation)); if (inCompletion) { 491 if (this.completionNode == null) { 492 if (isTypeParam) { 493 this.completionNode = new CompletionOnJavadocTypeParamReference(name, namePosition, startPosition, endPosition); 494 } else { 495 this.completionNode = new CompletionOnJavadocParamNameReference(name, namePosition, startPosition, endPosition); 496 } 497 if (CompletionEngine.DEBUG) { 498 System.out.println(" completion param="+completionNode); } 500 } else if (this.completionNode instanceof CompletionOnJavadocParamNameReference) { 501 CompletionOnJavadocParamNameReference paramNameRef = (CompletionOnJavadocParamNameReference)this.completionNode; 502 int nameStart = (int) (namePosition>>32); 503 paramNameRef.sourceStart = nameStart; 504 int nameEnd = (int) namePosition; 505 if (nameStart<this.cursorLocation && this.cursorLocation<nameEnd) { 506 paramNameRef.sourceEnd = this.cursorLocation + 1; 507 } else { 508 paramNameRef.sourceEnd = nameEnd; 509 } 510 paramNameRef.tagSourceStart = startPosition; 511 paramNameRef.tagSourceEnd = endPosition; 512 } else if (this.completionNode instanceof CompletionOnJavadocTypeParamReference) { 513 CompletionOnJavadocTypeParamReference typeParamRef = (CompletionOnJavadocTypeParamReference)this.completionNode; 514 int nameStart = (int) (namePosition>>32); 515 typeParamRef.sourceStart = nameStart; 516 int nameEnd = (int) namePosition; 517 if (nameStart<this.cursorLocation && this.cursorLocation<nameEnd) { 518 typeParamRef.sourceEnd = this.cursorLocation + 1; 519 } else { 520 typeParamRef.sourceEnd = nameEnd; 521 } 522 typeParamRef.tagSourceStart = startPosition; 523 typeParamRef.tagSourceEnd = endPosition; 524 } 525 } 526 return valid; 527 } 528 529 532 protected boolean parseReference() throws InvalidInputException { 533 boolean completed = this.completionNode != null; 534 boolean valid = super.parseReference(); 535 if (!completed && this.completionNode != null) { 536 this.completionNode.addCompletionFlags(CompletionOnJavadoc.FORMAL_REFERENCE); 537 } 538 return valid; 539 } 540 541 544 protected boolean parseTag(int previousPosition) throws InvalidInputException { 545 int startPosition = this.inlineTagStarted ? this.inlineTagStart : previousPosition; 546 boolean newLine = !this.lineStarted; 547 boolean valid = super.parseTag(previousPosition); 548 boolean inCompletion = (this.tagSourceStart <= (this.cursorLocation+1) && this.cursorLocation <= this.tagSourceEnd) || ((this.tagSourceStart == (this.tagSourceEnd+1) && this.tagSourceEnd == this.cursorLocation)); if (inCompletion) { 551 int end = this.tagSourceEnd; 552 if (this.inlineTagStarted && this.scanner.currentCharacter == '}') { 553 end = this.scanner.currentPosition; 554 } 555 long position = (((long)startPosition)<<32) + end; 556 int length = this.cursorLocation+1-tagSourceStart; 557 char[] tag = new char[length]; 558 System.arraycopy(this.source, this.tagSourceStart, tag, 0, length); 559 char[][][] tags = possibleTags(tag, newLine); 560 if (tags != null) { 561 this.completionNode = new CompletionOnJavadocTag(tag, position, startPosition, end, tags, this.allPossibleTags); 562 } 563 } 564 return valid; 565 } 566 567 570 protected boolean parseThrows() { 571 try { 572 Object typeRef = parseQualifiedName(true); 573 if (this.completionNode != null) { 574 this.completionNode.addCompletionFlags(CompletionOnJavadoc.EXCEPTION); 575 } 576 return pushThrowName(typeRef); 577 } catch (InvalidInputException ex) { 578 } 580 return false; 581 } 582 583 586 protected boolean pushParamName(boolean isTypeParam) { 587 if (super.pushParamName(isTypeParam)) { 588 Expression expression = (Expression) astStack[astPtr]; 589 if (expression.sourceStart <= (this.cursorLocation+1) && this.cursorLocation <= expression.sourceEnd) { 591 if (isTypeParam) { 592 this.completionNode = new CompletionOnJavadocTypeParamReference((JavadocSingleTypeReference)expression); 593 } else { 594 this.completionNode = new CompletionOnJavadocParamNameReference((JavadocSingleNameReference)expression); 595 } 596 if (CompletionEngine.DEBUG) { 597 System.out.println(" completion param="+completionNode); } 599 } 600 return true; 601 } 602 return false; 603 } 604 605 611 protected void pushText(int start, int end) { 612 if (start <= this.cursorLocation && this.cursorLocation <= end) { 613 this.scanner.resetTo(start, end); 614 boolean tokenizeWhiteSpace = this.scanner.tokenizeWhiteSpace; 615 this.scanner.tokenizeWhiteSpace = true; 616 try { 617 Object typeRef = null; 618 this.pushText = true; 619 620 int previousToken = TerminalTokens.TokenNameWHITESPACE; 622 while (!this.scanner.atEnd() && this.completionNode == null && !this.abort) { 623 int token = readTokenSafely(); 624 switch (token) { 625 case TerminalTokens.TokenNameStringLiteral : 626 int strStart = 0, strEnd = 0; 627 if ((strStart=this.scanner.getCurrentTokenStartPosition()+1) <= this.cursorLocation && 628 this.cursorLocation <= (strEnd=this.scanner.getCurrentTokenEndPosition()-1)) 629 { 630 this.scanner.resetTo(strStart, strEnd); 631 } 632 consumeToken(); 633 break; 634 case TerminalTokens.TokenNameERROR : 635 consumeToken(); 636 if (this.scanner.currentCharacter == '#') { Object member = null; 638 try { 639 this.scanner.tokenizeWhiteSpace = false; 640 member = parseMember(typeRef); 641 } catch (InvalidInputException e) { 642 consumeToken(); 643 } 644 this.scanner.tokenizeWhiteSpace = true; 645 if (this.completionNode != null) { 646 int flags = this.inlineTagStarted ? 0 : CompletionOnJavadoc.TEXT|CompletionOnJavadoc.ONLY_INLINE_TAG; 647 if (member instanceof JavadocMessageSend) { 648 JavadocMessageSend msgSend = (JavadocMessageSend) member; 649 this.completionNode = new CompletionOnJavadocMessageSend(msgSend, this.memberStart, flags); 650 if (CompletionEngine.DEBUG) { 651 System.out.println(" new completion method="+completionNode); } 653 } else if (member instanceof JavadocAllocationExpression) { 654 JavadocAllocationExpression alloc = (JavadocAllocationExpression) member; 655 this.completionNode = new CompletionOnJavadocAllocationExpression(alloc, this.memberStart, flags); 656 if (CompletionEngine.DEBUG) { 657 System.out.println(" new completion method="+completionNode); } 659 } else { 660 this.completionNode.addCompletionFlags(flags); 661 } 662 } 663 } 664 break; 665 case TerminalTokens.TokenNameIdentifier : 666 try { 667 this.scanner.tokenizeWhiteSpace = false; 668 typeRef = parseQualifiedName(true); 669 if (this.completionNode == null) { 670 consumeToken(); 671 this.scanner.resetTo(this.tokenPreviousPosition, end); 672 this.index = this.tokenPreviousPosition; 673 } 674 } 675 catch (InvalidInputException e) { 676 consumeToken(); 677 } 678 finally { 679 this.scanner.tokenizeWhiteSpace = true; 680 } 681 if (previousToken != TerminalTokens.TokenNameWHITESPACE) { 682 typeRef = null; 683 this.completionNode = null; 684 } 685 break; 686 case TerminalTokens.TokenNameAT: 687 consumeToken(); 688 try { 689 this.scanner.tokenizeWhiteSpace = false; 690 int startPosition = this.scanner.getCurrentTokenStartPosition(); 691 parseTag(startPosition); 692 if (this.completionNode != null) { 693 if (this.inlineTagStarted) { 694 715 } else { 716 741 } 742 } 743 } catch (InvalidInputException e) { 744 consumeToken(); 745 } 746 this.scanner.tokenizeWhiteSpace = true; 747 break; 748 default : 749 consumeToken(); 750 typeRef = null; 751 break; 752 } 753 previousToken = token; 754 } 755 } 756 finally { 757 this.scanner.tokenizeWhiteSpace = tokenizeWhiteSpace; 758 this.pushText = false; 759 } 760 761 this.index = end; 763 this.scanner.currentPosition = end; 764 consumeToken(); 765 766 if (this.completionNode != null) { 767 if (this.inlineTagStarted) { 768 this.completionNode.addCompletionFlags(CompletionOnJavadoc.FORMAL_REFERENCE); 769 } else { 770 this.completionNode.addCompletionFlags(CompletionOnJavadoc.TEXT); 771 } 772 } 773 } 774 } 775 776 779 protected int readToken() throws InvalidInputException { 780 int token = super.readToken(); 781 if (token == TerminalTokens.TokenNameIdentifier && this.scanner.currentPosition == this.scanner.startPosition) { 782 this.scanner.getCurrentIdentifierSource(); 784 } 785 return token; 786 } 787 788 791 protected Object syntaxRecoverQualifiedName(int primitiveToken) throws InvalidInputException { 792 if (this.cursorLocation == ((int)this.identifierPositionStack[this.identifierPtr])) { 793 return createTypeReference(primitiveToken); 795 } 796 int idLength = this.identifierLengthStack[this.identifierLengthPtr]; 797 char[][] tokens = new char[idLength][]; 798 int startPtr = this.identifierPtr-idLength+1; 799 System.arraycopy(this.identifierStack, startPtr, tokens, 0, idLength); 800 long[] positions = new long[idLength+1]; 801 System.arraycopy(this.identifierPositionStack, startPtr, positions, 0, idLength); 802 positions[idLength] = (((long)this.tokenPreviousPosition)<<32) + this.tokenPreviousPosition; 803 this.completionNode = new CompletionOnJavadocQualifiedTypeReference(tokens, CharOperation.NO_CHAR, positions, this.tagSourceStart, this.tagSourceEnd); 804 805 if (CompletionEngine.DEBUG) { 806 System.out.println(" completion partial qualified type="+completionNode); } 808 return this.completionNode; 809 } 810 811 814 protected Object syntaxRecoverArgumentType(Object receiver, List arguments, Object argument) throws InvalidInputException { 815 if (this.completionNode != null && !this.pushText) { 816 this.completionNode.addCompletionFlags(CompletionOnJavadoc.BASE_TYPES); 817 if (this.completionNode instanceof CompletionOnJavadocSingleTypeReference) { 818 char[] token = ((CompletionOnJavadocSingleTypeReference)this.completionNode).token; 819 if (token != null && token.length > 0) { 820 return this.completionNode; 821 } 822 } else { 823 return this.completionNode; 824 } 825 } 826 if (this.completionNode instanceof CompletionOnJavadocSingleTypeReference) { 828 CompletionOnJavadocSingleTypeReference singleTypeReference = (CompletionOnJavadocSingleTypeReference) this.completionNode; 829 if (singleTypeReference.token != null && singleTypeReference.token.length > 0) { 830 arguments.add(argument); 831 } 832 } else if (this.completionNode instanceof CompletionOnJavadocQualifiedTypeReference) { 833 CompletionOnJavadocQualifiedTypeReference qualifiedTypeReference = (CompletionOnJavadocQualifiedTypeReference) this.completionNode; 834 if (qualifiedTypeReference.tokens != null && qualifiedTypeReference.tokens.length == qualifiedTypeReference.sourcePositions.length) { 835 arguments.add(argument); 836 } 837 } else { 838 arguments.add(argument); 839 } 840 Object methodRef = super.createMethodReference(receiver, arguments); 841 if (methodRef instanceof JavadocMessageSend) { 842 JavadocMessageSend msgSend = (JavadocMessageSend) methodRef; 843 if (this.index > this.cursorLocation) { 844 msgSend.sourceEnd = this.tokenPreviousPosition-1; 845 } 846 int nameStart = (int) (msgSend.nameSourcePosition >>> 32); 847 int nameEnd = (int) msgSend.nameSourcePosition; 848 if ((nameStart <= (this.cursorLocation+1) && this.cursorLocation <= nameEnd)) { 849 this.completionNode = new CompletionOnJavadocFieldReference(msgSend, this.memberStart); 850 } else { 851 this.completionNode = new CompletionOnJavadocMessageSend(msgSend, this.memberStart); 852 } 853 } else if (methodRef instanceof JavadocAllocationExpression) { 854 JavadocAllocationExpression allocExp = (JavadocAllocationExpression) methodRef; 855 if (this.index > this.cursorLocation) { 856 allocExp.sourceEnd = this.tokenPreviousPosition-1; 857 } 858 this.completionNode = new CompletionOnJavadocAllocationExpression(allocExp, this.memberStart); 859 } 860 if (CompletionEngine.DEBUG) { 861 System.out.println(" completion method="+completionNode); } 863 return this.completionNode; 864 } 865 866 869 protected Object syntaxRecoverEmptyArgumentType(Object methodRef) throws InvalidInputException { 870 if (methodRef instanceof JavadocMessageSend) { 871 JavadocMessageSend msgSend = (JavadocMessageSend) methodRef; 872 if (this.index > this.cursorLocation) { 873 msgSend.sourceEnd = this.tokenPreviousPosition-1; 874 } 875 this.completionNode = new CompletionOnJavadocMessageSend(msgSend, this.memberStart); 876 } else if (methodRef instanceof JavadocAllocationExpression) { 877 JavadocAllocationExpression allocExp = (JavadocAllocationExpression) methodRef; 878 if (this.index > this.cursorLocation) { 879 allocExp.sourceEnd = this.tokenPreviousPosition-1; 880 } 881 this.completionNode = new CompletionOnJavadocAllocationExpression(allocExp, this.memberStart); 882 } 883 if (CompletionEngine.DEBUG) { 884 System.out.println(" completion method="+completionNode); } 886 return this.completionNode; 887 } 888 889 892 protected void updateDocComment() { 893 super.updateDocComment(); 894 if (completionNode instanceof Expression) { 895 getCompletionParser().assistNodeParent = this.docComment; 896 getCompletionParser().assistNode = (ASTNode) this.completionNode; 897 getCompletionJavadoc().completionNode = (Expression) completionNode; 898 } 899 } 900 901 904 protected boolean verifySpaceOrEndComment() { 905 CompletionScanner completionScanner = (CompletionScanner) this.scanner; 906 if (completionScanner.completionIdentifier != null && completionScanner.completedIdentifierStart <= this.cursorLocation && this.cursorLocation <= completionScanner.completedIdentifierEnd) { 907 return true; 909 } 910 return super.verifySpaceOrEndComment(); 911 } 912 913 } 914 | Popular Tags |