1 19 20 package org.netbeans.modules.editor.java; 21 22 import com.sun.source.tree.*; 23 import com.sun.source.util.*; 24 25 import java.io.IOException ; 26 import java.util.*; 27 import java.util.logging.Logger ; 28 import java.util.logging.Level ; 29 import javax.lang.model.element.*; 30 import static javax.lang.model.element.ElementKind.*; 31 import static javax.lang.model.element.Modifier.*; 32 import javax.lang.model.type.*; 33 import javax.lang.model.util.Elements; 34 import javax.lang.model.util.Types; 35 import javax.swing.JToolTip ; 36 import javax.swing.text.BadLocationException ; 37 import javax.swing.text.Document ; 38 import javax.swing.text.JTextComponent ; 39 import javax.tools.Diagnostic; 40 41 import org.netbeans.api.editor.completion.Completion; 42 import org.netbeans.api.java.lexer.JavaTokenId; 43 import org.netbeans.api.java.source.*; 44 import org.netbeans.api.java.source.JavaSource.Phase; 45 import org.netbeans.api.java.source.ClassIndex; 46 import org.netbeans.api.lexer.TokenSequence; 47 import org.netbeans.editor.Registry; 48 import org.netbeans.modules.java.editor.codegen.GeneratorUtils; 49 import org.netbeans.spi.editor.completion.*; 50 import org.netbeans.spi.editor.completion.support.AsyncCompletionQuery; 51 import org.netbeans.spi.editor.completion.support.AsyncCompletionTask; 52 53 import org.openide.filesystems.FileObject; 54 import org.openide.util.Exceptions; 55 import org.openide.util.NbBundle; 56 57 61 public class JavaCompletionProvider implements CompletionProvider { 62 63 public int getAutoQueryTypes(JTextComponent component, String typedText) { 64 if (".".equals(typedText)) { 65 if (Utilities.isJavaContext(component, component.getSelectionStart() - 1)) 66 return COMPLETION_QUERY_TYPE; 67 } 68 return 0; 69 } 70 71 public CompletionTask createTask(int type, JTextComponent component) { 72 if ((type & COMPLETION_QUERY_TYPE) != 0 || type == TOOLTIP_QUERY_TYPE || type == DOCUMENTATION_QUERY_TYPE) 73 return new AsyncCompletionTask(new JavaCompletionQuery(type, component.getSelectionStart()), component); 74 return null; 75 } 76 77 static CompletionTask createDocTask(ElementHandle element) { 78 JavaCompletionQuery query = new JavaCompletionQuery(DOCUMENTATION_QUERY_TYPE, -1); 79 query.element = element; 80 return new AsyncCompletionTask(query, Registry.getMostActiveComponent()); 81 } 82 83 public static List<? extends CompletionItem> query(JavaSource source, int queryType, int offset, int substitutionOffset) throws IOException { 84 assert source != null; 85 assert (queryType & COMPLETION_QUERY_TYPE) != 0; 86 JavaCompletionQuery query = new JavaCompletionQuery(queryType, offset); 87 source.runUserActionTask(query, false); 88 if (offset != substitutionOffset) { 89 for (JavaCompletionItem jci : query.results) { 90 jci.substitutionOffset += (substitutionOffset - offset); 91 } 92 } 93 return query.results; 94 } 95 96 static final class JavaCompletionQuery extends AsyncCompletionQuery implements CancellableTask<CompilationController> { 97 98 private static final String ERROR = "<error>"; private static final String INIT = "<init>"; private static final String SPACE = " "; private static final String COLON = ":"; private static final String SEMI = ";"; private static final String EMPTY = ""; 105 private static final String ABSTRACT_KEYWORD = "abstract"; private static final String ASSERT_KEYWORD = "assert"; private static final String BOOLEAN_KEYWORD = "boolean"; private static final String BREAK_KEYWORD = "break"; private static final String BYTE_KEYWORD = "byte"; private static final String CASE_KEYWORD = "case"; private static final String CATCH_KEYWORD = "catch"; private static final String CHAR_KEYWORD = "char"; private static final String CLASS_KEYWORD = "class"; private static final String CONTINUE_KEYWORD = "continue"; private static final String DEFAULT_KEYWORD = "default"; private static final String DOUBLE_KEYWORD = "double"; private static final String ENUM_KEYWORD = "enum"; private static final String EXTENDS_KEYWORD = "extends"; private static final String FALSE_KEYWORD = "false"; private static final String FINAL_KEYWORD = "final"; private static final String FINALLY_KEYWORD = "finally"; private static final String FLOAT_KEYWORD = "float"; private static final String FOR_KEYWORD = "for"; private static final String IF_KEYWORD = "if"; private static final String IMPLEMENTS_KEYWORD = "implements"; private static final String IMPORT_KEYWORD = "import"; private static final String INSTANCEOF_KEYWORD = "instanceof"; private static final String INT_KEYWORD = "int"; private static final String INTERFACE_KEYWORD = "interface"; private static final String LONG_KEYWORD = "long"; private static final String NATIVE_KEYWORD = "native"; private static final String NEW_KEYWORD = "new"; private static final String NULL_KEYWORD = "null"; private static final String PACKAGE_KEYWORD = "package"; private static final String PRIVATE_KEYWORD = "private"; private static final String PROTECTED_KEYWORD = "protected"; private static final String PUBLIC_KEYWORD = "public"; private static final String RETURN_KEYWORD = "return"; private static final String SHORT_KEYWORD = "short"; private static final String STATIC_KEYWORD = "static"; private static final String STRICT_KEYWORD = "strictfp"; private static final String SUPER_KEYWORD = "super"; private static final String SWITCH_KEYWORD = "switch"; private static final String SYNCHRONIZED_KEYWORD = "synchronized"; private static final String THIS_KEYWORD = "this"; private static final String THROW_KEYWORD = "throw"; private static final String THROWS_KEYWORD = "throws"; private static final String TRANSIENT_KEYWORD = "transient"; private static final String TRUE_KEYWORD = "true"; private static final String TRY_KEYWORD = "try"; private static final String VOID_KEYWORD = "void"; private static final String VOLATILE_KEYWORD = "volatile"; private static final String WHILE_KEYWORD = "while"; 155 private static final String [] PRIM_KEYWORDS = new String [] { 156 BOOLEAN_KEYWORD, BYTE_KEYWORD, CHAR_KEYWORD, DOUBLE_KEYWORD, 157 FLOAT_KEYWORD, INT_KEYWORD, LONG_KEYWORD, SHORT_KEYWORD 158 }; 159 160 private static final String [] STATEMENT_KEYWORDS = new String [] { 161 FOR_KEYWORD, SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, TRY_KEYWORD, 162 VOID_KEYWORD, WHILE_KEYWORD 163 }; 164 165 private static final String [] STATEMENT_SPACE_KEYWORDS = new String [] { 166 ASSERT_KEYWORD, NEW_KEYWORD, THROW_KEYWORD 167 }; 168 169 private static final String [] BLOCK_KEYWORDS = new String [] { 170 ASSERT_KEYWORD, CLASS_KEYWORD, FINAL_KEYWORD, NEW_KEYWORD, 171 THROW_KEYWORD 172 }; 173 174 private static final String [] CLASS_BODY_KEYWORDS = new String [] { 175 ABSTRACT_KEYWORD, CLASS_KEYWORD, ENUM_KEYWORD, FINAL_KEYWORD, 176 INTERFACE_KEYWORD, NATIVE_KEYWORD, PRIVATE_KEYWORD, PROTECTED_KEYWORD, 177 PUBLIC_KEYWORD, STATIC_KEYWORD, STRICT_KEYWORD, SYNCHRONIZED_KEYWORD, 178 TRANSIENT_KEYWORD, VOID_KEYWORD, VOLATILE_KEYWORD 179 }; 180 181 private List<JavaCompletionItem> results; 182 private JToolTip toolTip; 183 private CompletionDocumentation documentation; 184 private int anchorOffset; 185 186 private JTextComponent component; 187 188 private int queryType; 189 private int caretOffset; 190 private String filterPrefix; 191 192 private ElementHandle element; 193 194 private JavaCompletionQuery(int queryType, int caretOffset) { 195 this.queryType = queryType; 196 this.caretOffset = caretOffset; 197 } 198 199 @Override 200 protected void preQueryUpdate(JTextComponent component) { 201 int newCaretOffset = component.getSelectionStart(); 202 if (newCaretOffset >= caretOffset) { 203 try { 204 if (getJavaIdentifierPart(component.getDocument().getText(caretOffset, newCaretOffset - caretOffset)) != null) 205 return; 206 } catch (BadLocationException e) { 207 } 208 } 209 Completion.get().hideCompletion(); 210 } 211 212 @Override 213 protected void prepareQuery(JTextComponent component) { 214 this.component = component; 215 } 216 217 @Override 218 protected void query(CompletionResultSet resultSet, Document doc, int caretOffset) { 219 try { 220 this.caretOffset = caretOffset; 221 if (queryType == TOOLTIP_QUERY_TYPE || Utilities.isJavaContext(component, caretOffset)) { 222 results = null; 223 documentation = null; 224 toolTip = null; 225 anchorOffset = -1; 226 JavaSource js = JavaSource.forDocument(doc); 227 if (queryType == DOCUMENTATION_QUERY_TYPE && element != null) { 228 FileObject fo = SourceUtils.getFile(element, js.getClasspathInfo()); 229 if (fo != null) 230 js = JavaSource.forFileObject(fo); 231 } 232 if (js != null) { 233 if (SourceUtils.isScanInProgress()) 234 resultSet.setWaitText(NbBundle.getMessage(JavaCompletionProvider.class, "scanning-in-progress")); js.runUserActionTask(this, true); 236 if ((queryType & COMPLETION_QUERY_TYPE) != 0) { 237 if (results != null) 238 resultSet.addAllItems(results); 239 } else if (queryType == TOOLTIP_QUERY_TYPE) { 240 if (toolTip != null) 241 resultSet.setToolTip(toolTip); 242 } else if (queryType == DOCUMENTATION_QUERY_TYPE) { 243 if (documentation != null) 244 resultSet.setDocumentation(documentation); 245 } 246 if (anchorOffset > -1) 247 resultSet.setAnchorOffset(anchorOffset); 248 } 249 } 250 } catch (IOException ioe) { 251 Exceptions.printStackTrace(ioe); 252 } finally { 253 resultSet.finish(); 254 } 255 } 256 257 @Override 258 protected boolean canFilter(JTextComponent component) { 259 filterPrefix = null; 260 int newOffset = component.getSelectionStart(); 261 if ((queryType & COMPLETION_QUERY_TYPE) != 0) { 262 int offset = Math.min(anchorOffset, caretOffset); 263 if (offset > -1) { 264 if (newOffset < offset) 265 return true; 266 if (newOffset >= caretOffset) { 267 try { 268 String prefix = component.getDocument().getText(offset, newOffset - offset); 269 filterPrefix = getJavaIdentifierPart(prefix); 270 if (filterPrefix != null && filterPrefix.length() == 0) 271 anchorOffset = newOffset; 272 } catch (BadLocationException e) {} 273 return true; 274 } 275 } 276 return false; 277 } else if (queryType == TOOLTIP_QUERY_TYPE) { 278 try { 279 if (newOffset == caretOffset) 280 filterPrefix = EMPTY; 281 else if (newOffset - caretOffset > 0) 282 filterPrefix = component.getDocument().getText(caretOffset, newOffset - caretOffset); 283 else if (newOffset - caretOffset < 0) 284 filterPrefix = component.getDocument().getText(newOffset, caretOffset - newOffset); 285 } catch (BadLocationException ex) {} 286 return (filterPrefix != null && filterPrefix.indexOf(',') == -1 && filterPrefix.indexOf('(') == -1 && filterPrefix.indexOf(')') == -1); } 288 return false; 289 } 290 291 @Override 292 protected void filter(CompletionResultSet resultSet) { 293 try { 294 if ((queryType & COMPLETION_QUERY_TYPE) != 0) { 295 if (filterPrefix != null) { 296 if (results != null) 297 resultSet.addAllItems(getFilteredData(results, filterPrefix)); 298 } else { 299 Completion.get().hideDocumentation(); 300 Completion.get().hideCompletion(); 301 } 302 } else if (queryType == TOOLTIP_QUERY_TYPE) { 303 resultSet.setToolTip(toolTip); 304 } 305 resultSet.setAnchorOffset(anchorOffset); 306 } catch (Exception ex) { 307 Exceptions.printStackTrace(ex); 308 } 309 resultSet.finish(); 310 } 311 312 public void run(CompilationController controller) throws Exception { 313 if ((queryType & COMPLETION_QUERY_TYPE) != 0) 314 resolveCompletion(controller); 315 else if (queryType == TOOLTIP_QUERY_TYPE) 316 resolveToolTip(controller); 317 else if (queryType == DOCUMENTATION_QUERY_TYPE) 318 resolveDocumentation(controller); 319 } 320 321 public void cancel() { 322 } 323 324 private void resolveToolTip(final CompilationController controller) throws IOException { 325 Env env = getCompletionEnvironment(controller, false); 326 Tree lastTree = null; 327 int offset = env.getOffset(); 328 TreePath path = env.getPath(); 329 while (path != null) { 330 Tree tree = path.getLeaf(); 331 if (tree.getKind() == Tree.Kind.METHOD_INVOCATION) { 332 MethodInvocationTree mi = (MethodInvocationTree)tree; 333 CompilationUnitTree root = env.getRoot(); 334 SourcePositions sourcePositions = env.getSourcePositions(); 335 int startPos = lastTree != null ? (int)sourcePositions.getStartPosition(root, lastTree) : offset; 336 List<Tree> argTypes = getArgumentsUpToPos(env, mi.getArguments(), (int)sourcePositions.getEndPosition(root, mi.getMethodSelect()), startPos); 337 if (argTypes != null) { 338 controller.toPhase(Phase.ELEMENTS_RESOLVED); 339 TypeMirror[] types = new TypeMirror[argTypes.size()]; 340 int j = 0; 341 for (Tree t : argTypes) 342 types[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t)); 343 List<List<String >> params = null; 344 Tree mid = mi.getMethodSelect(); 345 path = new TreePath(path, mid); 346 switch (mid.getKind()) { 347 case MEMBER_SELECT: { 348 ExpressionTree exp = ((MemberSelectTree)mid).getExpression(); 349 path = new TreePath(path, exp); 350 Trees trees = controller.getTrees(); 351 final TypeMirror type = trees.getTypeMirror(path); 352 final Element element = trees.getElement(path); 353 final boolean isStatic = element != null && (element.getKind().isClass() || element.getKind().isInterface() || element.getKind() == TYPE_PARAMETER); 354 final boolean isSuperCall = element != null && element.getKind().isField() && element.getSimpleName().contentEquals(SUPER_KEYWORD); 355 final Scope scope = env.getScope(); 356 final TreeUtilities tu = controller.getTreeUtilities(); 357 TypeElement enclClass = scope.getEnclosingClass(); 358 final TypeMirror enclType = enclClass != null ? enclClass.asType() : null; 359 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 360 public boolean accept(Element e, TypeMirror t) { 361 return (!isStatic || e.getModifiers().contains(STATIC) || e.getKind() == CONSTRUCTOR) && tu.isAccessible(scope, e, isSuperCall && enclType != null ? enclType : t); 362 } 363 }; 364 params = getMatchingParams(type, controller.getElementUtilities().getMembers(type, acceptor), ((MemberSelectTree)mid).getIdentifier().toString(), types, controller.getTypes()); 365 break; 366 } 367 case IDENTIFIER: { 368 final Scope scope = env.getScope(); 369 final TreeUtilities tu = controller.getTreeUtilities(); 370 final TypeElement enclClass = scope.getEnclosingClass(); 371 final boolean isStatic = enclClass != null ? (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())) : false; 372 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 373 final ExecutableElement method = scope.getEnclosingMethod(); 374 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 375 public boolean accept(Element e, TypeMirror t) { 376 switch (e.getKind()) { 377 case LOCAL_VARIABLE: 378 case EXCEPTION_PARAMETER: 379 case PARAMETER: 380 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 381 !illegalForwardRefs.contains(e); 382 case FIELD: 383 if (illegalForwardRefs.contains(e)) 384 return false; 385 if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) 386 return !isStatic; 387 default: 388 return (!isStatic || e.getModifiers().contains(STATIC)) && tu.isAccessible(scope, e, t); 389 } 390 } 391 }; 392 String name = ((IdentifierTree)mid).getName().toString(); 393 if (SUPER_KEYWORD.equals(name) && enclClass != null) { 394 TypeMirror superclass = enclClass.getSuperclass(); 395 params = getMatchingParams(superclass, controller.getElementUtilities().getMembers(superclass, acceptor), INIT, types, controller.getTypes()); 396 } else { 397 params = getMatchingParams(enclClass != null ? enclClass.asType() : null, controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), THIS_KEYWORD.equals(name) ? INIT : name, types, controller.getTypes()); 398 } 399 break; 400 } 401 } 402 if (params != null) 403 toolTip = new MethodParamsTipPaintComponent(params, types.length, component); 404 startPos = (int)sourcePositions.getEndPosition(env.getRoot(), mi.getMethodSelect()); 405 anchorOffset = controller.getText().indexOf('(', startPos); return; 407 } 408 } else if (tree.getKind() == Tree.Kind.NEW_CLASS) { 409 NewClassTree nc = (NewClassTree)tree; 410 CompilationUnitTree root = env.getRoot(); 411 SourcePositions sourcePositions = env.getSourcePositions(); 412 int startPos = lastTree != null ? (int)sourcePositions.getStartPosition(root, lastTree) : offset; 413 List<Tree> argTypes = getArgumentsUpToPos(env, nc.getArguments(), (int)sourcePositions.getEndPosition(root, nc.getIdentifier()), startPos); 414 if (argTypes != null) { 415 controller.toPhase(Phase.ELEMENTS_RESOLVED); 416 TypeMirror[] types = new TypeMirror[argTypes.size()]; 417 int j = 0; 418 for (Tree t : argTypes) 419 types[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t)); 420 path = new TreePath(path, nc.getIdentifier()); 421 Trees trees = controller.getTrees(); 422 final TypeMirror type = trees.getTypeMirror(path); 423 final Element el = trees.getElement(path); 424 final Scope scope = env.getScope(); 425 final TreeUtilities tu = controller.getTreeUtilities(); 426 final boolean isAnonymous = nc.getClassBody() != null || el.getKind().isInterface() || el.getModifiers().contains(ABSTRACT); 427 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 428 public boolean accept(Element e, TypeMirror t) { 429 return e.getKind() == CONSTRUCTOR && (tu.isAccessible(scope, e, t) || isAnonymous && e.getModifiers().contains(PROTECTED)); 430 } 431 }; 432 List<List<String >> params = getMatchingParams(type, controller.getElementUtilities().getMembers(type, acceptor), INIT, types, controller.getTypes()); 433 if (params != null) 434 toolTip = new MethodParamsTipPaintComponent(params, types.length, component); 435 startPos = (int)sourcePositions.getEndPosition(env.getRoot(), nc.getIdentifier()); 436 anchorOffset = controller.getText().indexOf('(', startPos); return; 438 } 439 } 440 lastTree = tree; 441 path = path.getParentPath(); 442 } 443 } 444 445 private void resolveDocumentation(CompilationController controller) throws IOException { 446 controller.toPhase(Phase.RESOLVED); 447 Element el = element != null ? element.resolve(controller) : controller.getTrees().getElement(getCompletionEnvironment(controller, false).getPath()); 448 if (el != null) { 449 switch (el.getKind()) { 450 case ANNOTATION_TYPE: 451 case CLASS: 452 case ENUM: 453 case INTERFACE: 454 if (el.asType().getKind() == TypeKind.ERROR) 455 break; 456 case CONSTRUCTOR: 457 case ENUM_CONSTANT: 458 case FIELD: 459 case METHOD: 460 documentation = JavaCompletionDoc.create(controller, el); 461 } 462 } 463 } 464 465 private void resolveCompletion(CompilationController controller) throws IOException { 466 Env env = getCompletionEnvironment(controller, true); 467 results = new ArrayList<JavaCompletionItem>(); 468 anchorOffset = env.getOffset(); 469 TreePath path = env.getPath(); 470 switch(path.getLeaf().getKind()) { 471 case COMPILATION_UNIT: 472 insideCompilationUnit(env); 473 break; 474 case IMPORT: 475 insideImport(env); 476 break; 477 case CLASS: 478 insideClass(env); 479 break; 480 case VARIABLE: 481 insideVariable(env); 482 break; 483 case METHOD: 484 insideMethod(env); 485 break; 486 case MODIFIERS: 487 insideModifiers(env, path); 488 break; 489 case ANNOTATION: 490 insideAnnotation(env); 491 break; 492 case TYPE_PARAMETER: 493 insideTypeParameter(env); 494 break; 495 case PARAMETERIZED_TYPE: 496 insideParameterizedType(env, path); 497 break; 498 case UNBOUNDED_WILDCARD: 499 case EXTENDS_WILDCARD: 500 case SUPER_WILDCARD: 501 TreePath parentPath = path.getParentPath(); 502 if (parentPath.getLeaf().getKind() == Tree.Kind.PARAMETERIZED_TYPE) 503 insideParameterizedType(env, parentPath); 504 break; 505 case BLOCK: 506 insideBlock(env); 507 break; 508 case MEMBER_SELECT: 509 insideMemberSelect(env); 510 break; 511 case METHOD_INVOCATION: 512 insideMethodInvocation(env); 513 break; 514 case NEW_CLASS: 515 insideNewClass(env); 516 break; 517 case ASSERT: 518 case RETURN: 519 case THROW: 520 localResult(env); 521 addValueKeywords(env); 522 break; 523 case CATCH: 524 insideCatch(env); 525 break; 526 case IF: 527 insideIf(env); 528 break; 529 case WHILE_LOOP: 530 insideWhile(env); 531 break; 532 case FOR_LOOP: 533 insideFor(env); 534 break; 535 case ENHANCED_FOR_LOOP: 536 insideForEach(env); 537 break; 538 case SWITCH: 539 insideSwitch(env); 540 break; 541 case CASE: 542 insideCase(env); 543 break; 544 case PARENTHESIZED: 545 insideParens(env); 546 break; 547 case TYPE_CAST: 548 insideExpression(env, path); 549 break; 550 case INSTANCE_OF: 551 insideTypeCheck(env); 552 break; 553 case ARRAY_ACCESS: 554 insideArrayAccess(env); 555 break; 556 case NEW_ARRAY: 557 insideNewArray(env); 558 break; 559 case ASSIGNMENT: 560 insideAssignment(env); 561 break; 562 case MULTIPLY_ASSIGNMENT: 563 case DIVIDE_ASSIGNMENT: 564 case REMAINDER_ASSIGNMENT: 565 case PLUS_ASSIGNMENT: 566 case MINUS_ASSIGNMENT: 567 case LEFT_SHIFT_ASSIGNMENT: 568 case RIGHT_SHIFT_ASSIGNMENT: 569 case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: 570 case AND_ASSIGNMENT: 571 case XOR_ASSIGNMENT: 572 case OR_ASSIGNMENT: 573 insideCompoundAssignment(env); 574 break; 575 case PREFIX_INCREMENT: 576 case PREFIX_DECREMENT: 577 case UNARY_PLUS: 578 case UNARY_MINUS: 579 case BITWISE_COMPLEMENT: 580 case LOGICAL_COMPLEMENT: 581 localResult(env); 582 break; 583 case AND: 584 case CONDITIONAL_AND: 585 case CONDITIONAL_OR: 586 case DIVIDE: 587 case EQUAL_TO: 588 case GREATER_THAN: 589 case GREATER_THAN_EQUAL: 590 case LEFT_SHIFT: 591 case LESS_THAN: 592 case LESS_THAN_EQUAL: 593 case MINUS: 594 case MULTIPLY: 595 case NOT_EQUAL_TO: 596 case OR: 597 case PLUS: 598 case REMAINDER: 599 case RIGHT_SHIFT: 600 case UNSIGNED_RIGHT_SHIFT: 601 case XOR: 602 insideBinaryTree(env); 603 break; 604 case CONDITIONAL_EXPRESSION: 605 insideConditionalExpression(env); 606 break; 607 case EXPRESSION_STATEMENT: 608 insideExpressionStatement(env); 609 break; 610 } 611 } 612 613 private void insideCompilationUnit(Env env) throws IOException { 614 int offset = env.getOffset(); 615 SourcePositions sourcePositions = env.getSourcePositions(); 616 CompilationUnitTree root = env.getRoot(); 617 Tree pkg = root.getPackageName(); 618 if (pkg == null || offset <= sourcePositions.getStartPosition(root, root)) { 619 addKeywordsForCU(env); 620 return; 621 } 622 if (offset <= sourcePositions.getStartPosition(root, pkg)) { 623 addPackages(env, env.getPrefix()); 624 } else if (env.getController().getText().substring((int)sourcePositions.getEndPosition(root, pkg), offset).trim().startsWith(SEMI)) { 625 addKeywordsForCU(env); 626 } 627 } 628 629 private void insideImport(Env env) { 630 int offset = env.getOffset(); 631 String prefix = env.getPrefix(); 632 ImportTree im = (ImportTree)env.getPath().getLeaf(); 633 SourcePositions sourcePositions = env.getSourcePositions(); 634 CompilationUnitTree root = env.getRoot(); 635 if (offset <= sourcePositions.getStartPosition(root, im.getQualifiedIdentifier())) { 636 TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, im, offset); 637 if (last.token().id() == JavaTokenId.IMPORT && Utilities.startsWith(STATIC_KEYWORD, prefix)) 638 addKeyword(env, STATIC_KEYWORD, SPACE, false); 639 addPackages(env, prefix); 640 } 641 } 642 643 private void insideClass(Env env) throws IOException { 644 int offset = env.getOffset(); 645 String prefix = env.getPrefix(); 646 TreePath path = env.getPath(); 647 ClassTree cls = (ClassTree)path.getLeaf(); 648 CompilationController controller = env.getController(); 649 SourcePositions sourcePositions = env.getSourcePositions(); 650 CompilationUnitTree root = env.getRoot(); 651 int startPos = (int)sourcePositions.getEndPosition(root, cls.getModifiers()); 652 if (startPos <= 0) 653 startPos = (int)sourcePositions.getStartPosition(root, cls); 654 String headerText = controller.getText().substring(startPos, offset); 655 int idx = headerText.indexOf('{'); if (idx >= 0) { 657 addKeywordsForClassBody(env); 658 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 659 addElementCreators(env); 660 return; 661 } 662 TreeUtilities tu = controller.getTreeUtilities(); 663 Tree lastImpl = null; 664 for (Tree impl : cls.getImplementsClause()) { 665 int implPos = (int)sourcePositions.getEndPosition(root, impl); 666 if (implPos == Diagnostic.NOPOS || offset <= implPos) 667 break; 668 lastImpl = impl; 669 startPos = implPos; 670 } 671 if (lastImpl != null) { 672 if (controller.getText().substring(startPos, offset).trim().equals(",")) { controller.toPhase(Phase.ELEMENTS_RESOLVED); 674 addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path)); 675 } 676 return; 677 } 678 Tree ext = cls.getExtendsClause(); 679 if (ext != null) { 680 int extPos = (int)sourcePositions.getEndPosition(root, ext); 681 if (extPos != Diagnostic.NOPOS && offset > extPos) { 682 headerText = controller.getText().substring(extPos + 1, offset).trim(); 683 if (IMPLEMENTS_KEYWORD.equals(headerText)) { 684 controller.toPhase(Phase.ELEMENTS_RESOLVED); 685 addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path)); 686 } else { 687 addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false); 688 } 689 return; 690 } 691 } 692 TypeParameterTree lastTypeParam = null; 693 for (TypeParameterTree tp : cls.getTypeParameters()) { 694 int tpPos = (int)sourcePositions.getEndPosition(root, tp); 695 if (tpPos == Diagnostic.NOPOS || offset <= tpPos) 696 break; 697 lastTypeParam = tp; 698 startPos = tpPos; 699 } 700 if (lastTypeParam != null) { 701 headerText = controller.getText().substring(startPos, offset); 702 idx = headerText.indexOf('>'); if (idx > -1) { headerText = headerText.substring(idx + 1).trim(); 705 if (EXTENDS_KEYWORD.equals(headerText)) { 706 controller.toPhase(Phase.ELEMENTS_RESOLVED); 707 addTypes(env, tu.isInterface(cls) ? EnumSet.of(INTERFACE, ANNOTATION_TYPE) : EnumSet.of(CLASS), null, controller.getTrees().getElement(path)); 708 } else if (IMPLEMENTS_KEYWORD.equals(headerText)) { 709 controller.toPhase(Phase.ELEMENTS_RESOLVED); 710 addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path)); 711 } else { 712 if (!tu.isAnnotation(cls)) { 713 if (!tu.isEnum(cls)) 714 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 715 if (!tu.isInterface(cls)) 716 addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false); 717 } 718 } 719 } else { 720 if (lastTypeParam.getBounds().isEmpty()) { 721 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 722 } 723 } 724 return; 725 } 726 TokenSequence<JavaTokenId> lastNonWhitespaceToken = findLastNonWhitespaceToken(env, startPos, offset); 727 if (lastNonWhitespaceToken != null) { 728 switch (lastNonWhitespaceToken.token().id()) { 729 case EXTENDS: 730 controller.toPhase(Phase.ELEMENTS_RESOLVED); 731 addTypes(env, tu.isInterface(cls) ? EnumSet.of(INTERFACE, ANNOTATION_TYPE) : EnumSet.of(CLASS), null, controller.getTrees().getElement(path)); 732 break; 733 case IMPLEMENTS: 734 controller.toPhase(Phase.ELEMENTS_RESOLVED); 735 addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path)); 736 break; 737 case IDENTIFIER: 738 if (!tu.isAnnotation(cls)) { 739 if (!tu.isEnum(cls)) 740 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 741 if (!tu.isInterface(cls)) 742 addKeyword(env, IMPLEMENTS_KEYWORD, SPACE, false); 743 } 744 break; 745 } 746 return; 747 } 748 lastNonWhitespaceToken = findLastNonWhitespaceToken(env, (int)sourcePositions.getStartPosition(root, cls), offset); 749 if (lastNonWhitespaceToken != null && lastNonWhitespaceToken.token().id() == JavaTokenId.AT) { 750 addKeyword(env, INTERFACE_KEYWORD, SPACE, false); 751 addTypes(env, EnumSet.of(ANNOTATION_TYPE), null, null); 752 } else if (path.getParentPath().getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) { 753 addClassModifiers(env, cls.getModifiers().getFlags()); 754 } else { 755 addMemberModifiers(env, cls.getModifiers().getFlags(), false); 756 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 757 } 758 } 759 760 private void insideVariable(Env env) throws IOException { 761 int offset = env.getOffset(); 762 TreePath path = env.getPath(); 763 VariableTree var = (VariableTree)path.getLeaf(); 764 SourcePositions sourcePositions = env.getSourcePositions(); 765 CompilationUnitTree root = env.getRoot(); 766 boolean isLocal = path.getParentPath().getLeaf().getKind() != Tree.Kind.CLASS; 767 Tree type = var.getType(); 768 int typePos = type.getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree)type).getErrorTrees().isEmpty() ? 769 (int)sourcePositions.getEndPosition(root, type) : (int)sourcePositions.getStartPosition(root, type); 770 if (offset <= typePos) { 771 addMemberModifiers(env, var.getModifiers().getFlags(), isLocal); 772 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 773 ModifiersTree mods = var.getModifiers(); 774 if (mods.getFlags().isEmpty() && mods.getAnnotations().isEmpty()) 775 addElementCreators(env); 776 return; 777 } 778 Tree init = unwrapErrTree(var.getInitializer()); 779 if ((init == null || offset <= sourcePositions.getStartPosition(root, init))) { 780 String text = env.getController().getText().substring((int)sourcePositions.getEndPosition(root, type), offset).trim(); 781 if (text.length() == 0) { 782 insideExpression(env, new TreePath(path, type)); 783 } else if (text.endsWith("=")) { localResult(env); 785 addValueKeywords(env); 786 } 787 } else { 788 insideExpression(env, new TreePath(path, init)); 789 } 790 } 791 792 private void insideMethod(Env env) throws IOException { 793 int offset = env.getOffset(); 794 String prefix = env.getPrefix(); 795 TreePath path = env.getPath(); 796 MethodTree mth = (MethodTree)path.getLeaf(); 797 CompilationController controller = env.getController(); 798 SourcePositions sourcePositions = env.getSourcePositions(); 799 CompilationUnitTree root = env.getRoot(); 800 int startPos = (int)sourcePositions.getStartPosition(root, mth); 801 Tree retType = mth.getReturnType(); 802 if (retType == null) { 803 int modPos = (int)sourcePositions.getEndPosition(root, mth.getModifiers()); 804 if (modPos > startPos) 805 startPos = modPos; 806 if (controller.getText().substring(startPos, offset).trim().length() == 0) { 807 addMemberModifiers(env, mth.getModifiers().getFlags(), false); 808 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 809 return; 810 } 811 } else { 812 if (offset <= sourcePositions.getStartPosition(root, retType)) { 813 addMemberModifiers(env, mth.getModifiers().getFlags(), false); 814 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 815 return; 816 } 817 startPos = (int)sourcePositions.getEndPosition(root, retType) + 1; 818 } 819 Tree lastThr = null; 820 for (Tree thr: mth.getThrows()) { 821 int thrPos = (int)sourcePositions.getEndPosition(root, thr); 822 if (thrPos == Diagnostic.NOPOS || offset <= thrPos) 823 break; 824 lastThr = thr; 825 startPos = thrPos; 826 } 827 if (lastThr != null) { 828 if (controller.getText().substring(startPos, offset).trim().equals(",")) { if (queryType == COMPLETION_QUERY_TYPE && mth.getBody() != null) { 830 controller.toPhase(Phase.RESOLVED); 831 Set<TypeMirror> exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, mth.getBody())); 832 Trees trees = controller.getTrees(); 833 Types types = controller.getTypes(); 834 for (ExpressionTree thr : mth.getThrows()) { 835 TypeMirror t = trees.getTypeMirror(new TreePath(path, thr)); 836 for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) 837 if (types.isSubtype(it.next(), t)) 838 it.remove(); 839 if (thr == lastThr) 840 break; 841 } 842 Elements elements = controller.getElements(); 843 for (TypeMirror ex : exs) 844 if (ex.getKind() == TypeKind.DECLARED && Utilities.startsWith(((DeclaredType)ex).asElement().getSimpleName().toString(), prefix)) 845 results.add(JavaCompletionItem.createTypeItem((TypeElement)((DeclaredType)ex).asElement(), (DeclaredType)ex, offset, true, elements.isDeprecated(((DeclaredType)ex).asElement()), true)); 846 } 847 addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")), null); } 849 return; 850 } 851 String headerText = controller.getText().substring(startPos, offset); 852 int parStart = headerText.indexOf('('); if (parStart >= 0) { 854 int parEnd = headerText.indexOf(')', parStart); if (parEnd > parStart) { 856 headerText = headerText.substring(parEnd + 1).trim(); 857 if (THROWS_KEYWORD.equals(headerText)) { 858 if (queryType == COMPLETION_QUERY_TYPE && mth.getBody() != null) { 859 controller.toPhase(Phase.RESOLVED); 860 Set<TypeMirror> exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, mth.getBody())); 861 Elements elements = controller.getElements(); 862 for (TypeMirror ex : exs) 863 if (ex.getKind() == TypeKind.DECLARED && Utilities.startsWith(((DeclaredType)ex).asElement().getSimpleName().toString(), prefix)) 864 results.add(JavaCompletionItem.createTypeItem((TypeElement)((DeclaredType)ex).asElement(), (DeclaredType)ex, offset, true, elements.isDeprecated(((DeclaredType)ex).asElement()), true)); 865 } 866 addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")), null); } else { 868 Tree mthParent = path.getParentPath().getLeaf(); 869 if (mthParent.getKind() == Tree.Kind.CLASS && controller.getTreeUtilities().isAnnotation((ClassTree)mthParent)) { 870 addKeyword(env, DEFAULT_KEYWORD, SPACE, false); 871 } else { 872 addKeyword(env, THROWS_KEYWORD, SPACE, false); 873 } 874 } 875 } else { 876 for (VariableTree param : mth.getParameters()) { 877 int parPos = (int)sourcePositions.getEndPosition(root, param); 878 if (parPos == Diagnostic.NOPOS || offset <= parPos) 879 break; 880 parStart = parPos - startPos; 881 } 882 headerText = headerText.substring(parStart).trim(); 883 if ("(".equals(headerText) || ",".equals(headerText)) { addMemberModifiers(env, Collections.<Modifier>emptySet(), true); 885 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 886 } 887 } 888 } else if (retType != null && headerText.trim().length() == 0) { 889 insideExpression(env, new TreePath(path, retType)); 890 } 891 } 892 893 private void insideModifiers(Env env, TreePath modPath) throws IOException { 894 int offset = env.getOffset(); 895 ModifiersTree mods = (ModifiersTree)modPath.getLeaf(); 896 Set<Modifier> m = EnumSet.noneOf(Modifier.class); 897 TokenSequence<JavaTokenId> ts = env.getController().getTreeUtilities().tokensFor(mods, env.getSourcePositions()); 898 JavaTokenId lastNonWhitespaceTokenId = null; 899 while(ts.moveNext() && ts.offset() < offset) { 900 lastNonWhitespaceTokenId = ts.token().id(); 901 switch (lastNonWhitespaceTokenId) { 902 case PUBLIC: 903 m.add(PUBLIC); 904 break; 905 case PROTECTED: 906 m.add(PROTECTED); 907 break; 908 case PRIVATE: 909 m.add(PRIVATE); 910 break; 911 case STATIC: 912 m.add(STATIC); 913 break; 914 case ABSTRACT: 915 m.add(ABSTRACT); 916 break; 917 case FINAL: 918 m.add(FINAL); 919 break; 920 case SYNCHRONIZED: 921 m.add(SYNCHRONIZED); 922 break; 923 case NATIVE: 924 m.add(NATIVE); 925 break; 926 case STRICTFP: 927 m.add(STRICTFP); 928 break; 929 case TRANSIENT: 930 m.add(TRANSIENT); 931 break; 932 case VOLATILE: 933 m.add(VOLATILE); 934 break; 935 } 936 }; 937 if (lastNonWhitespaceTokenId == JavaTokenId.AT) { 938 addKeyword(env, INTERFACE_KEYWORD, SPACE, false); 939 addTypes(env, EnumSet.of(ANNOTATION_TYPE), null, null); 940 return; 941 } 942 TreePath parentPath = modPath.getParentPath(); 943 Tree parent = parentPath.getLeaf(); 944 TreePath grandParentPath = parentPath.getParentPath(); 945 Tree grandParent = grandParentPath != null ? grandParentPath.getLeaf() : null; 946 if (isTopLevelClass(parent, env.getRoot())) { 947 addClassModifiers(env, m); 948 } else if (parent.getKind() != Tree.Kind.VARIABLE || grandParent == null || grandParent.getKind() == Tree.Kind.CLASS) { 949 addMemberModifiers(env, m, false); 950 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 951 } else if (parent.getKind() == Tree.Kind.VARIABLE && grandParent.getKind() == Tree.Kind.METHOD) { 952 addMemberModifiers(env, m, true); 953 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 954 } else { 955 localResult(env); 956 addKeywordsForBlock(env); 957 } 958 } 959 960 private void insideAnnotation(Env env) throws IOException { 961 int offset = env.getOffset(); 962 String prefix = env.getPrefix(); 963 TreePath path = env.getPath(); 964 AnnotationTree ann = (AnnotationTree)path.getLeaf(); 965 CompilationController controller = env.getController(); 966 SourcePositions sourcePositions = env.getSourcePositions(); 967 CompilationUnitTree root = env.getRoot(); 968 int typeEndPos = (int)sourcePositions.getEndPosition(root, ann.getAnnotationType()); 969 if (offset <= typeEndPos) { 970 TreePath parentPath = path.getParentPath(); 971 if (parentPath.getLeaf().getKind() == Tree.Kind.MODIFIERS) 972 addKeyword(env, INTERFACE_KEYWORD, SPACE, false); 973 if (queryType == CompletionProvider.COMPLETION_QUERY_TYPE) { 974 controller.toPhase(Phase.ELEMENTS_RESOLVED); 975 Set<? extends TypeMirror> smarts = env.getSmartTypes(); 976 if (smarts != null) { 977 Elements elements = controller.getElements(); 978 for (TypeMirror smart : smarts) { 979 if (smart.getKind() == TypeKind.DECLARED) { 980 TypeElement elem = (TypeElement)((DeclaredType)smart).asElement(); 981 if (elem.getKind() == ANNOTATION_TYPE) 982 results.add(JavaCompletionItem.createTypeItem(elem, (DeclaredType)smart, anchorOffset, true, elements.isDeprecated(elem), true)); 983 } 984 } 985 } 986 } 987 addTypes(env, EnumSet.of(ANNOTATION_TYPE), null, null); 988 return; 989 } 990 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, ann, offset); 991 if (ts == null || (ts.token().id() != JavaTokenId.LPAREN && ts.token().id() != JavaTokenId.COMMA)) 992 return; 993 controller.toPhase(Phase.ELEMENTS_RESOLVED); 994 Element annTypeElement = controller.getTrees().getElement(new TreePath(path, ann.getAnnotationType())); 995 if (annTypeElement != null && annTypeElement.getKind() == ANNOTATION_TYPE) { 996 HashSet<String > names = new HashSet<String >(); 997 for(ExpressionTree arg : ann.getArguments()) { 998 if (arg.getKind() == Tree.Kind.ASSIGNMENT && sourcePositions.getEndPosition(root, arg) < offset) { 999 ExpressionTree var = ((AssignmentTree)arg).getVariable(); 1000 if (var.getKind() == Tree.Kind.IDENTIFIER) 1001 names.add(((IdentifierTree)var).getName().toString()); 1002 } 1003 } 1004 int hasOnlyValue = 0; 1005 Elements elements = controller.getElements(); 1006 for(Element e : ((TypeElement)annTypeElement).getEnclosedElements()) { 1007 if (e.getKind() == METHOD) { 1008 String name = e.getSimpleName().toString(); 1009 if (hasOnlyValue < 2) 1010 hasOnlyValue += "value".equals(name) ? 1 : 2; if (!names.contains(name) && Utilities.startsWith(name, prefix)) 1012 results.add(JavaCompletionItem.createAttributeItem((ExecutableElement)e, (ExecutableType)e.asType(), offset, elements.isDeprecated(e))); 1013 } 1014 } 1015 if (hasOnlyValue == 1 && names.size() == 0) 1016 addLocalConstantsAndTypes(env); 1017 } 1018 } 1019 1020 private void insideTypeParameter(Env env) throws IOException { 1021 int offset = env.getOffset(); 1022 String prefix = env.getPrefix(); 1023 TreePath path = env.getPath(); 1024 TypeParameterTree tp = (TypeParameterTree)path.getLeaf(); 1025 CompilationController controller = env.getController(); 1026 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, tp, offset); 1027 if (ts != null) { 1028 switch(ts.token().id()) { 1029 case EXTENDS: 1030 controller.toPhase(Phase.ELEMENTS_RESOLVED); 1031 addTypes(env, EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path.getParentPath())); 1032 break; 1033 case AMP: 1034 controller.toPhase(Phase.ELEMENTS_RESOLVED); 1035 addTypes(env, EnumSet.of(INTERFACE, ANNOTATION_TYPE), null, controller.getTrees().getElement(path.getParentPath())); 1036 break; 1037 case IDENTIFIER: 1038 if (ts.offset() == env.getSourcePositions().getStartPosition(env.getRoot(), tp)) 1039 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 1040 break; 1041 } 1042 } 1043 } 1044 1045 private void insideParameterizedType(Env env, TreePath ptPath) throws IOException { 1046 int offset = env.getOffset(); 1047 String prefix = env.getPrefix(); 1048 ParameterizedTypeTree ta = (ParameterizedTypeTree)ptPath.getLeaf(); 1049 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, ta, offset); 1050 if (ts != null) { 1051 switch (ts.token().id()) { 1052 case EXTENDS: 1053 case SUPER: 1054 case LT: 1055 case COMMA: 1056 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1057 break; 1058 case QUESTION: 1059 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 1060 addKeyword(env, SUPER_KEYWORD, SPACE, false); 1061 break; 1062 } 1063 } 1064 } 1065 1066 private void insideBlock(Env env) throws IOException { 1067 int offset = env.getOffset(); 1068 BlockTree bl = (BlockTree)env.getPath().getLeaf(); 1069 SourcePositions sourcePositions = env.getSourcePositions(); 1070 CompilationUnitTree root = env.getRoot(); 1071 int blockPos = (int)sourcePositions.getStartPosition(root, bl); 1072 String text = env.getController().getText().substring(blockPos, offset); 1073 if (text.indexOf('{') < 0) { addMemberModifiers(env, Collections.singleton(STATIC), false); 1075 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1076 return; 1077 } 1078 StatementTree last = null; 1079 for(StatementTree stat : bl.getStatements()) { 1080 int pos = (int)sourcePositions.getStartPosition(root, stat); 1081 if (pos == Diagnostic.NOPOS || offset <= pos) 1082 break; 1083 last = stat; 1084 } 1085 if (last == null) { 1086 ExecutableElement enclMethod = env.getScope().getEnclosingMethod(); 1087 if (enclMethod != null && enclMethod.getKind() == ElementKind.CONSTRUCTOR) { 1088 String prefix = env.getPrefix(); 1089 if (THIS_KEYWORD.equals(prefix)) { 1090 Element element = enclMethod.getEnclosingElement(); 1091 addMembers(env, element.asType(), element, EnumSet.of(CONSTRUCTOR), null, false); 1092 } else if (SUPER_KEYWORD.equals(prefix)) { 1093 Element element = enclMethod.getEnclosingElement(); 1094 element = ((DeclaredType)((TypeElement)element).getSuperclass()).asElement(); 1095 addMembers(env, element.asType(), element, EnumSet.of(CONSTRUCTOR), null, false); 1096 } 1097 } 1098 } else if (last.getKind() == Tree.Kind.TRY) { 1099 if (((TryTree)last).getFinallyBlock() == null) { 1100 addKeyword(env, CATCH_KEYWORD, null, false); 1101 addKeyword(env, FINALLY_KEYWORD, null, false); 1102 } 1103 if (((TryTree)last).getCatches().size() == 0) 1104 return; 1105 } 1106 localResult(env); 1107 addKeywordsForBlock(env); 1108 } 1109 1110 private void insideMemberSelect(Env env) throws IOException { 1111 int offset = env.getOffset(); 1112 String prefix = env.getPrefix(); 1113 TreePath path = env.getPath(); 1114 MemberSelectTree fa = (MemberSelectTree)path.getLeaf(); 1115 CompilationController controller = env.getController(); 1116 CompilationUnitTree root = env.getRoot(); 1117 SourcePositions sourcePositions = env.getSourcePositions(); 1118 int expEndPos = (int)sourcePositions.getEndPosition(root, fa.getExpression()); 1119 boolean afterDot = false; 1120 boolean afterLt = false; 1121 int openLtNum = 0; 1122 JavaTokenId lastNonWhitespaceTokenId = null; 1123 TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language()); 1124 ts.move(expEndPos); 1125 while (ts.moveNext()) { 1126 if (ts.offset() >= offset) { 1127 break; 1128 } 1129 switch (ts.token().id()) { 1130 case DOUBLE_LITERAL: 1131 if (ts.offset() != expEndPos || ts.token().text().charAt(0) != '.') 1132 break; 1133 case DOT: 1134 afterDot = true; 1135 break; 1136 case LT: 1137 afterLt = true; 1138 openLtNum++; 1139 break; 1140 case GT: 1141 openLtNum--; 1142 break; 1143 case GTGT: 1144 openLtNum -= 2; 1145 break; 1146 case GTGTGT: 1147 openLtNum -= 3; 1148 break; 1149 } 1150 switch (ts.token().id()) { 1151 case WHITESPACE: 1152 case LINE_COMMENT: 1153 case BLOCK_COMMENT: 1154 break; 1155 default: 1156 lastNonWhitespaceTokenId = ts.token().id(); 1157 } 1158 } 1159 if (!afterDot) { 1160 if (expEndPos <= offset) 1161 insideExpression(env, new TreePath(path, fa.getExpression())); 1162 return; 1163 } 1164 if (openLtNum > 0) { 1165 switch (lastNonWhitespaceTokenId) { 1166 case QUESTION: 1167 addKeyword(env, EXTENDS_KEYWORD, SPACE, false); 1168 addKeyword(env, SUPER_KEYWORD, SPACE, false); 1169 break; 1170 case LT: 1171 case COLON: 1172 case EXTENDS: 1173 case SUPER: 1174 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1175 break; 1176 } 1177 } else if (lastNonWhitespaceTokenId != JavaTokenId.STAR) { 1178 controller.toPhase(Phase.ELEMENTS_RESOLVED); 1179 TreePath parentPath = path.getParentPath(); 1180 Tree parent = parentPath != null ? parentPath.getLeaf() : null; 1181 TreePath grandParentPath = parentPath != null ? parentPath.getParentPath() : null; 1182 Tree grandParent = grandParentPath != null ? grandParentPath.getLeaf() : null; 1183 ExpressionTree exp = fa.getExpression(); 1184 TreePath expPath = new TreePath(path, exp); 1185 TypeMirror type = controller.getTrees().getTypeMirror(expPath); 1186 if (type != null) { 1187 EnumSet<ElementKind> kinds; 1188 DeclaredType baseType = null; 1189 Set<TypeMirror> exs = null; 1190 boolean inImport = false; 1191 if (parent.getKind() == Tree.Kind.CLASS && ((ClassTree)parent).getExtendsClause() == fa) { 1192 kinds = EnumSet.of(CLASS); 1193 } else if (parent.getKind() == Tree.Kind.CLASS && ((ClassTree)parent).getImplementsClause().contains(fa)) { 1194 kinds = EnumSet.of(INTERFACE); 1195 } else if (parent.getKind() == Tree.Kind.IMPORT) { 1196 inImport = true; 1197 kinds = ((ImportTree)parent).isStatic() ? EnumSet.of(CLASS, ENUM, INTERFACE, ANNOTATION_TYPE, FIELD, METHOD, ENUM_CONSTANT) : EnumSet.of(CLASS, ANNOTATION_TYPE, ENUM, INTERFACE); 1198 } else if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree)parent).getIdentifier() == fa) { 1199 kinds = EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE); 1200 if (grandParent.getKind() == Tree.Kind.THROW) 1201 baseType = controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")); } else if (parent.getKind() == Tree.Kind.PARAMETERIZED_TYPE && ((ParameterizedTypeTree)parent).getTypeArguments().contains(fa)) { 1203 kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE); 1204 } else if (parent.getKind() == Tree.Kind.ANNOTATION) { 1205 if (((AnnotationTree)parent).getAnnotationType() == fa) { 1206 kinds = EnumSet.of(ANNOTATION_TYPE); 1207 } else { 1208 Iterator<? extends ExpressionTree> it = ((AnnotationTree)parent).getArguments().iterator(); 1209 if (it.hasNext()) { 1210 ExpressionTree et = it.next(); 1211 if (et == fa || (et.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree)et).getExpression() == fa)) { 1212 Element el = controller.getTrees().getElement(expPath); 1213 if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) { 1214 el = controller.getElements().getPackageElement(((TypeElement)el).getQualifiedName()); 1215 } 1216 if (el instanceof PackageElement) 1217 addPackageContent(env, (PackageElement)el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null); 1218 else if (type.getKind() == TypeKind.DECLARED) 1219 addMemberConstantsAndTypes(env, (DeclaredType)type, el); 1220 return; 1221 } 1222 } 1223 kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT); 1224 } 1225 } else if (parent.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree)parent).getExpression() == fa && grandParent != null && grandParent.getKind() == Tree.Kind.ANNOTATION) { 1226 Element el = controller.getTrees().getElement(expPath); 1227 if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) { 1228 el = controller.getElements().getPackageElement(((TypeElement)el).getQualifiedName()); 1229 } 1230 if (el instanceof PackageElement) 1231 addPackageContent(env, (PackageElement)el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null); 1232 else if (type.getKind() == TypeKind.DECLARED) 1233 addMemberConstantsAndTypes(env, (DeclaredType)type, el); 1234 return; 1235 } else if (parent.getKind() == Tree.Kind.VARIABLE && ((VariableTree)parent).getType() == fa && grandParent.getKind() == Tree.Kind.CATCH) { 1236 if (queryType == COMPLETION_QUERY_TYPE) 1237 exs = controller.getTreeUtilities().getUncaughtExceptions(grandParentPath.getParentPath()); 1238 kinds = EnumSet.of(CLASS, INTERFACE); 1239 baseType = controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")); } else if (parent.getKind() == Tree.Kind.METHOD && ((MethodTree)parent).getThrows().contains(fa)) { 1241 Types types = controller.getTypes(); 1242 if (queryType == COMPLETION_QUERY_TYPE && ((MethodTree)parent).getBody() != null) { 1243 controller.toPhase(Phase.RESOLVED); 1244 exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, ((MethodTree)parent).getBody())); 1245 Trees trees = controller.getTrees(); 1246 for (ExpressionTree thr : ((MethodTree)parent).getThrows()) { 1247 if (sourcePositions.getEndPosition(root, thr) >= offset) 1248 break; 1249 TypeMirror t = trees.getTypeMirror(new TreePath(path, thr)); 1250 for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) 1251 if (types.isSubtype(it.next(), t)) 1252 it.remove(); 1253 } 1254 } 1255 kinds = EnumSet.of(CLASS, INTERFACE); 1256 baseType = controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")); } else if (afterLt) { 1258 kinds = EnumSet.of(METHOD); 1259 } else if (parent.getKind() == Tree.Kind.ENHANCED_FOR_LOOP && ((EnhancedForLoopTree)parent).getExpression() == fa) { 1260 env.insideForEachExpressiion(); 1261 kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT); 1262 } else { 1263 kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT); 1264 } 1265 switch (type.getKind()) { 1266 case TYPEVAR: 1267 type = ((TypeVariable)type).getUpperBound(); 1268 if (type == null) 1269 return; 1270 type = controller.getTypes().capture(type); 1271 case ARRAY: 1272 case DECLARED: 1273 case BOOLEAN: 1274 case BYTE: 1275 case CHAR: 1276 case DOUBLE: 1277 case FLOAT: 1278 case INT: 1279 case LONG: 1280 case SHORT: 1281 case VOID: 1282 boolean b = exp.getKind() == Tree.Kind.PARENTHESIZED || exp.getKind() == Tree.Kind.TYPE_CAST; 1283 while(b) { 1284 if (exp.getKind() == Tree.Kind.PARENTHESIZED) { 1285 exp = ((ParenthesizedTree)exp).getExpression(); 1286 expPath = new TreePath(expPath, exp); 1287 } else if (exp.getKind() == Tree.Kind.TYPE_CAST) { 1288 exp = ((TypeCastTree)exp).getExpression(); 1289 expPath = new TreePath(expPath, exp); 1290 } else { 1291 b = false; 1292 } 1293 } 1294 Element el = controller.getTrees().getElement(expPath); 1295 if (el != null && (el.getKind().isClass() || el.getKind().isInterface())) { 1296 if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree)parent).getIdentifier() == fa && prefix != null) { 1297 String typeName = Utilities.getElementName(el, true) + "." + prefix; TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass()); 1299 if (tm != null && tm.getKind() == TypeKind.DECLARED) 1300 addMembers(env, tm, ((DeclaredType)tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport); 1301 } 1302 } 1303 if (exs != null) { 1304 Elements elements = controller.getElements(); 1305 for (TypeMirror ex : exs) 1306 if (ex.getKind() == TypeKind.DECLARED) { 1307 Element e = ((DeclaredType)ex).asElement(); 1308 if (e.getEnclosingElement() == el && Utilities.startsWith(e.getSimpleName().toString(), prefix)) 1309 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)ex, offset, true, elements.isDeprecated(e), true)); 1310 } 1311 } else { 1312 if (el == null && exp.getKind() == Tree.Kind.PRIMITIVE_TYPE) 1313 el = controller.getTypes().boxedClass((PrimitiveType)type); 1314 addMembers(env, type, el, kinds, baseType, inImport); 1315 } 1316 break; 1317 default: 1318 el = controller.getTrees().getElement(expPath); 1319 if (type.getKind() == TypeKind.ERROR && el != null && el.getKind().isClass()) { 1320 el = controller.getElements().getPackageElement(((TypeElement)el).getQualifiedName()); 1321 } 1322 if (el != null && el.getKind() == PACKAGE) { 1323 if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree)parent).getIdentifier() == fa && prefix != null) { 1324 String typeName = Utilities.getElementName(el, true) + "." + prefix; TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass()); 1326 if (tm != null && tm.getKind() == TypeKind.DECLARED) 1327 addMembers(env, tm, ((DeclaredType)tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport); 1328 } 1329 if (exs != null) { 1330 Elements elements = controller.getElements(); 1331 for (TypeMirror ex : exs) 1332 if (ex.getKind() == TypeKind.DECLARED) { 1333 Element e = ((DeclaredType)ex).asElement(); 1334 if (e.getEnclosingElement() == el && Utilities.startsWith(e.getSimpleName().toString(), prefix)) 1335 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)ex, offset, true, elements.isDeprecated(e), true)); 1336 } 1337 } else { 1338 addPackageContent(env, (PackageElement)el, kinds, baseType); 1339 } 1340 } 1341 } 1342 } 1343 } 1344 } 1345 1346 private void insideMethodInvocation(Env env) throws IOException { 1347 MethodInvocationTree mi = (MethodInvocationTree)env.getPath().getLeaf(); 1348 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, mi, env.getOffset()); 1349 if (ts == null || (ts.token().id() != JavaTokenId.LPAREN && ts.token().id() != JavaTokenId.COMMA)) 1350 return; 1351 addLocalMembersAndVars(env); 1352 addValueKeywords(env); 1353 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1354 addPrimitiveTypeKeywords(env); 1355 } 1356 1357 private void insideNewClass(Env env) throws IOException { 1358 int offset = env.getOffset(); 1359 TreePath path = env.getPath(); 1360 NewClassTree nc = (NewClassTree)path.getLeaf(); 1361 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, nc, offset); 1362 if (ts != null) { 1363 switch(ts.token().id()) { 1364 case NEW: 1365 if (queryType == COMPLETION_QUERY_TYPE) { 1366 Set<? extends TypeMirror> smarts = env.getSmartTypes(); 1367 if (smarts != null) 1368 for (TypeMirror smart : smarts) { 1369 if (smart.getKind() == TypeKind.DECLARED) 1370 addSubtypesOf(env, (DeclaredType)smart, true); 1371 else if (smart.getKind() == TypeKind.ARRAY) 1372 results.add(JavaCompletionItem.createArrayItem((ArrayType)smart, offset, env.getController().getElements())); 1373 } 1374 } 1375 String prefix = env.getPrefix(); 1376 CompilationController controller = env.getController(); 1377 DeclaredType base = path.getParentPath().getLeaf().getKind() == Tree.Kind.THROW ? 1378 controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")) : null; if (nc.getIdentifier().getKind() == Tree.Kind.IDENTIFIER && prefix != null) { 1380 TypeMirror tm = controller.getTreeUtilities().parseType(prefix, env.getScope().getEnclosingClass()); 1381 if (tm != null && tm.getKind() == TypeKind.DECLARED) 1382 addMembers(env, tm, ((DeclaredType)tm).asElement(), EnumSet.of(CONSTRUCTOR), base, false); 1383 } 1384 addTypes(env, EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE), base, null); 1385 break; 1386 case LPAREN: 1387 case COMMA: 1388 addLocalMembersAndVars(env); 1389 addValueKeywords(env); 1390 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1391 addPrimitiveTypeKeywords(env); 1392 break; 1393 case GT: 1394 case GTGT: 1395 case GTGTGT: 1396 controller = env.getController(); 1397 TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, nc.getIdentifier())); 1398 addMembers(env, tm, ((DeclaredType)tm).asElement(), EnumSet.of(CONSTRUCTOR), null, false); 1399 break; 1400 } 1401 } 1402 } 1403 1404 private void insideCatch(Env env) throws IOException { 1405 int offset = env.getOffset(); 1406 TreePath path = env.getPath(); 1407 String prefix = env.getPrefix(); 1408 CatchTree ct = (CatchTree)path.getLeaf(); 1409 CompilationController controller = env.getController(); 1410 TokenSequence<JavaTokenId> last = findLastNonWhitespaceToken(env, ct, offset); 1411 if (last != null && last.token().id() == JavaTokenId.LPAREN) { 1412 if (queryType == COMPLETION_QUERY_TYPE) { 1413 Set<TypeMirror> exs = controller.getTreeUtilities().getUncaughtExceptions(path.getParentPath()); 1414 Elements elements = controller.getElements(); 1415 for (TypeMirror ex : exs) 1416 if (ex.getKind() == TypeKind.DECLARED && Utilities.startsWith(((DeclaredType)ex).asElement().getSimpleName().toString(), prefix)) 1417 results.add(JavaCompletionItem.createTypeItem((TypeElement)((DeclaredType)ex).asElement(), (DeclaredType)ex, offset, true, elements.isDeprecated(((DeclaredType)ex).asElement()), true)); 1418 } 1419 addTypes(env, EnumSet.of(CLASS, INTERFACE, TYPE_PARAMETER), controller.getTypes().getDeclaredType(controller.getElements().getTypeElement("java.lang.Throwable")), null); } 1421 } 1422 1423 private void insideIf(Env env) throws IOException { 1424 IfTree iff = (IfTree)env.getPath().getLeaf(); 1425 if (env.getSourcePositions().getEndPosition(env.getRoot(), iff.getCondition()) <= env.getOffset()) { 1426 localResult(env); 1427 addKeywordsForStatement(env); 1428 } 1429 } 1430 1431 private void insideWhile(Env env) throws IOException { 1432 WhileLoopTree wlt = (WhileLoopTree)env.getPath().getLeaf(); 1433 if (env.getSourcePositions().getEndPosition(env.getRoot(), wlt.getCondition()) <= env.getOffset()) { 1434 localResult(env); 1435 addKeywordsForStatement(env); 1436 } 1437 } 1438 1439 private void insideFor(Env env) throws IOException { 1440 int offset = env.getOffset(); 1441 TreePath path = env.getPath(); 1442 ForLoopTree fl = (ForLoopTree)path.getLeaf(); 1443 SourcePositions sourcePositions = env.getSourcePositions(); 1444 CompilationUnitTree root = env.getRoot(); 1445 Tree lastTree = null; 1446 int lastTreePos = offset; 1447 for (Tree update : fl.getUpdate()) { 1448 int pos = (int)sourcePositions.getEndPosition(root, update); 1449 if (pos == Diagnostic.NOPOS || offset <= pos) 1450 break; 1451 lastTree = update; 1452 lastTreePos = pos; 1453 } 1454 if (lastTree == null) { 1455 int pos = (int)sourcePositions.getEndPosition(root, fl.getCondition()); 1456 if (pos != Diagnostic.NOPOS && pos < offset) { 1457 lastTree = fl.getCondition(); 1458 lastTreePos = pos; 1459 } 1460 } 1461 if (lastTree == null) { 1462 for (Tree init : fl.getInitializer()) { 1463 int pos = (int)sourcePositions.getEndPosition(root, init); 1464 if (pos == Diagnostic.NOPOS || offset <= pos) 1465 break; 1466 lastTree = init; 1467 lastTreePos = pos; 1468 } 1469 } 1470 if (lastTree == null) { 1471 addLocalFieldsAndVars(env); 1472 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1473 addPrimitiveTypeKeywords(env); 1474 } else { 1475 String text = env.getController().getText().substring(lastTreePos, offset).trim(); 1476 if (";".equals(text)) { localResult(env); 1478 addValueKeywords(env); 1479 } else if (text.endsWith(")")) { localResult(env); 1481 addKeywordsForStatement(env); 1482 } else { 1483 switch (lastTree.getKind()) { 1484 case VARIABLE: 1485 Tree var = ((VariableTree)lastTree).getInitializer(); 1486 if (var != null) 1487 insideExpression(env, new TreePath(new TreePath(path, lastTree), var)); 1488 break; 1489 case EXPRESSION_STATEMENT: 1490 Tree exp = unwrapErrTree(((ExpressionStatementTree)lastTree).getExpression()); 1491 if (exp != null) 1492 insideExpression(env, new TreePath(new TreePath(path, lastTree), exp)); 1493 break; 1494 default: 1495 insideExpression(env, new TreePath(path, lastTree)); 1496 } 1497 } 1498 } 1499 } 1500 1501 private void insideForEach(Env env) throws IOException { 1502 int offset = env.getOffset(); 1503 TreePath path = env.getPath(); 1504 EnhancedForLoopTree efl = (EnhancedForLoopTree)path.getLeaf(); 1505 SourcePositions sourcePositions = env.getSourcePositions(); 1506 CompilationUnitTree root = env.getRoot(); 1507 CompilationController controller = env.getController(); 1508 if (sourcePositions.getStartPosition(root, efl.getExpression()) >= offset) { 1509 if (":".equals(controller.getText().substring((int)sourcePositions.getEndPosition(root, efl.getVariable()), offset).trim())) { env.insideForEachExpressiion(); 1511 addKeyword(env, NEW_KEYWORD, SPACE, false); 1512 localResult(env); 1513 } 1514 return; 1515 } 1516 if (controller.getText().substring((int)sourcePositions.getEndPosition(root, efl.getExpression()), offset).trim().endsWith(")")) { addKeywordsForStatement(env); 1518 } else { 1519 env.insideForEachExpressiion(); 1520 addKeyword(env, NEW_KEYWORD, SPACE, false); 1521 } 1522 localResult(env); 1523 1524 } 1525 1526 private void insideSwitch(Env env) throws IOException { 1527 int offset = env.getOffset(); 1528 String prefix = env.getPrefix(); 1529 TreePath path = env.getPath(); 1530 SwitchTree st = (SwitchTree)path.getLeaf(); 1531 SourcePositions sourcePositions = env.getSourcePositions(); 1532 CompilationUnitTree root = env.getRoot(); 1533 if (sourcePositions.getStartPosition(root, st.getExpression()) < offset) { 1534 CaseTree lastCase = null; 1535 for (CaseTree t : st.getCases()) { 1536 int pos = (int)sourcePositions.getStartPosition(root, t); 1537 if (pos == Diagnostic.NOPOS || offset <= pos) 1538 break; 1539 lastCase = t; 1540 } 1541 if (lastCase != null) { 1542 localResult(env); 1543 addKeywordsForBlock(env); 1544 } else { 1545 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, st, offset); 1546 if (ts != null && ts.token().id() == JavaTokenId.LBRACE) { 1547 addKeyword(env, CASE_KEYWORD, SPACE, false); 1548 addKeyword(env, DEFAULT_KEYWORD, COLON, false); 1549 } 1550 } 1551 } 1552 } 1553 1554 private void insideCase(Env env) throws IOException { 1555 int offset = env.getOffset(); 1556 TreePath path = env.getPath(); 1557 CaseTree cst = (CaseTree)path.getLeaf(); 1558 SourcePositions sourcePositions = env.getSourcePositions(); 1559 CompilationUnitTree root = env.getRoot(); 1560 CompilationController controller = env.getController(); 1561 if (cst.getExpression() != null && ((sourcePositions.getStartPosition(root, cst.getExpression()) >= offset) || 1562 (cst.getExpression().getKind() == Tree.Kind.ERRONEOUS && ((ErroneousTree)cst.getExpression()).getErrorTrees().isEmpty() && sourcePositions.getEndPosition(root, cst.getExpression()) >= offset))) { 1563 TreePath path1 = path.getParentPath(); 1564 if (path1.getLeaf().getKind() == Tree.Kind.SWITCH) { 1565 TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path1, ((SwitchTree)path1.getLeaf()).getExpression())); 1566 if (tm.getKind() == TypeKind.DECLARED && ((DeclaredType)tm).asElement().getKind() == ENUM) { 1567 addEnumConstants(env, (TypeElement)((DeclaredType)tm).asElement()); 1568 } else { 1569 addLocalConstantsAndTypes(env); 1570 } 1571 } 1572 } else { 1573 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, cst, offset); 1574 if (ts != null && ts.token().id() == JavaTokenId.COLON) { 1575 localResult(env); 1576 addKeywordsForBlock(env); 1577 } 1578 } 1579 } 1580 1581 private void insideParens(Env env) throws IOException { 1582 TreePath path = env.getPath(); 1583 ParenthesizedTree pa = (ParenthesizedTree)path.getLeaf(); 1584 SourcePositions sourcePositions = env.getSourcePositions(); 1585 CompilationUnitTree root = env.getRoot(); 1586 Tree exp = unwrapErrTree(pa.getExpression()); 1587 if (exp == null || env.getOffset() <= sourcePositions.getStartPosition(root, exp)) { 1588 localResult(env); 1589 addValueKeywords(env); 1590 } else { 1591 insideExpression(env, new TreePath(path, exp)); 1592 } 1593 } 1594 1595 private void insideTypeCheck(Env env) throws IOException { 1596 InstanceOfTree iot = (InstanceOfTree)env.getPath().getLeaf(); 1597 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, iot, env.getOffset()); 1598 if (ts != null && ts.token().id() == JavaTokenId.INSTANCEOF) 1599 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 1600 } 1601 1602 private void insideArrayAccess(Env env) throws IOException { 1603 int offset = env.getOffset(); 1604 ArrayAccessTree aat = (ArrayAccessTree)env.getPath().getLeaf(); 1605 SourcePositions sourcePositions = env.getSourcePositions(); 1606 CompilationUnitTree root = env.getRoot(); 1607 int aaTextStart = (int)sourcePositions.getEndPosition(root, aat.getExpression()); 1608 if (aaTextStart != Diagnostic.NOPOS) { 1609 Tree expr = unwrapErrTree(aat.getIndex()); 1610 if (expr == null || offset <= (int)sourcePositions.getStartPosition(root, expr)) { 1611 String aatText = env.getController().getText().substring(aaTextStart, offset); 1612 int bPos = aatText.indexOf('['); if (bPos > -1) { 1614 localResult(env); 1615 addValueKeywords(env); 1616 } 1617 } 1618 } 1619 } 1620 1621 private void insideNewArray(Env env) throws IOException { 1622 int offset = env.getOffset(); 1623 TreePath path = env.getPath(); 1624 NewArrayTree nat = (NewArrayTree)path.getLeaf(); 1625 if (nat.getInitializers() != null) { SourcePositions sourcePositions = env.getSourcePositions(); 1627 CompilationUnitTree root = env.getRoot(); 1628 Tree last = null; 1629 int lastPos = offset; 1630 for (Tree init : nat.getInitializers()) { 1631 int pos = (int)sourcePositions.getEndPosition(root, init); 1632 if (pos == Diagnostic.NOPOS || offset <= pos) 1633 break; 1634 last = init; 1635 lastPos = pos; 1636 } 1637 if (last != null) { 1638 String text = env.getController().getText().substring(lastPos, offset).trim(); 1639 if (",".equals(text)) { TreePath parentPath = path.getParentPath(); 1641 TreePath gparentPath = parentPath.getParentPath(); 1642 if (parentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION || gparentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION) { 1643 addLocalConstantsAndTypes(env); 1644 } else { 1645 localResult(env); 1646 addValueKeywords(env); 1647 } 1648 } 1649 return; 1650 } 1651 } 1652 TokenSequence<JavaTokenId> ts = findLastNonWhitespaceToken(env, nat, offset); 1653 switch (ts.token().id()) { 1654 case LBRACKET: 1655 case LBRACE: 1656 TreePath parentPath = path.getParentPath(); 1657 TreePath gparentPath = parentPath.getParentPath(); 1658 if (parentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION || gparentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION) { 1659 addLocalConstantsAndTypes(env); 1660 } else { 1661 localResult(env); 1662 addValueKeywords(env); 1663 } 1664 break; 1665 case RBRACKET: 1666 if (nat.getDimensions().size() > 0) 1667 insideExpression(env, path); 1668 break; 1669 } 1670 } 1671 1672 private void insideAssignment(Env env) throws IOException { 1673 int offset = env.getOffset(); 1674 TreePath path = env.getPath(); 1675 AssignmentTree as = (AssignmentTree)path.getLeaf(); 1676 SourcePositions sourcePositions = env.getSourcePositions(); 1677 CompilationUnitTree root = env.getRoot(); 1678 int asTextStart = (int)sourcePositions.getEndPosition(root, as.getVariable()); 1679 if (asTextStart != Diagnostic.NOPOS) { 1680 Tree expr = unwrapErrTree(as.getExpression()); 1681 if (expr == null || offset <= (int)sourcePositions.getStartPosition(root, expr)) { 1682 String asText = env.getController().getText().substring(asTextStart, offset); 1683 int eqPos = asText.indexOf('='); if (eqPos > -1) { 1685 if (path.getParentPath().getLeaf().getKind() == Tree.Kind.ANNOTATION) { 1686 addLocalConstantsAndTypes(env); 1687 } else { 1688 localResult(env); 1689 addValueKeywords(env); 1690 } 1691 } 1692 } else { 1693 insideExpression(env, new TreePath(path, expr)); 1694 } 1695 } 1696 } 1697 1698 private void insideCompoundAssignment(Env env) throws IOException { 1699 int offset = env.getOffset(); 1700 CompoundAssignmentTree cat = (CompoundAssignmentTree)env.getPath().getLeaf(); 1701 SourcePositions sourcePositions = env.getSourcePositions(); 1702 CompilationUnitTree root = env.getRoot(); 1703 int catTextStart = (int)sourcePositions.getEndPosition(root, cat.getVariable()); 1704 if (catTextStart != Diagnostic.NOPOS) { 1705 Tree expr = unwrapErrTree(cat.getExpression()); 1706 if (expr == null || offset <= (int)sourcePositions.getStartPosition(root, expr)) { 1707 String catText = env.getController().getText().substring(catTextStart, offset); 1708 int eqPos = catText.indexOf('='); if (eqPos > -1) { 1710 localResult(env); 1711 addValueKeywords(env); 1712 } 1713 } 1714 } 1715 } 1716 1717 private void insideBinaryTree(Env env) throws IOException { 1718 int offset = env.getOffset(); 1719 BinaryTree bi = (BinaryTree)env.getPath().getLeaf(); 1720 SourcePositions sourcePositions = env.getSourcePositions(); 1721 CompilationUnitTree root = env.getRoot(); 1722 int pos = (int)sourcePositions.getEndPosition(root, bi.getRightOperand()); 1723 if (pos != Diagnostic.NOPOS && pos < offset) 1724 return; 1725 pos = (int)sourcePositions.getEndPosition(root, bi.getLeftOperand()); 1726 if (pos != Diagnostic.NOPOS) { 1727 String biText = env.getController().getText().substring(pos, offset).trim(); 1728 if (biText.length() > 0) { 1729 localResult(env); 1730 addValueKeywords(env); 1731 } 1732 } 1733 } 1734 1735 private void insideConditionalExpression(Env env) throws IOException { 1736 ConditionalExpressionTree co = (ConditionalExpressionTree)env.getPath().getLeaf(); 1737 SourcePositions sourcePositions = env.getSourcePositions(); 1738 CompilationUnitTree root = env.getRoot(); 1739 int coTextStart = (int)sourcePositions.getStartPosition(root, co); 1740 if (coTextStart != Diagnostic.NOPOS) { 1741 String coText = env.getController().getText().substring(coTextStart, env.getOffset()).trim(); 1742 if (coText.endsWith("?") || coText.endsWith(":")) { localResult(env); 1744 addValueKeywords(env); 1745 } 1746 } 1747 } 1748 1749 private void insideExpressionStatement(Env env) throws IOException { 1750 TreePath path = env.getPath(); 1751 ExpressionStatementTree est = (ExpressionStatementTree)path.getLeaf(); 1752 CompilationController controller = env.getController(); 1753 Tree t = est.getExpression(); 1754 if (t.getKind() == Tree.Kind.ERRONEOUS) { 1755 Iterator<? extends Tree> it = ((ErroneousTree)t).getErrorTrees().iterator(); 1756 if (it.hasNext()) { 1757 t = it.next(); 1758 } else { 1759 TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language()); 1760 ts.move((int)env.getSourcePositions().getStartPosition(env.getRoot(), est)); 1761 ts.movePrevious(); 1762 switch (ts.token().id()) { 1763 case FOR: 1764 case IF: 1765 case SWITCH: 1766 case WHILE: 1767 return; 1768 } 1769 localResult(env); 1770 Tree parentTree = path.getParentPath().getLeaf(); 1771 switch (parentTree.getKind()) { 1772 case FOR_LOOP: 1773 if (((ForLoopTree)parentTree).getStatement() == est) 1774 addKeywordsForStatement(env); 1775 else 1776 addValueKeywords(env); 1777 break; 1778 case ENHANCED_FOR_LOOP: 1779 if (((EnhancedForLoopTree)parentTree).getStatement() == est) 1780 addKeywordsForStatement(env); 1781 else 1782 addValueKeywords(env); 1783 break; 1784 case VARIABLE: 1785 addValueKeywords(env); 1786 break; 1787 default: 1788 addKeywordsForStatement(env); 1789 break; 1790 } 1791 return; 1792 } 1793 } 1794 TreePath tPath = new TreePath(path, t); 1795 if (t.getKind() == Tree.Kind.MODIFIERS) { 1796 insideModifiers(env, tPath); 1797 } else if (t.getKind() == Tree.Kind.MEMBER_SELECT && ERROR.contentEquals(((MemberSelectTree)t).getIdentifier())) { 1798 controller.toPhase(Phase.ELEMENTS_RESOLVED); 1799 TreePath expPath = new TreePath(tPath, ((MemberSelectTree)t).getExpression()); 1800 TypeMirror type = controller.getTrees().getTypeMirror(expPath); 1801 switch (type.getKind()) { 1802 case TYPEVAR: 1803 type = ((TypeVariable)type).getUpperBound(); 1804 if (type == null) 1805 return; 1806 type = controller.getTypes().capture(type); 1807 case ARRAY: 1808 case DECLARED: 1809 case BOOLEAN: 1810 case BYTE: 1811 case CHAR: 1812 case DOUBLE: 1813 case FLOAT: 1814 case INT: 1815 case LONG: 1816 case SHORT: 1817 case VOID: 1818 addMembers(env, type, controller.getTrees().getElement(expPath), EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT), null, false); 1819 break; 1820 default: 1821 Element el = controller.getTrees().getElement(expPath); 1822 if (el instanceof PackageElement) { 1823 addPackageContent(env, (PackageElement)el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, FIELD, METHOD, ENUM_CONSTANT), null); 1824 } 1825 } 1826 } else { 1827 insideExpression(env, tPath); 1828 } 1829 1830 } 1831 1832 private void insideExpression(Env env, TreePath exPath) throws IOException { 1833 int offset = env.getOffset(); 1834 String prefix = env.getPrefix(); 1835 Tree et = exPath.getLeaf(); 1836 Tree parent = exPath.getParentPath().getLeaf(); 1837 CompilationController controller = env.getController(); 1838 int endPos = (int)env.getSourcePositions().getEndPosition(env.getRoot(), et); 1839 if (endPos != Diagnostic.NOPOS && endPos < offset) { 1840 if (controller.getText().substring(endPos, offset).trim().length() > 0) 1841 return; 1842 } 1843 controller.toPhase(Phase.ELEMENTS_RESOLVED); 1844 boolean isConst = parent.getKind() == Tree.Kind.VARIABLE && ((VariableTree)parent).getModifiers().getFlags().containsAll(EnumSet.of(FINAL, STATIC)); 1845 if ((parent == null || parent.getKind() != Tree.Kind.PARENTHESIZED) && 1846 (et.getKind() == Tree.Kind.PRIMITIVE_TYPE || et.getKind() == Tree.Kind.ARRAY_TYPE || et.getKind() == Tree.Kind.PARAMETERIZED_TYPE)) { 1847 TypeMirror tm = controller.getTrees().getTypeMirror(exPath); 1848 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 1849 Scope scope = env.getScope(); 1850 final ExecutableElement method = scope.getEnclosingMethod(); 1851 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 1852 public boolean accept(Element e, TypeMirror t) { 1853 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 1854 !illegalForwardRefs.contains(e); 1855 } 1856 }; 1857 for (String name : Utilities.varNamesSuggestions(tm, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalVars(scope, acceptor), isConst)) 1858 results.add(JavaCompletionItem.createVariableItem(name, offset, false)); 1859 return; 1860 } 1861 if (et.getKind() == Tree.Kind.IDENTIFIER) { 1862 Element e = controller.getTrees().getElement(exPath); 1863 if (e == null) 1864 return; 1865 TypeMirror tm = controller.getTrees().getTypeMirror(exPath); 1866 switch (e.getKind()) { 1867 case ANNOTATION_TYPE: 1868 case CLASS: 1869 case ENUM: 1870 case INTERFACE: 1871 case PACKAGE: 1872 if (parent == null || parent.getKind() != Tree.Kind.PARENTHESIZED) { 1873 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 1874 Scope scope = env.getScope(); 1875 final ExecutableElement method = scope.getEnclosingMethod(); 1876 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 1877 public boolean accept(Element e, TypeMirror t) { 1878 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 1879 !illegalForwardRefs.contains(e); 1880 } 1881 }; 1882 for (String name : Utilities.varNamesSuggestions(tm, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalVars(scope, acceptor), isConst)) 1883 results.add(JavaCompletionItem.createVariableItem(name, offset, false)); 1884 } 1885 VariableElement ve = getFieldOrVar(env, e.getSimpleName().toString()); 1886 if (ve != null) { 1887 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1888 } 1889 break; 1890 case ENUM_CONSTANT: 1891 case EXCEPTION_PARAMETER: 1892 case FIELD: 1893 case LOCAL_VARIABLE: 1894 case PARAMETER: 1895 if (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR) { 1896 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1897 } 1898 TypeElement te = getTypeElement(env, e.getSimpleName().toString()); 1899 if (te != null) { 1900 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 1901 Scope scope = env.getScope(); 1902 final ExecutableElement method = scope.getEnclosingMethod(); 1903 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 1904 public boolean accept(Element e, TypeMirror t) { 1905 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 1906 !illegalForwardRefs.contains(e); 1907 } 1908 }; 1909 for (String name : Utilities.varNamesSuggestions(controller.getTypes().getDeclaredType(te), prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalVars(scope, acceptor), isConst)) 1910 results.add(JavaCompletionItem.createVariableItem(name, offset, false)); 1911 } 1912 break; 1913 } 1914 return; 1915 } 1916 Tree exp = null; 1917 if (et.getKind() == Tree.Kind.PARENTHESIZED) { 1918 exp = ((ParenthesizedTree)et).getExpression(); 1919 } else if (et.getKind() == Tree.Kind.TYPE_CAST) { 1920 if(env.getSourcePositions().getEndPosition(env.getRoot(), et) > offset || 1921 ((TypeCastTree)et).getExpression().getKind() == Tree.Kind.IDENTIFIER) 1922 exp = ((TypeCastTree)et).getType(); 1923 } else if (et.getKind() == Tree.Kind.ASSIGNMENT) { 1924 Tree t = ((AssignmentTree)et).getExpression(); 1925 if (t.getKind() == Tree.Kind.PARENTHESIZED && env.getSourcePositions().getEndPosition(env.getRoot(), t) < offset) 1926 exp = ((ParenthesizedTree)t).getExpression(); 1927 } 1928 if (exp != null) { 1929 exPath = new TreePath(exPath, exp); 1930 if (exp.getKind() == Tree.Kind.PRIMITIVE_TYPE || et.getKind() == Tree.Kind.ARRAY_TYPE || et.getKind() == Tree.Kind.PARAMETERIZED_TYPE) { 1931 localResult(env); 1932 addValueKeywords(env); 1933 return; 1934 } 1935 Element e = controller.getTrees().getElement(exPath); 1936 if (e == null) { 1937 if (exp.getKind() == Tree.Kind.TYPE_CAST) { 1938 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1939 } 1940 return; 1941 } 1942 TypeMirror tm = controller.getTrees().getTypeMirror(exPath); 1943 switch (e.getKind()) { 1944 case ANNOTATION_TYPE: 1945 case CLASS: 1946 case ENUM: 1947 case INTERFACE: 1948 case PACKAGE: 1949 if (exp.getKind() == Tree.Kind.IDENTIFIER) { 1950 VariableElement ve = getFieldOrVar(env, e.getSimpleName().toString()); 1951 if (ve != null) { 1952 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1953 } 1954 if (ve == null || tm.getKind() != TypeKind.ERROR) { 1955 localResult(env); 1956 addValueKeywords(env); 1957 } 1958 } else if (exp.getKind() == Tree.Kind.MEMBER_SELECT) { 1959 if (tm.getKind() == TypeKind.ERROR || tm.getKind() == TypeKind.PACKAGE) { 1960 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1961 } 1962 localResult(env); 1963 addValueKeywords(env); 1964 } else if (exp.getKind() == Tree.Kind.PARENTHESIZED && (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY)) { 1965 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1966 } 1967 break; 1968 case ENUM_CONSTANT: 1969 case EXCEPTION_PARAMETER: 1970 case FIELD: 1971 case LOCAL_VARIABLE: 1972 case PARAMETER: 1973 if (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR) { 1974 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1975 } 1976 TypeElement te = getTypeElement(env, e.getSimpleName().toString()); 1977 if (te != null || exp.getKind() == Tree.Kind.MEMBER_SELECT) { 1978 localResult(env); 1979 addValueKeywords(env); 1980 } 1981 break; 1982 case CONSTRUCTOR: 1983 case METHOD: 1984 if (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR) { 1985 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1986 } 1987 } 1988 return; 1989 } 1990 Element e = controller.getTrees().getElement(exPath); 1991 TypeMirror tm = controller.getTrees().getTypeMirror(exPath); 1992 if (e == null) { 1993 if (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR) { 1994 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 1995 } 1996 return; 1997 } 1998 switch (e.getKind()) { 1999 case ANNOTATION_TYPE: 2000 case CLASS: 2001 case ENUM: 2002 case INTERFACE: 2003 case PACKAGE: 2004 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 2005 Scope scope = env.getScope(); 2006 final ExecutableElement method = scope.getEnclosingMethod(); 2007 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2008 public boolean accept(Element e, TypeMirror t) { 2009 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 2010 !illegalForwardRefs.contains(e); 2011 } 2012 }; 2013 for (String name : Utilities.varNamesSuggestions(tm, prefix, controller.getTypes(), controller.getElements(), controller.getElementUtilities().getLocalVars(scope, acceptor), isConst)) 2014 results.add(JavaCompletionItem.createVariableItem(name, offset, false)); 2015 if (et.getKind() == Tree.Kind.MEMBER_SELECT && tm.getKind() == TypeKind.ERROR) { 2016 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 2017 } 2018 break; 2019 case ENUM_CONSTANT: 2020 case EXCEPTION_PARAMETER: 2021 case FIELD: 2022 case LOCAL_VARIABLE: 2023 case PARAMETER: 2024 case CONSTRUCTOR: 2025 case METHOD: 2026 if (tm.getKind() == TypeKind.DECLARED || tm.getKind() == TypeKind.ARRAY || tm.getKind() == TypeKind.ERROR) { 2027 addKeyword(env, INSTANCEOF_KEYWORD, SPACE, false); 2028 } 2029 } 2030 } 2031 2032 private void localResult(Env env) throws IOException { 2033 addLocalMembersAndVars(env); 2034 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 2035 addPrimitiveTypeKeywords(env); 2036 } 2037 2038 private void addLocalConstantsAndTypes(final Env env) throws IOException { 2039 int offset = env.getOffset(); 2040 final String prefix = env.getPrefix(); 2041 final CompilationController controller = env.getController(); 2042 final Elements elements = controller.getElements(); 2043 final Types types = controller.getTypes(); 2044 final TreeUtilities tu = controller.getTreeUtilities(); 2045 final Scope scope = env.getScope(); 2046 Set<? extends TypeMirror> smartTypes = null; 2047 boolean smartType = false; 2048 if (queryType == COMPLETION_QUERY_TYPE) { 2049 smartTypes = env.getSmartTypes(); 2050 if (smartTypes != null) { 2051 for (TypeMirror st : smartTypes) { 2052 if (st.getKind() == TypeKind.BOOLEAN) { 2053 smartType = true; 2054 } 2055 if (st.getKind().isPrimitive()) 2056 st = types.boxedClass((PrimitiveType)st).asType(); 2057 if (st.getKind() == TypeKind.DECLARED) { 2058 final DeclaredType type = (DeclaredType)st; 2059 final TypeElement element = (TypeElement)type.asElement(); 2060 if (element.getKind() == ANNOTATION_TYPE) 2061 results.add(JavaCompletionItem.createAnnotationItem(element, (DeclaredType)type, anchorOffset, elements.isDeprecated(element))); 2062 final boolean isStatic = element.getKind().isClass() || element.getKind().isInterface(); 2063 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2064 public boolean accept(Element e, TypeMirror t) { 2065 return (e.getKind() == ENUM_CONSTANT || e.getKind() == FIELD && ((VariableElement)e).getConstantValue() != null) && 2066 (!isStatic || e.getModifiers().contains(STATIC)) && 2067 Utilities.startsWith(e.getEnclosingElement().getSimpleName() + "." + e.getSimpleName(), prefix) && 2068 tu.isAccessible(scope, e, t) && 2069 types.isAssignable(((VariableElement)e).asType(), type); 2070 } 2071 }; 2072 for (Element ee : controller.getElementUtilities().getMembers(type, acceptor)) { 2073 results.add(JavaCompletionItem.createStaticMemberItem(type, ee, types.asMemberOf(type, ee), offset, elements.isDeprecated(ee))); 2074 } 2075 } 2076 } 2077 } 2078 } 2079 if (env.getPath().getLeaf().getKind() != Tree.Kind.CASE) { 2080 if (Utilities.startsWith(FALSE_KEYWORD, prefix)) 2081 results.add(JavaCompletionItem.createKeywordItem(FALSE_KEYWORD, null, offset, smartType)); 2082 if (Utilities.startsWith(TRUE_KEYWORD, prefix)) 2083 results.add(JavaCompletionItem.createKeywordItem(TRUE_KEYWORD, null, offset, smartType)); 2084 } 2085 final TypeElement enclClass = scope.getEnclosingClass(); 2086 final boolean isStatic = enclClass == null ? false : 2087 (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2088 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 2089 final ExecutableElement method = scope.getEnclosingMethod(); 2090 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2091 public boolean accept(Element e, TypeMirror t) { 2092 switch (e.getKind()) { 2093 case LOCAL_VARIABLE: 2094 case EXCEPTION_PARAMETER: 2095 case PARAMETER: 2096 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL) || 2097 (method == null && (e.getEnclosingElement().getKind() == INSTANCE_INIT || 2098 e.getEnclosingElement().getKind() == STATIC_INIT))) && 2099 !illegalForwardRefs.contains(e) && 2100 ((VariableElement)e).getConstantValue() != null; 2101 case FIELD: 2102 if (illegalForwardRefs.contains(e) || ((VariableElement)e).getConstantValue() == null) 2103 return false; 2104 case ENUM_CONSTANT: 2105 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2106 (!isStatic || e.getModifiers().contains(STATIC)) && 2107 tu.isAccessible(scope, e, t); 2108 } 2109 return false; 2110 } 2111 }; 2112 for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) 2113 if (e.getKind() == FIELD) { 2114 TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types); 2115 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, tm, offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes))); 2116 } else { 2117 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, e.asType(), offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes))); 2118 } 2119 addTypes(env, EnumSet.of(CLASS, INTERFACE, ENUM, ANNOTATION_TYPE, TYPE_PARAMETER), null, null); 2120 } 2121 2122 private void addLocalMembersAndVars(final Env env) throws IOException { 2123 int offset = env.getOffset(); 2124 final String prefix = env.getPrefix(); 2125 final CompilationController controller = env.getController(); 2126 final Elements elements = controller.getElements(); 2127 final Types types = controller.getTypes(); 2128 final TreeUtilities tu = controller.getTreeUtilities(); 2129 final Scope scope = env.getScope(); 2130 Set<? extends TypeMirror> smartTypes = null; 2131 if (queryType == COMPLETION_QUERY_TYPE) { 2132 smartTypes = env.getSmartTypes(); 2133 if (smartTypes != null) { 2134 for (TypeMirror st : smartTypes) { 2135 if (st.getKind().isPrimitive()) 2136 st = types.boxedClass((PrimitiveType)st).asType(); 2137 if (st.getKind() == TypeKind.DECLARED) { 2138 final DeclaredType type = (DeclaredType)st; 2139 final TypeElement element = (TypeElement)type.asElement(); 2140 if (withinScope(env, element)) 2141 continue; 2142 final boolean isStatic = element.getKind().isClass() || element.getKind().isInterface(); 2143 final Set<? extends TypeMirror> finalSmartTypes = smartTypes; 2144 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2145 public boolean accept(Element e, TypeMirror t) { 2146 return (!isStatic || e.getModifiers().contains(STATIC)) && 2147 Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2148 tu.isAccessible(scope, e, t) && 2149 (e.getKind().isField() && isOfSmartType(env, ((VariableElement)e).asType(), finalSmartTypes) || e.getKind() == METHOD && isOfSmartType(env, ((ExecutableElement)e).getReturnType(), finalSmartTypes)); 2150 } 2151 }; 2152 for (Element ee : controller.getElementUtilities().getMembers(type, acceptor)) { 2153 results.add(JavaCompletionItem.createStaticMemberItem(type, ee, types.asMemberOf(type, ee), offset, elements.isDeprecated(ee))); 2154 } 2155 } 2156 } 2157 } 2158 } 2159 final TypeElement enclClass = scope.getEnclosingClass(); 2160 final boolean isStatic = enclClass == null ? false : 2161 (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2162 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 2163 final ExecutableElement method = scope.getEnclosingMethod(); 2164 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2165 public boolean accept(Element e, TypeMirror t) { 2166 switch (e.getKind()) { 2167 case CONSTRUCTOR: 2168 return false; 2169 case LOCAL_VARIABLE: 2170 case EXCEPTION_PARAMETER: 2171 case PARAMETER: 2172 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2173 (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL) || 2174 (method == null && (e.getEnclosingElement().getKind() == INSTANCE_INIT || 2175 e.getEnclosingElement().getKind() == STATIC_INIT))) && 2176 !illegalForwardRefs.contains(e); 2177 case FIELD: 2178 if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) 2179 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && !isStatic; 2180 case ENUM_CONSTANT: 2181 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2182 !illegalForwardRefs.contains(e) && 2183 (!isStatic || e.getModifiers().contains(STATIC)) && 2184 tu.isAccessible(scope, e, t); 2185 case METHOD: 2186 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2187 (!isStatic || e.getModifiers().contains(STATIC)) && 2188 tu.isAccessible(scope, e, t); 2189 } 2190 return false; 2191 } 2192 }; 2193 for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) { 2194 switch (e.getKind()) { 2195 case ENUM_CONSTANT: 2196 case EXCEPTION_PARAMETER: 2197 case LOCAL_VARIABLE: 2198 case PARAMETER: 2199 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, e.asType(), offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes))); 2200 break; 2201 case FIELD: 2202 String name = e.getSimpleName().toString(); 2203 if (THIS_KEYWORD.equals(name) || SUPER_KEYWORD.equals(name)) { 2204 results.add(JavaCompletionItem.createKeywordItem(name, null, offset, false)); 2205 } else { 2206 TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types); 2207 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, tm, offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes))); 2208 } 2209 break; 2210 case METHOD: 2211 ExecutableType et = (ExecutableType)asMemberOf(e, enclClass != null ? enclClass.asType() : null, types); 2212 results.add(JavaCompletionItem.createExecutableItem((ExecutableElement)e, et, offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), false, isOfSmartType(env, et.getReturnType(), smartTypes))); 2213 break; 2214 } 2215 } 2216 } 2217 2218 private void addLocalFieldsAndVars(final Env env) throws IOException { 2219 int offset = env.getOffset(); 2220 final String prefix = env.getPrefix(); 2221 final CompilationController controller = env.getController(); 2222 final Elements elements = controller.getElements(); 2223 final Types types = controller.getTypes(); 2224 final TreeUtilities tu = controller.getTreeUtilities(); 2225 final Scope scope = env.getScope(); 2226 Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null; 2227 final TypeElement enclClass = scope.getEnclosingClass(); 2228 final boolean isStatic = enclClass == null ? false : 2229 (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2230 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 2231 final ExecutableElement method = scope.getEnclosingMethod(); 2232 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2233 public boolean accept(Element e, TypeMirror t) { 2234 switch (e.getKind()) { 2235 case LOCAL_VARIABLE: 2236 case EXCEPTION_PARAMETER: 2237 case PARAMETER: 2238 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2239 (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL) || 2240 (method == null && (e.getEnclosingElement().getKind() == INSTANCE_INIT || 2241 e.getEnclosingElement().getKind() == STATIC_INIT))) && 2242 !illegalForwardRefs.contains(e); 2243 case FIELD: 2244 return !e.getSimpleName().contentEquals(THIS_KEYWORD) && !e.getSimpleName().contentEquals(SUPER_KEYWORD) && 2245 !isStatic && Utilities.startsWith(e.getSimpleName().toString(), prefix); 2246 } 2247 return false; 2248 } 2249 }; 2250 for (Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) { 2251 switch (e.getKind()) { 2252 case ENUM_CONSTANT: 2253 case EXCEPTION_PARAMETER: 2254 case LOCAL_VARIABLE: 2255 case PARAMETER: 2256 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, e.asType(), offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes))); 2257 break; 2258 case FIELD: 2259 TypeMirror tm = asMemberOf(e, enclClass != null ? enclClass.asType() : null, types); 2260 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, tm, offset, env.getScope().getEnclosingClass() != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes))); 2261 break; 2262 } 2263 } 2264 } 2265 2266 private void addMemberConstantsAndTypes(final Env env, final TypeMirror type, final Element elem) throws IOException { 2267 Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null; 2268 int offset = env.getOffset(); 2269 final String prefix = env.getPrefix(); 2270 final CompilationController controller = env.getController(); 2271 final Elements elements = controller.getElements(); 2272 final Types types = controller.getTypes(); 2273 final TreeUtilities tu = controller.getTreeUtilities(); 2274 TypeElement typeElem = type.getKind() == TypeKind.DECLARED ? (TypeElement)((DeclaredType)type).asElement() : null; 2275 final boolean isStatic = elem != null && (elem.getKind().isClass() || elem.getKind().isInterface() || elem.getKind() == TYPE_PARAMETER); 2276 final boolean isSuperCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(SUPER_KEYWORD); 2277 final Scope scope = env.getScope(); 2278 TypeElement enclClass = scope.getEnclosingClass(); 2279 final TypeMirror enclType = enclClass != null ? enclClass.asType() : null; 2280 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2281 public boolean accept(Element e, TypeMirror t) { 2282 if (!Utilities.startsWith(e.getSimpleName().toString(), prefix) || 2283 (isStatic && !e.getModifiers().contains(STATIC))) 2284 return false; 2285 switch (e.getKind()) { 2286 case FIELD: 2287 if (((VariableElement)e).getConstantValue() == null && !CLASS_KEYWORD.contentEquals(e.getSimpleName())) 2288 return false; 2289 case ENUM_CONSTANT: 2290 return tu.isAccessible(scope, e, isSuperCall && enclType != null ? enclType : t); 2291 case CLASS: 2292 case ENUM: 2293 case INTERFACE: 2294 return tu.isAccessible(scope, e, t); 2295 } 2296 return false; 2297 } 2298 }; 2299 for(Element e : controller.getElementUtilities().getMembers(type, acceptor)) { 2300 switch (e.getKind()) { 2301 case FIELD: 2302 case ENUM_CONSTANT: 2303 String name = e.getSimpleName().toString(); 2304 if (CLASS_KEYWORD.equals(name)) { 2305 results.add(JavaCompletionItem.createKeywordItem(name, null, offset, false)); 2306 } else { 2307 TypeMirror tm = type.getKind() == TypeKind.DECLARED ? types.asMemberOf((DeclaredType)type, e) : e.asType(); 2308 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, tm, offset, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes))); 2309 } 2310 break; 2311 case CLASS: 2312 case ENUM: 2313 case INTERFACE: 2314 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)e.asType(), offset, false, elements.isDeprecated(e), false)); 2315 break; 2316 } 2317 } 2318 } 2319 2320 private void addMembers(final Env env, final TypeMirror type, final Element elem, final EnumSet<ElementKind> kinds, final DeclaredType baseType, final boolean inImport) throws IOException { 2321 Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null; 2322 int offset = env.getOffset(); 2323 final String prefix = env.getPrefix(); 2324 final CompilationController controller = env.getController(); 2325 final Trees trees = controller.getTrees(); 2326 final Elements elements = controller.getElements(); 2327 final Types types = controller.getTypes(); 2328 final TreeUtilities tu = controller.getTreeUtilities(); 2329 TypeElement typeElem = type.getKind() == TypeKind.DECLARED ? (TypeElement)((DeclaredType)type).asElement() : null; 2330 final boolean isStatic = elem != null && (elem.getKind().isClass() || elem.getKind().isInterface() || elem.getKind() == TYPE_PARAMETER); 2331 final boolean isSuperCall = elem != null && elem.getKind().isField() && elem.getSimpleName().contentEquals(SUPER_KEYWORD); 2332 final Scope scope = env.getScope(); 2333 final boolean[] ctorSeen = {false}; 2334 TypeElement enclClass = scope.getEnclosingClass(); 2335 final TypeMirror enclType = enclClass != null ? enclClass.asType() : null; 2336 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2337 public boolean accept(Element e, TypeMirror t) { 2338 switch (e.getKind()) { 2339 case FIELD: 2340 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2341 isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types) && 2342 tu.isAccessible(scope, e, isSuperCall && enclType != null ? enclType : t) && 2343 (!isStatic || e.getModifiers().contains(STATIC)) && 2344 (isStatic || !e.getSimpleName().contentEquals(THIS_KEYWORD)) && 2345 ((isStatic && !inImport) || !e.getSimpleName().contentEquals(CLASS_KEYWORD)); 2346 case ENUM_CONSTANT: 2347 case EXCEPTION_PARAMETER: 2348 case LOCAL_VARIABLE: 2349 case PARAMETER: 2350 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2351 isOfKindAndType(asMemberOf(e, t, types), e, kinds, baseType, scope, trees, types) && 2352 tu.isAccessible(scope, e, t); 2353 case METHOD: 2354 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2355 isOfKindAndType(((ExecutableType)asMemberOf(e, t, types)).getReturnType(), e, kinds, baseType, scope, trees, types) && 2356 (isSuperCall && e.getModifiers().contains(PROTECTED) || tu.isAccessible(scope, e, isSuperCall && enclType != null ? enclType : t)) && 2357 (!isStatic || e.getModifiers().contains(STATIC)); 2358 case CLASS: 2359 case ENUM: 2360 case INTERFACE: 2361 case ANNOTATION_TYPE: 2362 return Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2363 isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types) && 2364 tu.isAccessible(scope, e, t) && isStatic; 2365 case CONSTRUCTOR: 2366 ctorSeen[0] = true; 2367 return isOfKindAndType(e.getEnclosingElement().asType(), e, kinds, baseType, scope, trees, types) && 2368 (tu.isAccessible(scope, e, t) || (elem.getModifiers().contains(ABSTRACT) && !e.getModifiers().contains(PRIVATE))) && 2369 isStatic; 2370 } 2371 return false; 2372 } 2373 }; 2374 for(Element e : controller.getElementUtilities().getMembers(type, acceptor)) { 2375 switch (e.getKind()) { 2376 case ENUM_CONSTANT: 2377 case EXCEPTION_PARAMETER: 2378 case FIELD: 2379 case LOCAL_VARIABLE: 2380 case PARAMETER: 2381 String name = e.getSimpleName().toString(); 2382 if (THIS_KEYWORD.equals(name) || CLASS_KEYWORD.equals(name)) { 2383 results.add(JavaCompletionItem.createKeywordItem(name, null, offset, false)); 2384 } else { 2385 TypeMirror tm = type.getKind() == TypeKind.DECLARED ? types.asMemberOf((DeclaredType)type, e) : e.asType(); 2386 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, tm, offset, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), isOfSmartType(env, tm, smartTypes))); 2387 } 2388 break; 2389 case CONSTRUCTOR: 2390 case METHOD: 2391 ExecutableType et = (ExecutableType)(type.getKind() == TypeKind.DECLARED ? types.asMemberOf((DeclaredType)type, e) : e.asType()); 2392 results.add(JavaCompletionItem.createExecutableItem((ExecutableElement)e, et, offset, typeElem != e.getEnclosingElement(), elements.isDeprecated(e), inImport, isOfSmartType(env, et.getReturnType(), smartTypes))); 2393 break; 2394 case CLASS: 2395 case ENUM: 2396 case INTERFACE: 2397 case ANNOTATION_TYPE: 2398 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)e.asType(), offset, false, elements.isDeprecated(e), false)); 2399 break; 2400 } 2401 } 2402 if (!ctorSeen[0] && kinds.contains(CONSTRUCTOR) && elem.getKind().isInterface()) { 2403 results.add(JavaCompletionItem.createDefaultConstructorItem((TypeElement)elem, offset)); 2404 } 2405 } 2406 2407 private void addEnumConstants(Env env, TypeElement elem) { 2408 int offset = env.getOffset(); 2409 String prefix = env.getPrefix(); 2410 Elements elements = env.getController().getElements(); 2411 for(Element e : elem.getEnclosedElements()) { 2412 if (e.getKind() == ENUM_CONSTANT) { 2413 String name = e.getSimpleName().toString(); 2414 if (Utilities.startsWith(name, prefix)) 2415 results.add(JavaCompletionItem.createVariableItem((VariableElement)e, e.asType(), offset, false, elements.isDeprecated(e), false)); 2416 } 2417 } 2418 } 2419 2420 private void addPackageContent(final Env env, PackageElement pe, EnumSet<ElementKind> kinds, DeclaredType baseType) throws IOException { 2421 Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null; 2422 int offset = env.getOffset(); 2423 String prefix = env.getPrefix(); 2424 CompilationController controller = env.getController(); 2425 Elements elements = controller.getElements(); 2426 Types types = controller.getTypes(); 2427 Trees trees = controller.getTrees(); 2428 Scope scope = env.getScope(); 2429 for(Element e : pe.getEnclosedElements()) { 2430 if (e.getKind().isClass() || e.getKind().isInterface()) { 2431 String name = e.getSimpleName().toString(); 2432 if (Utilities.startsWith(name, prefix) && trees.isAccessible(scope, (TypeElement)e) && isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types)) { 2433 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)e.asType(), offset, false, elements.isDeprecated(e), isOfSmartType(env, e.asType(), smartTypes))); 2434 } 2435 } 2436 } 2437 String pkgName = pe.getQualifiedName() + "."; if (prefix != null && prefix.length() > 0) 2439 pkgName += prefix; 2440 addPackages(env, pkgName); 2441 } 2442 2443 private void addPackages(Env env, String fqnPrefix) { 2444 int offset = env.getOffset(); 2445 if (fqnPrefix == null) 2446 fqnPrefix = EMPTY; 2447 for (String pkgName : env.getController().getClasspathInfo().getClassIndex().getPackageNames(fqnPrefix, true,EnumSet.allOf(ClassIndex.SearchScope.class))) 2448 if (pkgName.length() > 0) 2449 results.add(JavaCompletionItem.createPackageItem(pkgName, offset, false)); 2450 } 2451 2452 private void addTypes(Env env, EnumSet<ElementKind> kinds, DeclaredType baseType, Element toExclude) throws IOException { 2453 if (queryType == COMPLETION_ALL_QUERY_TYPE) { 2454 if (baseType == null) 2455 addAllTypes(env, kinds); 2456 else 2457 addSubtypesOf(env, baseType, false); 2458 } else { 2459 addLocalAndImportedTypes(env, kinds, baseType, toExclude); 2460 } 2461 addPackages(env, env.getPrefix()); 2462 } 2463 2464 private void addLocalAndImportedTypes(Env env, final EnumSet<ElementKind> kinds, final DeclaredType baseType, final Element toExclude) throws IOException { 2465 int offset = env.getOffset(); 2466 final String prefix = env.getPrefix(); 2467 final CompilationController controller = env.getController(); 2468 final Trees trees = controller.getTrees(); 2469 final Elements elements = controller.getElements(); 2470 final Types types = controller.getTypes(); 2471 final TreeUtilities tu = controller.getTreeUtilities(); 2472 final Scope scope = env.getScope(); 2473 final TypeElement enclClass = scope.getEnclosingClass(); 2474 final boolean isStatic = enclClass == null ? false : 2475 (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2476 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2477 public boolean accept(Element e, TypeMirror t) { 2478 if (e.getKind().isClass() || e.getKind().isInterface() || e.getKind() == TYPE_PARAMETER) { 2479 String name = e.getSimpleName().toString(); 2480 return name.length() > 0 && !Character.isDigit(name.charAt(0)) && Utilities.startsWith(name, prefix) && 2481 (!isStatic || e.getModifiers().contains(STATIC)) && isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types); 2482 } 2483 return false; 2484 } 2485 }; 2486 for(Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) { 2487 switch (e.getKind()) { 2488 case CLASS: 2489 case ENUM: 2490 case INTERFACE: 2491 case ANNOTATION_TYPE: 2492 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)e.asType(), offset, false, elements.isDeprecated(e), false)); 2493 break; 2494 case TYPE_PARAMETER: 2495 results.add(JavaCompletionItem.createTypeParameterItem((TypeParameterElement)e, offset)); 2496 break; 2497 } 2498 } 2499 acceptor = new ElementUtilities.ElementAcceptor() { 2500 public boolean accept(Element e, TypeMirror t) { 2501 return toExclude != e && Utilities.startsWith(e.getSimpleName().toString(), prefix) && 2502 e.getEnclosingElement().getKind() == PACKAGE && 2503 trees.isAccessible(scope, (TypeElement)e) && 2504 isOfKindAndType(e.asType(), e, kinds, baseType, scope, trees, types); 2505 } 2506 }; 2507 for (TypeElement e : controller.getElementUtilities().getGlobalTypes(acceptor)) { 2508 results.add(JavaCompletionItem.createTypeItem((TypeElement)e, (DeclaredType)e.asType(), offset, false, elements.isDeprecated(e), false)); 2509 } 2510 } 2511 2512 private void addAllTypes(Env env, EnumSet<ElementKind> kinds) { 2513 int offset = env.getOffset(); 2514 String prefix = env.getPrefix(); 2515 CompilationController controller = env.getController(); 2516 LazyTypeCompletionItem lastItem = null; 2517 for(ElementHandle<TypeElement> name : controller.getJavaSource().getClasspathInfo().getClassIndex().getDeclaredTypes(prefix != null ? prefix : EMPTY, Utilities.isCaseSensitive() ? ClassIndex.NameKind.PREFIX : ClassIndex.NameKind.CASE_INSENSITIVE_PREFIX, EnumSet.allOf(ClassIndex.SearchScope.class))) { 2518 LazyTypeCompletionItem item = LazyTypeCompletionItem.create(name, kinds, offset, controller.getJavaSource()); 2519 if (lastItem != null) 2520 lastItem.setNextItem(item); 2521 lastItem = item; 2522 results.add(item); 2523 } 2524 } 2525 2526 private void addSubtypesOf(Env env, DeclaredType baseType, boolean smartTypes) throws IOException { 2527 int offset = env.getOffset(); 2528 String prefix = env.getPrefix(); 2529 CompilationController controller = env.getController(); 2530 Elements elements = controller.getElements(); 2531 Types types = controller.getTypes(); 2532 Trees trees = controller.getTrees(); 2533 Scope scope = env.getScope(); 2534 HashSet<TypeElement> elems = new HashSet<TypeElement>(); 2535 LinkedList<DeclaredType> bases = new LinkedList<DeclaredType>(); 2536 bases.add(baseType); 2537 ClassIndex index = controller.getJavaSource().getClasspathInfo().getClassIndex(); 2538 while(!bases.isEmpty()) { 2539 DeclaredType head = bases.remove(); 2540 TypeElement elem = (TypeElement)head.asElement(); 2541 if (!elems.add(elem)) 2542 continue; 2543 if (Utilities.startsWith(elem.getSimpleName().toString(), prefix) && trees.isAccessible(scope, elem)) { 2544 results.add(JavaCompletionItem.createTypeItem(elem, head, offset, true, elements.isDeprecated(elem), smartTypes)); 2545 } 2546 List<? extends TypeMirror> tas = head.getTypeArguments(); 2547 boolean isRaw = !tas.iterator().hasNext(); 2548 subtypes: 2549 for (ElementHandle<TypeElement> eh : index.getElements(ElementHandle.create(elem), EnumSet.of(ClassIndex.SearchKind.IMPLEMENTORS),EnumSet.allOf(ClassIndex.SearchScope.class))) { 2550 TypeElement e = eh.resolve(controller); 2551 if (e != null) { 2552 if (trees.isAccessible(scope, e)) { 2553 if (isRaw) { 2554 DeclaredType dt = types.getDeclaredType(e); 2555 bases.add(dt); 2556 } else { 2557 HashMap<Element, TypeMirror> map = new HashMap<Element, TypeMirror>(); 2558 TypeMirror sup = e.getSuperclass(); 2559 if (sup.getKind() == TypeKind.DECLARED && ((DeclaredType)sup).asElement() == elem) { 2560 DeclaredType dt = (DeclaredType)sup; 2561 Iterator<? extends TypeMirror> ittas = tas.iterator(); 2562 Iterator<? extends TypeMirror> it = dt.getTypeArguments().iterator(); 2563 while(it.hasNext() && ittas.hasNext()) { 2564 TypeMirror basetm = ittas.next(); 2565 TypeMirror stm = it.next(); 2566 if (basetm != stm) { 2567 if (stm.getKind() == TypeKind.TYPEVAR) { 2568 map.put(((TypeVariable)stm).asElement(), basetm); 2569 } else { 2570 continue subtypes; 2571 } 2572 } 2573 } 2574 if (it.hasNext() != ittas.hasNext()) { 2575 continue subtypes; 2576 } 2577 } else { 2578 for (TypeMirror tm : e.getInterfaces()) { 2579 if (((DeclaredType)tm).asElement() == elem) { 2580 DeclaredType dt = (DeclaredType)tm; 2581 Iterator<? extends TypeMirror> ittas = tas.iterator(); 2582 Iterator<? extends TypeMirror> it = dt.getTypeArguments().iterator(); 2583 while(it.hasNext() && ittas.hasNext()) { 2584 TypeMirror basetm = ittas.next(); 2585 TypeMirror stm = it.next(); 2586 if (basetm != stm) { 2587 if (stm.getKind() == TypeKind.TYPEVAR) { 2588 map.put(((TypeVariable)stm).asElement(), basetm); 2589 } else { 2590 continue subtypes; 2591 } 2592 } 2593 } 2594 if (it.hasNext() != ittas.hasNext()) { 2595 continue subtypes; 2596 } 2597 break; 2598 } 2599 } 2600 } 2601 List<? extends TypeParameterElement> tpes = e.getTypeParameters(); 2602 TypeMirror[] targs = new TypeMirror[tpes.size()]; 2603 int i = 0; 2604 for (Iterator<? extends TypeParameterElement> it = tpes.iterator(); it.hasNext();) { 2605 TypeParameterElement tpe = it.next(); 2606 TypeMirror t = map.get(tpe); 2607 targs[i++] = t != null ? t : tpe.asType(); 2608 } 2609 DeclaredType dt = types.getDeclaredType(e, targs); 2610 bases.add(dt); 2611 } 2612 } 2613 } else { 2614 Logger.getLogger("global").log(Level.FINE, String.format("Cannot resolve: %s on bootpath: %s classpath: %s sourcepath: %s\n", eh.toString(), 2615 controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.BOOT), 2616 controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.COMPILE), 2617 controller.getClasspathInfo().getClassPath(ClasspathInfo.PathKind.SOURCE))); 2618 } 2619 } 2620 } 2621 } 2622 2623 private void addKeyword(Env env, String kw, String postfix, boolean smartType) { 2624 if (Utilities.startsWith(kw, env.getPrefix())) 2625 results.add(JavaCompletionItem.createKeywordItem(kw, postfix, env.getOffset(), smartType)); 2626 } 2627 2628 private void addKeywordsForCU(Env env) { 2629 List<String > kws = new ArrayList<String >(); 2630 int offset = env.getOffset(); 2631 String prefix = env.getPrefix(); 2632 CompilationUnitTree cu = env.getRoot(); 2633 SourcePositions sourcePositions = env.getSourcePositions(); 2634 kws.add(ABSTRACT_KEYWORD); 2635 kws.add(CLASS_KEYWORD); 2636 kws.add(ENUM_KEYWORD); 2637 kws.add(FINAL_KEYWORD); 2638 kws.add(INTERFACE_KEYWORD); 2639 boolean beforeAnyClass = true; 2640 boolean beforePublicClass = true; 2641 for(Tree t : cu.getTypeDecls()) { 2642 if (t.getKind() == Tree.Kind.CLASS) { 2643 int pos = (int)sourcePositions.getEndPosition(cu, t); 2644 if (pos != Diagnostic.NOPOS && offset >= pos) { 2645 beforeAnyClass = false; 2646 if (((ClassTree)t).getModifiers().getFlags().contains(Modifier.PUBLIC)) { 2647 beforePublicClass = false; 2648 break; 2649 } 2650 } 2651 } 2652 } 2653 if (beforePublicClass) 2654 kws.add(PUBLIC_KEYWORD); 2655 if (beforeAnyClass) { 2656 kws.add(IMPORT_KEYWORD); 2657 Tree firstImport = null; 2658 for(Tree t : cu.getImports()) { 2659 firstImport = t; 2660 break; 2661 } 2662 Tree pd = cu.getPackageName(); 2663 if ((pd != null && offset <= sourcePositions.getStartPosition(cu, cu)) || 2664 (pd == null && (firstImport == null || sourcePositions.getStartPosition(cu, firstImport) >= offset))) 2665 kws.add(PACKAGE_KEYWORD); 2666 } 2667 for (String kw : kws) { 2668 if (Utilities.startsWith(kw, prefix)) 2669 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2670 } 2671 } 2672 2673 private void addKeywordsForClassBody(Env env) { 2674 int offset = env.getOffset(); 2675 String prefix = env.getPrefix(); 2676 for (String kw : CLASS_BODY_KEYWORDS) 2677 if (Utilities.startsWith(kw, prefix)) 2678 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2679 addPrimitiveTypeKeywords(env); 2680 } 2681 2682 private void addKeywordsForBlock(Env env) { 2683 int offset = env.getOffset(); 2684 String prefix = env.getPrefix(); 2685 for (String kw : STATEMENT_KEYWORDS) { 2686 if (Utilities.startsWith(kw, prefix)) 2687 results.add(JavaCompletionItem.createKeywordItem(kw, null, offset, false)); 2688 } 2689 for (String kw : BLOCK_KEYWORDS) { 2690 if (Utilities.startsWith(kw, prefix)) 2691 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2692 } 2693 if (Utilities.startsWith(RETURN_KEYWORD, prefix)) { 2694 TreePath mth = Utilities.getPathElementOfKind(Tree.Kind.METHOD, env.getPath()); 2695 String postfix = SPACE; 2696 if (mth != null) { 2697 Tree rt = ((MethodTree)mth.getLeaf()).getReturnType(); 2698 if (rt == null || (rt.getKind() == Tree.Kind.PRIMITIVE_TYPE && ((PrimitiveTypeTree)rt).getPrimitiveTypeKind() == TypeKind.VOID)) 2699 postfix = SEMI; 2700 } 2701 results.add(JavaCompletionItem.createKeywordItem(RETURN_KEYWORD, postfix, offset, false)); 2702 } 2703 TreePath tp = env.getPath(); 2704 while (tp != null) { 2705 switch (tp.getLeaf().getKind()) { 2706 case SWITCH: 2707 CaseTree lastCase = null; 2708 CompilationUnitTree root = env.getRoot(); 2709 SourcePositions sourcePositions = env.getSourcePositions(); 2710 for (CaseTree t : ((SwitchTree)tp.getLeaf()).getCases()) { 2711 if (sourcePositions.getStartPosition(root, t) >= offset) 2712 break; 2713 lastCase = t; 2714 } 2715 if (lastCase == null || lastCase.getExpression() != null) { 2716 if (Utilities.startsWith(CASE_KEYWORD, prefix)) 2717 results.add(JavaCompletionItem.createKeywordItem(CASE_KEYWORD, SPACE, offset, false)); 2718 if (Utilities.startsWith(DEFAULT_KEYWORD, prefix)) 2719 results.add(JavaCompletionItem.createKeywordItem(DEFAULT_KEYWORD, COLON, offset, false)); 2720 } 2721 if (Utilities.startsWith(BREAK_KEYWORD, prefix)) 2722 results.add(JavaCompletionItem.createKeywordItem(BREAK_KEYWORD, SEMI, offset, false)); 2723 break; 2724 case DO_WHILE_LOOP: 2725 case ENHANCED_FOR_LOOP: 2726 case FOR_LOOP: 2727 case WHILE_LOOP: 2728 if (Utilities.startsWith(BREAK_KEYWORD, prefix)) 2729 results.add(JavaCompletionItem.createKeywordItem(BREAK_KEYWORD, SEMI, offset, false)); 2730 if (Utilities.startsWith(CONTINUE_KEYWORD, prefix)) 2731 results.add(JavaCompletionItem.createKeywordItem(CONTINUE_KEYWORD, SEMI, offset, false)); 2732 break; 2733 } 2734 tp = tp.getParentPath(); 2735 } 2736 } 2737 2738 private void addKeywordsForStatement(Env env) { 2739 int offset = env.getOffset(); 2740 String prefix = env.getPrefix(); 2741 for (String kw : STATEMENT_KEYWORDS) { 2742 if (Utilities.startsWith(kw, prefix)) 2743 results.add(JavaCompletionItem.createKeywordItem(kw, null, offset, false)); 2744 } 2745 for (String kw : STATEMENT_SPACE_KEYWORDS) { 2746 if (Utilities.startsWith(kw, prefix)) 2747 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2748 } 2749 if (Utilities.startsWith(RETURN_KEYWORD, prefix)) { 2750 TreePath mth = Utilities.getPathElementOfKind(Tree.Kind.METHOD, env.getPath()); 2751 String postfix = SPACE; 2752 if (mth != null) { 2753 Tree rt = ((MethodTree)mth.getLeaf()).getReturnType(); 2754 if (rt.getKind() == Tree.Kind.PRIMITIVE_TYPE && ((PrimitiveTypeTree)rt).getPrimitiveTypeKind() == TypeKind.VOID) 2755 postfix = SEMI; 2756 } 2757 results.add(JavaCompletionItem.createKeywordItem(RETURN_KEYWORD, postfix, offset, false)); 2758 } 2759 TreePath tp = env.getPath(); 2760 while (tp != null) { 2761 switch (tp.getLeaf().getKind()) { 2762 case DO_WHILE_LOOP: 2763 case ENHANCED_FOR_LOOP: 2764 case FOR_LOOP: 2765 case WHILE_LOOP: 2766 if (Utilities.startsWith(CONTINUE_KEYWORD, prefix)) 2767 results.add(JavaCompletionItem.createKeywordItem(CONTINUE_KEYWORD, SEMI, offset, false)); 2768 case SWITCH: 2769 if (Utilities.startsWith(BREAK_KEYWORD, prefix)) 2770 results.add(JavaCompletionItem.createKeywordItem(BREAK_KEYWORD, SEMI, offset, false)); 2771 break; 2772 } 2773 tp = tp.getParentPath(); 2774 } 2775 } 2776 2777 private void addValueKeywords(Env env) throws IOException { 2778 int offset = env.getOffset(); 2779 String prefix = env.getPrefix(); 2780 boolean smartType = false; 2781 if (queryType == COMPLETION_QUERY_TYPE) { 2782 Set<? extends TypeMirror> smartTypes = env.getSmartTypes(); 2783 if (smartTypes != null && !smartTypes.isEmpty()) { 2784 for (TypeMirror st : smartTypes) { 2785 if (st.getKind() == TypeKind.BOOLEAN) { 2786 smartType = true; 2787 break; 2788 } 2789 } 2790 } 2791 } 2792 if (Utilities.startsWith(FALSE_KEYWORD, prefix)) 2793 results.add(JavaCompletionItem.createKeywordItem(FALSE_KEYWORD, null, offset, smartType)); 2794 if (Utilities.startsWith(TRUE_KEYWORD, prefix)) 2795 results.add(JavaCompletionItem.createKeywordItem(TRUE_KEYWORD, null, offset, smartType)); 2796 if (Utilities.startsWith(NULL_KEYWORD, prefix)) 2797 results.add(JavaCompletionItem.createKeywordItem(NULL_KEYWORD, null, offset, false)); 2798 if (Utilities.startsWith(NEW_KEYWORD, prefix)) 2799 results.add(JavaCompletionItem.createKeywordItem(NEW_KEYWORD, SPACE, offset, false)); 2800 } 2801 2802 private void addPrimitiveTypeKeywords(Env env) { 2803 int offset = env.getOffset(); 2804 String prefix = env.getPrefix(); 2805 for (String kw : PRIM_KEYWORDS) { 2806 if (Utilities.startsWith(kw, prefix)) 2807 results.add(JavaCompletionItem.createKeywordItem(kw, null, offset, false)); 2808 } 2809 } 2810 2811 private void addClassModifiers(Env env, Set<Modifier> modifiers) { 2812 int offset = env.getOffset(); 2813 String prefix = env.getPrefix(); 2814 List<String > kws = new ArrayList<String >(); 2815 if (!modifiers.contains(PUBLIC) && !modifiers.contains(PRIVATE)) { 2816 kws.add(PUBLIC_KEYWORD); 2817 } 2818 if (!modifiers.contains(FINAL) && !modifiers.contains(ABSTRACT)) { 2819 kws.add(ABSTRACT_KEYWORD); 2820 kws.add(FINAL_KEYWORD); 2821 } 2822 kws.add(CLASS_KEYWORD); 2823 kws.add(INTERFACE_KEYWORD); 2824 kws.add(ENUM_KEYWORD); 2825 for (String kw : kws) { 2826 if (Utilities.startsWith(kw, prefix)) 2827 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2828 } 2829 } 2830 2831 private void addMemberModifiers(Env env, Set<Modifier> modifiers, boolean isLocal) { 2832 int offset = env.getOffset(); 2833 String prefix = env.getPrefix(); 2834 List<String > kws = new ArrayList<String >(); 2835 if (isLocal) { 2836 if (!modifiers.contains(FINAL)) { 2837 kws.add(FINAL_KEYWORD); 2838 } 2839 } else { 2840 if (!modifiers.contains(PUBLIC) && !modifiers.contains(PROTECTED) && !modifiers.contains(PRIVATE)) { 2841 kws.add(PUBLIC_KEYWORD); 2842 kws.add(PROTECTED_KEYWORD); 2843 kws.add(PRIVATE_KEYWORD); 2844 } 2845 if (!modifiers.contains(FINAL) && !modifiers.contains(ABSTRACT)) { 2846 kws.add(ABSTRACT_KEYWORD); 2847 kws.add(FINAL_KEYWORD); 2848 } 2849 if (!modifiers.contains(STATIC)) { 2850 kws.add(STATIC_KEYWORD); 2851 } 2852 kws.add(CLASS_KEYWORD); 2853 kws.add(INTERFACE_KEYWORD); 2854 kws.add(ENUM_KEYWORD); 2855 kws.add(NATIVE_KEYWORD); 2856 kws.add(STRICT_KEYWORD); 2857 kws.add(SYNCHRONIZED_KEYWORD); 2858 kws.add(TRANSIENT_KEYWORD); 2859 kws.add(VOID_KEYWORD); 2860 kws.add(VOLATILE_KEYWORD); 2861 } 2862 for (String kw : kws) { 2863 if (Utilities.startsWith(kw, prefix)) 2864 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2865 } 2866 for (String kw : PRIM_KEYWORDS) { 2867 if (Utilities.startsWith(kw, prefix)) 2868 results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false)); 2869 } 2870 } 2871 2872 private void addElementCreators(Env env) throws IOException { 2873 CompilationController controller = env.getController(); 2874 controller.toPhase(Phase.ELEMENTS_RESOLVED); 2875 TreePath clsPath = Utilities.getPathElementOfKind(Tree.Kind.CLASS, env.getPath()); 2876 if (clsPath == null) 2877 return; 2878 ClassTree cls = (ClassTree)clsPath.getLeaf(); 2879 CompilationUnitTree root = env.getRoot(); 2880 SourcePositions sourcePositions = env.getSourcePositions(); 2881 Tree currentMember = null; 2882 int nextMemberPos = (int)Diagnostic.NOPOS; 2883 for (Tree member : cls.getMembers()) { 2884 int pos = (int)sourcePositions.getStartPosition(root, member); 2885 if (pos > caretOffset) { 2886 nextMemberPos = pos; 2887 break; 2888 } 2889 pos = (int)sourcePositions.getEndPosition(root, member); 2890 if (caretOffset < pos) { 2891 currentMember = member; 2892 nextMemberPos = pos; 2893 break; 2894 } 2895 } 2896 if (nextMemberPos > caretOffset) { 2897 String text = controller.getText().substring(caretOffset, nextMemberPos); 2898 int idx = text.indexOf('\n'); if (idx >= 0) 2900 text = text.substring(0, idx); 2901 if (text.trim().length() > 0) 2902 return; 2903 } 2904 final Trees trees = controller.getTrees(); 2905 TypeElement te = (TypeElement)trees.getElement(clsPath); 2906 if (te == null || !te.getKind().isClass()) 2907 return; 2908 int offset = env.getOffset(); 2909 String prefix = env.getPrefix(); 2910 Types types = controller.getTypes(); 2911 DeclaredType clsType = (DeclaredType)te.asType(); 2912 for (ExecutableElement ee : GeneratorUtils.findUndefs(controller, te)) { 2913 if (Utilities.startsWith(ee.getSimpleName().toString(), prefix)) { 2914 ExecutableType type = (ExecutableType)types.asMemberOf(clsType, ee); 2915 results.add(JavaCompletionItem.createOverrideMethodItem(ee, type, offset, true)); 2916 } 2917 } 2918 for (ExecutableElement ee : GeneratorUtils.findOverridable(controller, te)) { 2919 if (Utilities.startsWith(ee.getSimpleName().toString(), prefix)) { 2920 ExecutableType type = (ExecutableType)types.asMemberOf(clsType, ee); 2921 results.add(JavaCompletionItem.createOverrideMethodItem(ee, type, offset, false)); 2922 } 2923 } 2924 if (Utilities.startsWith(te.getSimpleName().toString(), prefix)) { 2925 final Set<VariableElement> initializedFields = new LinkedHashSet<VariableElement>(); 2926 final Set<VariableElement> uninitializedFields = new LinkedHashSet<VariableElement>(); 2927 final List<ExecutableElement> constructors = new ArrayList<ExecutableElement>(); 2928 if (currentMember != null) { 2929 Element e = trees.getElement(new TreePath(clsPath, currentMember)); 2930 if (e.getKind().isField()) 2931 initializedFields.add((VariableElement)e); 2932 } 2933 GeneratorUtils.scanForFieldsAndConstructors(controller, clsPath, initializedFields, uninitializedFields, constructors); 2934 boolean hasDefaultConstructor = false; 2935 boolean hasConstrutorForAllUnintialized = false; 2936 for (ExecutableElement ee : constructors) { 2937 List<? extends VariableElement> parameters = ee.getParameters(); 2938 if (parameters.isEmpty() && !controller.getElementUtilities().isSynthetic(ee)) 2939 hasDefaultConstructor = true; 2940 if (parameters.size() == uninitializedFields.size() && !uninitializedFields.isEmpty()) { 2941 Iterator<? extends VariableElement> proposed = uninitializedFields.iterator(); 2942 Iterator<? extends VariableElement> original = parameters.iterator(); 2943 boolean same = true; 2944 while (same && proposed.hasNext() && original.hasNext()) 2945 same &= controller.getTypes().isSameType(proposed.next().asType(), original.next().asType()); 2946 if (same) 2947 hasConstrutorForAllUnintialized = true; 2948 } 2949 } 2950 if (!uninitializedFields.isEmpty() && !hasConstrutorForAllUnintialized) 2951 results.add(JavaCompletionItem.createInitializeAllConstructorItem(uninitializedFields, te, offset)); 2952 if (!hasDefaultConstructor) 2953 results.add(JavaCompletionItem.createInitializeAllConstructorItem(Collections.<VariableElement>emptySet(), te, offset)); 2954 } 2955 } 2956 2957 private TypeElement getTypeElement(Env env, final String simpleName) throws IOException { 2958 if (simpleName == null || simpleName.length() == 0) 2959 return null; 2960 final CompilationController controller = env.getController(); 2961 final TreeUtilities tu = controller.getTreeUtilities(); 2962 final Scope scope = env.getScope(); 2963 final TypeElement enclClass = scope.getEnclosingClass(); 2964 final boolean isStatic = enclClass == null ? false : 2965 (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2966 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 2967 public boolean accept(Element e, TypeMirror t) { 2968 return (e.getKind().isClass() || e.getKind().isInterface()) && 2969 e.getSimpleName().contentEquals(simpleName) && 2970 (!isStatic || e.getModifiers().contains(STATIC)) && 2971 tu.isAccessible(scope, e, t); 2972 } 2973 }; 2974 for(Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) 2975 return (TypeElement)e; 2976 final Trees trees = controller.getTrees(); 2977 acceptor = new ElementUtilities.ElementAcceptor() { 2978 public boolean accept(Element e, TypeMirror t) { 2979 return e.getSimpleName().contentEquals(simpleName) && e.getEnclosingElement().getKind() == PACKAGE && 2980 trees.isAccessible(scope, (TypeElement)e); 2981 } 2982 }; 2983 for (TypeElement e : controller.getElementUtilities().getGlobalTypes(acceptor)) 2984 if (simpleName.contentEquals(e.getSimpleName())) 2985 return e; 2986 return null; 2987 } 2988 2989 private VariableElement getFieldOrVar(Env env, final String simpleName) throws IOException { 2990 if (simpleName == null || simpleName.length() == 0) 2991 return null; 2992 final CompilationController controller = env.getController(); 2993 final Scope scope = env.getScope(); 2994 final TypeElement enclClass = scope.getEnclosingClass(); 2995 final boolean isStatic = enclClass == null ? false : 2996 (controller.getTreeUtilities().isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())); 2997 final Collection<? extends Element> illegalForwardRefs = env.getForwardReferences(); 2998 final ExecutableElement method = scope.getEnclosingMethod(); 2999 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 3000 public boolean accept(Element e, TypeMirror t) { 3001 if (!e.getSimpleName().contentEquals(simpleName)) 3002 return false; 3003 switch (e.getKind()) { 3004 case LOCAL_VARIABLE: 3005 if (isStatic && (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD))) 3006 return false; 3007 case EXCEPTION_PARAMETER: 3008 case PARAMETER: 3009 return (method == e.getEnclosingElement() || e.getModifiers().contains(FINAL)) && 3010 !illegalForwardRefs.contains(e); 3011 case FIELD: 3012 if (e.getSimpleName().contentEquals(THIS_KEYWORD) || e.getSimpleName().contentEquals(SUPER_KEYWORD)) 3013 return !isStatic; 3014 case ENUM_CONSTANT: 3015 return !illegalForwardRefs.contains(e); 3016 } 3017 return false; 3018 } 3019 }; 3020 for(Element e : controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor)) 3021 return (VariableElement)e; 3022 return null; 3023 } 3024 3025 private boolean isOfSmartType(Env env, TypeMirror type, Set<? extends TypeMirror> smartTypes) { 3026 if (smartTypes == null || smartTypes.isEmpty()) 3027 return false; 3028 if (env.isInsideForEachExpressiion()) { 3029 if (type.getKind() == TypeKind.ARRAY) { 3030 type = ((ArrayType)type).getComponentType(); 3031 } else if (type.getKind() == TypeKind.DECLARED) { 3032 Elements elements = env.getController().getElements(); 3033 Types types = env.getController().getTypes(); 3034 DeclaredType iterable = types.getDeclaredType(elements.getTypeElement("java.lang.Iterable")); if (types.isSubtype(type, iterable)) { 3036 Iterator<? extends TypeMirror> it = ((DeclaredType)type).getTypeArguments().iterator(); 3037 type = it.hasNext() ? it.next() : elements.getTypeElement("java.lang.Object").asType(); } else { 3039 return false; 3040 } 3041 } else { 3042 return false; 3043 } 3044 } 3045 for (TypeMirror smartType : smartTypes) { 3046 if (SourceUtils.checkTypesAssignable(env.getController(), type, smartType)) 3047 return true; 3048 } 3049 return false; 3050 } 3051 3052 private boolean isTopLevelClass(Tree tree, CompilationUnitTree root) { 3053 if (tree.getKind() == Tree.Kind.CLASS || (tree.getKind() == Tree.Kind.EXPRESSION_STATEMENT && ((ExpressionStatementTree)tree).getExpression().getKind() == Tree.Kind.ERRONEOUS)) { 3054 for (Tree t : root.getTypeDecls()) 3055 if (tree == t) 3056 return true; 3057 } 3058 return false; 3059 } 3060 private String getJavaIdentifierPart(String text) { 3061 for (int i = 0; i < text.length(); i++) { 3062 if (!(Character.isJavaIdentifierPart(text.charAt(i)))) 3063 return null; 3064 } 3065 return text; 3066 } 3067 3068 private Collection getFilteredData(Collection<JavaCompletionItem> data, String prefix) { 3069 if (prefix.length() == 0) 3070 return data; 3071 List ret = new ArrayList(); 3072 for (Iterator<JavaCompletionItem> it = data.iterator(); it.hasNext();) { 3073 CompletionItem itm = it.next(); 3074 if (Utilities.startsWith(itm.getInsertPrefix().toString(), prefix)) 3075 ret.add(itm); 3076 } 3077 return ret; 3078 } 3079 3080 private boolean isOfKindAndType(TypeMirror type, Element e, EnumSet<ElementKind> kinds, TypeMirror base, Scope scope, Trees trees, Types types) { 3081 if (kinds.contains(e.getKind())) { 3082 if (base == null) 3083 return true; 3084 if (types.isSubtype(type, base)) 3085 return true; 3086 } 3087 if ((e.getKind().isClass() || e.getKind().isInterface()) && 3088 (kinds.contains(ANNOTATION_TYPE) || kinds.contains(CLASS) || kinds.contains(ENUM) || kinds.contains(INTERFACE))) { 3089 DeclaredType dt = (DeclaredType)e.asType(); 3090 for (Element ee : e.getEnclosedElements()) 3091 if (trees.isAccessible(scope, ee, dt) && isOfKindAndType(ee.asType(), ee, kinds, base, scope, trees, types)) 3092 return true; 3093 } 3094 return false; 3095 } 3096 3097 private Set<? extends TypeMirror> getSmartTypes(Env env) throws IOException { 3098 int offset = env.getOffset(); 3099 final CompilationController controller = env.getController(); 3100 TreePath path = env.getPath(); 3101 Tree lastTree = null; 3102 int dim = 0; 3103 while(path != null) { 3104 Tree tree = path.getLeaf(); 3105 switch(tree.getKind()) { 3106 case VARIABLE: 3107 TypeMirror type = controller.getTrees().getTypeMirror(new TreePath(path, ((VariableTree)tree).getType())); 3108 while(dim-- > 0) { 3109 if (type.getKind() == TypeKind.ARRAY) 3110 type = ((ArrayType)type).getComponentType(); 3111 else 3112 return null; 3113 } 3114 return Collections.singleton(type); 3115 case ASSIGNMENT: 3116 type = controller.getTrees().getTypeMirror(new TreePath(path, ((AssignmentTree)tree).getVariable())); 3117 TreePath parentPath = path.getParentPath(); 3118 if (parentPath != null && parentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION && type.getKind() == TypeKind.EXECUTABLE) { 3119 type = ((ExecutableType)type).getReturnType(); 3120 while(dim-- > 0) { 3121 if (type.getKind() == TypeKind.ARRAY) 3122 type = ((ArrayType)type).getComponentType(); 3123 else 3124 return null; 3125 } 3126 if (type.getKind() == TypeKind.ARRAY) 3127 type = ((ArrayType)type).getComponentType(); 3128 } 3129 return Collections.singleton(type); 3130 case RETURN: 3131 TreePath methodPath = Utilities.getPathElementOfKind(Tree.Kind.METHOD, path); 3132 Tree retTree = methodPath != null ? ((MethodTree)methodPath.getLeaf()).getReturnType() : null; 3133 return retTree != null ? Collections.singleton(controller.getTrees().getTypeMirror(new TreePath(methodPath, retTree))) : null; 3134 case THROW: 3135 methodPath = Utilities.getPathElementOfKind(Tree.Kind.METHOD, path); 3136 if (methodPath == null) 3137 return null; 3138 HashSet<TypeMirror> ret = new HashSet<TypeMirror>(); 3139 Trees trees = controller.getTrees(); 3140 for (ExpressionTree thr : ((MethodTree)methodPath.getLeaf()).getThrows()) 3141 ret.add(trees.getTypeMirror(new TreePath(methodPath, thr))); 3142 return ret; 3143 case IF: 3144 IfTree iff = (IfTree)tree; 3145 return iff.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; 3146 case WHILE_LOOP: 3147 WhileLoopTree wl = (WhileLoopTree)tree; 3148 return wl.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; 3149 case FOR_LOOP: 3150 ForLoopTree fl = (ForLoopTree)tree; 3151 Tree cond = fl.getCondition(); 3152 if (lastTree != null) { 3153 if (cond instanceof ErroneousTree) { 3154 Iterator<? extends Tree> itt =((ErroneousTree)cond).getErrorTrees().iterator(); 3155 if (itt.hasNext()) 3156 cond = itt.next(); 3157 } 3158 return cond == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; 3159 } 3160 SourcePositions sourcePositions = env.getSourcePositions(); 3161 CompilationUnitTree root = env.getRoot(); 3162 if (cond != null && sourcePositions.getEndPosition(root, cond) < offset) 3163 return null; 3164 Tree lastInit = null; 3165 for (Tree init : fl.getInitializer()) { 3166 if (sourcePositions.getEndPosition(root, init) >= offset) 3167 return null; 3168 lastInit = init; 3169 } 3170 String text = null; 3171 if (lastInit == null) { 3172 text = controller.getText().substring((int)sourcePositions.getStartPosition(root, fl), offset).trim(); 3173 int idx = text.indexOf('('); if (idx >= 0) 3175 text = text.substring(idx + 1); 3176 } else { 3177 text = controller.getText().substring((int)sourcePositions.getEndPosition(root, lastInit), offset).trim(); 3178 } 3179 return ";".equals(text) ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; case ENHANCED_FOR_LOOP: 3181 EnhancedForLoopTree efl = (EnhancedForLoopTree)tree; 3182 Tree expr = efl.getExpression(); 3183 if (lastTree != null) { 3184 if (expr instanceof ErroneousTree) { 3185 Iterator<? extends Tree> itt =((ErroneousTree)expr).getErrorTrees().iterator(); 3186 if (itt.hasNext()) 3187 expr = itt.next(); 3188 } 3189 if(expr != lastTree) 3190 return null; 3191 } else { 3192 sourcePositions = env.getSourcePositions(); 3193 root = env.getRoot(); 3194 text = null; 3195 if (efl.getVariable() == null) { 3196 text = controller.getText().substring((int)sourcePositions.getStartPosition(root, efl), offset).trim(); 3197 int idx = text.indexOf('('); if (idx >= 0) 3199 text = text.substring(idx + 1); 3200 } else { 3201 text = controller.getText().substring((int)sourcePositions.getEndPosition(root, efl.getVariable()), offset).trim(); 3202 } 3203 if (!":".equals(text)) 3204 return null; 3205 } 3206 TypeMirror var = efl.getVariable() != null ? controller.getTrees().getTypeMirror(new TreePath(path, efl.getVariable())) : null; 3207 return var != null ? Collections.singleton(var) : null; 3208 case SWITCH: 3209 SwitchTree sw = (SwitchTree)tree; 3210 if (sw.getExpression() != lastTree) 3211 return null; 3212 ret = new HashSet<TypeMirror>(); 3213 Types types = controller.getTypes(); 3214 ret.add(controller.getTypes().getPrimitiveType(TypeKind.INT)); 3215 ret.add(types.getDeclaredType(controller.getElements().getTypeElement("java.lang.Enum"))); 3216 return ret; 3217 case METHOD_INVOCATION: 3218 MethodInvocationTree mi = (MethodInvocationTree)tree; 3219 sourcePositions = env.getSourcePositions(); 3220 root = env.getRoot(); 3221 List<Tree> argTypes = getArgumentsUpToPos(env, mi.getArguments(), (int)sourcePositions.getEndPosition(root, mi.getMethodSelect()), lastTree != null ? (int)sourcePositions.getStartPosition(root, lastTree) : offset); 3222 if (argTypes != null) { 3223 TypeMirror[] args = new TypeMirror[argTypes.size()]; 3224 int j = 0; 3225 for (Tree t : argTypes) 3226 args[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t)); 3227 Tree mid = mi.getMethodSelect(); 3228 path = new TreePath(path, mid); 3229 switch (mid.getKind()) { 3230 case MEMBER_SELECT: { 3231 String name = ((MemberSelectTree)mid).getIdentifier().toString(); 3232 ExpressionTree exp = ((MemberSelectTree)mid).getExpression(); 3233 path = new TreePath(path, exp); 3234 final TypeMirror tm = controller.getTrees().getTypeMirror(path); 3235 final Element el = controller.getTrees().getElement(path); 3236 final TreeUtilities tu = controller.getTreeUtilities(); 3237 if (el != null && tm.getKind() == TypeKind.DECLARED) { 3238 final boolean isStatic = el.getKind().isClass() || el.getKind().isInterface() || el.getKind() == TYPE_PARAMETER; 3239 final boolean isSuperCall = el != null && el.getKind().isField() && el.getSimpleName().contentEquals(SUPER_KEYWORD); 3240 final Scope scope = env.getScope(); 3241 TypeElement enclClass = scope.getEnclosingClass(); 3242 final TypeMirror enclType = enclClass != null ? enclClass.asType() : null; 3243 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 3244 public boolean accept(Element e, TypeMirror t) { 3245 return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && tu.isAccessible(scope, e, isSuperCall && enclType != null ? enclType : t); 3246 } 3247 }; 3248 return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), name, args, controller.getTypes()); 3249 } 3250 return null; 3251 } 3252 case IDENTIFIER: { 3253 String name = ((IdentifierTree)mid).getName().toString(); 3254 final Scope scope = env.getScope(); 3255 final TreeUtilities tu = controller.getTreeUtilities(); 3256 final TypeElement enclClass = scope.getEnclosingClass(); 3257 final boolean isStatic = enclClass != null ? (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree)env.getPath().getLeaf()).isStatic())) : false; 3258 if (SUPER_KEYWORD.equals(name) && enclClass != null) { 3259 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 3260 public boolean accept(Element e, TypeMirror t) { 3261 return e.getKind() == CONSTRUCTOR && tu.isAccessible(scope, e, t); 3262 } 3263 }; 3264 TypeMirror superclass = enclClass.getSuperclass(); 3265 return getMatchingArgumentTypes(superclass, controller.getElementUtilities().getMembers(superclass, acceptor), INIT, args, controller.getTypes()); 3266 } 3267 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 3268 public boolean accept(Element e, TypeMirror t) { 3269 return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && tu.isAccessible(scope, e, t); 3270 } 3271 }; 3272 return getMatchingArgumentTypes(enclClass != null ? enclClass.asType() : null, controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), THIS_KEYWORD.equals(name) ? INIT : name, args, controller.getTypes()); 3273 } 3274 } 3275 } 3276 return null; 3277 case NEW_CLASS: 3278 NewClassTree nc = (NewClassTree)tree; 3279 sourcePositions = env.getSourcePositions(); 3280 root = env.getRoot(); 3281 int idEndPos = (int)sourcePositions.getEndPosition(root, nc.getIdentifier()); 3282 if (controller.getText().substring(idEndPos, offset).indexOf('(') < 0) 3283 break; 3284 argTypes = getArgumentsUpToPos(env, nc.getArguments(), idEndPos, lastTree != null ? (int)sourcePositions.getStartPosition(root, lastTree) : offset); 3285 if (argTypes != null) { 3286 TypeMirror[] args = new TypeMirror[argTypes.size()]; 3287 int j = 0; 3288 for (Tree t : argTypes) 3289 args[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t)); 3290 Tree mid = nc.getIdentifier(); 3291 path = new TreePath(path, mid); 3292 final TypeMirror tm = controller.getTrees().getTypeMirror(path); 3293 final Element el = controller.getTrees().getElement(path); 3294 final TreeUtilities tu = controller.getTreeUtilities(); 3295 if (el != null && tm.getKind() == TypeKind.DECLARED) { 3296 final Scope scope = env.getScope(); 3297 final boolean isAnonymous = nc.getClassBody() != null || el.getKind().isInterface() || el.getModifiers().contains(ABSTRACT); 3298 ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() { 3299 public boolean accept(Element e, TypeMirror t) { 3300 return e.getKind() == CONSTRUCTOR && (tu.isAccessible(scope, e, t) || isAnonymous && e.getModifiers().contains(PROTECTED)); 3301 } 3302 }; 3303 return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), INIT, args, controller.getTypes()); 3304 } 3305 return null; 3306 } 3307 return null; 3308 case NEW_ARRAY: 3309 NewArrayTree nat = (NewArrayTree)tree; 3310 Tree arrayType = nat.getType(); 3311 if (arrayType == null) { 3312 dim++; 3313 break; 3314 } 3315 sourcePositions = env.getSourcePositions(); 3316 root = env.getRoot(); 3317 int typeEndPos = (int)sourcePositions.getEndPosition(root, arrayType); 3318 text = controller.getText().substring(typeEndPos, offset); 3319 if (text.indexOf('{') >= 0) { 3320 type = controller.getTrees().getTypeMirror(new TreePath(path, arrayType)); 3321 while(dim-- > 0) { 3322 if (type.getKind() == TypeKind.ARRAY) 3323 type = ((ArrayType)type).getComponentType(); 3324 else 3325 return null; 3326 } 3327 return Collections.singleton(type); 3328 } 3329 if (text.trim().endsWith("[")) return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.INT)); 3331 return null; 3332 case CASE: 3333 CaseTree ct = (CaseTree)tree; 3334 ExpressionTree exp = ct.getExpression(); 3335 if (exp != null && env.getSourcePositions().getEndPosition(env.getRoot(), exp) >= offset) { 3336 parentPath = path.getParentPath(); 3337 if (parentPath.getLeaf().getKind() == Tree.Kind.SWITCH) { 3338 exp = ((SwitchTree)parentPath.getLeaf()).getExpression(); 3339 return Collections.singleton(controller.getTrees().getTypeMirror(new TreePath(parentPath, exp))); 3340 } 3341 } 3342 return null; 3343 case ANNOTATION: 3344 AnnotationTree ann = (AnnotationTree)tree; 3345 int pos = (int)env.getSourcePositions().getStartPosition(env.getRoot(), ann.getAnnotationType()); 3346 if (offset <= pos) 3347 break; 3348 pos = (int)env.getSourcePositions().getEndPosition(env.getRoot(), ann.getAnnotationType()); 3349 if (offset < pos) 3350 break; 3351 text = controller.getText().substring(pos, offset).trim(); 3352 if ("(".equals(text) || text.endsWith("{") || text.endsWith(",")) { TypeElement el = (TypeElement)controller.getTrees().getElement(new TreePath(path, ann.getAnnotationType())); 3354 for (Element ee : el.getEnclosedElements()) { 3355 if (ee.getKind() == METHOD && "value".contentEquals(ee.getSimpleName())) { 3356 type = ((ExecutableElement)ee).getReturnType(); 3357 while(dim-- > 0) { 3358 if (type.getKind() == TypeKind.ARRAY) 3359 type = ((ArrayType)type).getComponentType(); 3360 else 3361 return null; 3362 } 3363 if (type.getKind() == TypeKind.ARRAY) 3364 type = ((ArrayType)type).getComponentType(); 3365 return Collections.singleton(type); 3366 } 3367 } 3368 } 3369 return null; 3370 case REMAINDER_ASSIGNMENT: 3371 case AND_ASSIGNMENT: 3372 case XOR_ASSIGNMENT: 3373 case OR_ASSIGNMENT: 3374 case PREFIX_INCREMENT: 3375 case PREFIX_DECREMENT: 3376 case BITWISE_COMPLEMENT: 3377 case LEFT_SHIFT: 3378 case RIGHT_SHIFT: 3379 case UNSIGNED_RIGHT_SHIFT: 3380 case LEFT_SHIFT_ASSIGNMENT: 3381 case RIGHT_SHIFT_ASSIGNMENT: 3382 case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: 3383 case AND: 3384 case OR: 3385 case XOR: 3386 case REMAINDER: 3387 ret = new HashSet<TypeMirror>(); 3388 types = controller.getTypes(); 3389 ret.add(types.getPrimitiveType(TypeKind.BYTE)); 3390 ret.add(types.getPrimitiveType(TypeKind.CHAR)); 3391 ret.add(types.getPrimitiveType(TypeKind.INT)); 3392 ret.add(types.getPrimitiveType(TypeKind.LONG)); 3393 ret.add(types.getPrimitiveType(TypeKind.SHORT)); 3394 return ret; 3395 case CONDITIONAL_AND: 3396 case CONDITIONAL_OR: 3397 case LOGICAL_COMPLEMENT: 3398 return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)); 3399 case PLUS: 3400 BinaryTree bt = (BinaryTree)tree; 3401 TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, bt.getLeftOperand())); 3402 if (tm.getKind().isPrimitive()) { 3403 ret = new HashSet<TypeMirror>(); 3404 types = controller.getTypes(); 3405 ret.add(types.getPrimitiveType(TypeKind.BYTE)); 3406 ret.add(types.getPrimitiveType(TypeKind.CHAR)); 3407 ret.add(types.getPrimitiveType(TypeKind.DOUBLE)); 3408 ret.add(types.getPrimitiveType(TypeKind.FLOAT)); 3409 ret.add(types.getPrimitiveType(TypeKind.INT)); 3410 ret.add(types.getPrimitiveType(TypeKind.LONG)); 3411 ret.add(types.getPrimitiveType(TypeKind.SHORT)); 3412 return ret; 3413 } 3414 return Collections.singleton(tm); 3415 case PLUS_ASSIGNMENT: 3416 CompoundAssignmentTree cat = (CompoundAssignmentTree)tree; 3417 tm = controller.getTrees().getTypeMirror(new TreePath(path, cat.getVariable())); 3418 if (tm.getKind().isPrimitive()) { 3419 ret = new HashSet<TypeMirror>(); 3420 types = controller.getTypes(); 3421 ret.add(types.getPrimitiveType(TypeKind.BYTE)); 3422 ret.add(types.getPrimitiveType(TypeKind.CHAR)); 3423 ret.add(types.getPrimitiveType(TypeKind.DOUBLE)); 3424 ret.add(types.getPrimitiveType(TypeKind.FLOAT)); 3425 ret.add(types.getPrimitiveType(TypeKind.INT)); 3426 ret.add(types.getPrimitiveType(TypeKind.LONG)); 3427 ret.add(types.getPrimitiveType(TypeKind.SHORT)); 3428 return ret; 3429 } 3430 return Collections.singleton(tm); 3431 case MULTIPLY_ASSIGNMENT: 3432 case DIVIDE_ASSIGNMENT: 3433 case MINUS_ASSIGNMENT: 3434 case DIVIDE: 3435 case EQUAL_TO: 3436 case GREATER_THAN: 3437 case GREATER_THAN_EQUAL: 3438 case LESS_THAN: 3439 case LESS_THAN_EQUAL: 3440 case MINUS: 3441 case MULTIPLY: 3442 case NOT_EQUAL_TO: 3443 case UNARY_PLUS: 3444 case UNARY_MINUS: 3445 ret = new HashSet<TypeMirror>(); 3446 types = controller.getTypes(); 3447 ret.add(types.getPrimitiveType(TypeKind.BYTE)); 3448 ret.add(types.getPrimitiveType(TypeKind.CHAR)); 3449 ret.add(types.getPrimitiveType(TypeKind.DOUBLE)); 3450 ret.add(types.getPrimitiveType(TypeKind.FLOAT)); 3451 ret.add(types.getPrimitiveType(TypeKind.INT)); 3452 ret.add(types.getPrimitiveType(TypeKind.LONG)); 3453 ret.add(types.getPrimitiveType(TypeKind.SHORT)); 3454 return ret; 3455 case EXPRESSION_STATEMENT: 3456 exp = ((ExpressionStatementTree)tree).getExpression(); 3457 if (exp.getKind() == Tree.Kind.PARENTHESIZED) { 3458 text = controller.getText().substring((int)env.getSourcePositions().getStartPosition(env.getRoot(), exp), offset).trim(); 3459 if (text.endsWith(")")) return null; 3461 } 3462 } 3463 lastTree = tree; 3464 path = path.getParentPath(); 3465 } 3466 return null; 3467 } 3468 3469 private TokenSequence<JavaTokenId> findLastNonWhitespaceToken(Env env, Tree tree, int position) { 3470 int startPos = (int)env.getSourcePositions().getStartPosition(env.getRoot(), tree); 3471 return findLastNonWhitespaceToken(env, startPos, position); 3472 } 3473 3474 private TokenSequence<JavaTokenId> findLastNonWhitespaceToken(Env env, int startPos, int endPos) { 3475 TokenSequence<JavaTokenId> ts = env.getController().getTokenHierarchy().tokenSequence(JavaTokenId.language()); 3476 ts.move(endPos); 3477 while(ts.movePrevious()) { 3478 int offset = ts.offset(); 3479 if (offset < startPos) 3480 return null; 3481 switch (ts.token().id()) { 3482 case WHITESPACE: 3483 case LINE_COMMENT: 3484 case BLOCK_COMMENT: 3485 break; 3486 default: 3487 return ts; 3488 } 3489 } 3490 return null; 3491 } 3492 3493 private List<Tree> getArgumentsUpToPos(Env env, Iterable <? extends ExpressionTree> args, int startPos, int position) { 3494 List<Tree> ret = new ArrayList<Tree>(); 3495 CompilationUnitTree root = env.getRoot(); 3496 SourcePositions sourcePositions = env.getSourcePositions(); 3497 for (ExpressionTree e : args) { 3498 int pos = (int)sourcePositions.getEndPosition(root, e); 3499 if (pos != Diagnostic.NOPOS && position > pos) { 3500 startPos = pos; 3501 ret.add(e); 3502 } 3503 } 3504 if (position > startPos) { 3505 String text = env.getController().getText().substring(startPos, position).trim(); 3506 if ("(".equals(text) || ",".equals(text)) return ret; 3508 } 3509 return null; 3510 } 3511 3512 private List<List<String >> getMatchingParams(TypeMirror type, Iterable <? extends Element> elements, String name, TypeMirror[] argTypes, Types types) { 3513 List<List<String >> ret = new ArrayList<List<String >>(); 3514 for (Element e : elements) { 3515 if ((e.getKind() == CONSTRUCTOR || e.getKind() == METHOD) && name.contentEquals(e.getSimpleName())) { 3516 List<? extends VariableElement> params = ((ExecutableElement)e).getParameters(); 3517 int parSize = params.size(); 3518 boolean varArgs = ((ExecutableElement)e).isVarArgs(); 3519 if (!varArgs && (parSize < argTypes.length)) { 3520 continue; 3521 } 3522 if (parSize == 0) { 3523 ret.add(Collections.<String >singletonList(NbBundle.getMessage(JavaCompletionProvider.class, "JCP-no-parameters"))); 3524 } else { 3525 ExecutableType eType = (ExecutableType)asMemberOf(e, type, types); 3526 Iterator<? extends TypeMirror> parIt = eType.getParameterTypes().iterator(); 3527 TypeMirror param = null; 3528 for (int i = 0; i <= argTypes.length; i++) { 3529 if (parIt.hasNext()) { 3530 param = parIt.next(); 3531 if (!parIt.hasNext() && param.getKind() == TypeKind.ARRAY) 3532 param = ((ArrayType)param).getComponentType(); 3533 } else if (!varArgs) { 3534 break; 3535 } 3536 if (i == argTypes.length) { 3537 List<String > paramStrings = new ArrayList<String >(parSize); 3538 Iterator<? extends TypeMirror> tIt = eType.getParameterTypes().iterator(); 3539 for (Iterator<? extends VariableElement> it = params.iterator(); it.hasNext();) { 3540 VariableElement ve = it.next(); 3541 StringBuffer sb = new StringBuffer (); 3542 sb.append(Utilities.getTypeName(tIt.next(), false)); 3543 if (varArgs && !tIt.hasNext()) 3544 sb.delete(sb.length() - 2, sb.length()).append("..."); CharSequence veName = ve.getSimpleName(); 3546 if (veName != null && veName.length() > 0) { 3547 sb.append(" "); sb.append(veName); 3549 } 3550 if (it.hasNext()) { 3551 sb.append(", "); } 3553 paramStrings.add(sb.toString()); 3554 } 3555 ret.add(paramStrings); 3556 break; 3557 } 3558 if (!types.isAssignable(argTypes[i], param)) 3559 break; 3560 } 3561 } 3562 } 3563 } 3564 return ret.isEmpty() ? null : ret; 3565 } 3566 3567 private Set<TypeMirror> getMatchingArgumentTypes(TypeMirror type, Iterable <? extends Element> elements, String name, TypeMirror[] argTypes, Types types) { 3568 Set<TypeMirror> ret = new HashSet<TypeMirror>(); 3569 for (Element e : elements) { 3570 if ((e.getKind() == CONSTRUCTOR || e.getKind() == METHOD) && name.contentEquals(e.getSimpleName())) { 3571 int i = 0; 3572 Collection<? extends VariableElement> params = ((ExecutableElement)e).getParameters(); 3573 if (params.size() <= argTypes.length) 3574 continue; 3575 for (TypeMirror param : ((ExecutableType)asMemberOf(e, type, types)).getParameterTypes()) { 3576 if (i == argTypes.length) { 3577 ret.add(param); 3578 break; 3579 } 3580 if (!types.isAssignable(argTypes[i++], param)) 3581 break; 3582 } 3583 } 3584 } 3585 return ret.isEmpty() ? null : ret; 3586 } 3587 3588 private TypeMirror asMemberOf(Element element, TypeMirror type, Types types) { 3589 TypeMirror ret = element.asType(); 3590 TypeMirror enclType = element.getEnclosingElement().asType(); 3591 if (enclType.getKind() == TypeKind.DECLARED) 3592 enclType = types.erasure(enclType); 3593 while(type != null && type.getKind() == TypeKind.DECLARED) { 3594 if (types.isSubtype(type, enclType)) { 3595 ret = types.asMemberOf((DeclaredType)type, element); 3596 break; 3597 } 3598 type = ((DeclaredType)type).getEnclosingType(); 3599 } 3600 return ret; 3601 } 3602 3603 private Tree unwrapErrTree(Tree tree) { 3604 if (tree != null && tree.getKind() == Tree.Kind.ERRONEOUS) { 3605 Iterator<? extends Tree> it = ((ErroneousTree)tree).getErrorTrees().iterator(); 3606 tree = it.hasNext() ? it.next() : null; 3607 } 3608 return tree; 3609 } 3610 3611 private boolean withinScope(Env env, TypeElement e) throws IOException { 3612 for (Element encl = env.getScope().getEnclosingClass(); encl != null; encl = encl.getEnclosingElement()) { 3613 if (e == encl) 3614 return true; 3615 } 3616 return false; 3617 } 3618 3619 private Env getCompletionEnvironment(CompilationController controller, boolean upToOffset) throws IOException { 3620 int offset = caretOffset; 3621 String prefix = null; 3622 if (upToOffset && offset > 0) { 3623 TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language()); 3624 if (ts.move(offset) == 0) ts.movePrevious(); else 3627 ts.moveNext(); if (ts.offset() < offset && (ts.token().id() == JavaTokenId.IDENTIFIER || "keyword".equals(ts.token().id().primaryCategory()))) { prefix = ts.token().toString().substring(0, offset - ts.offset()); 3630 offset = ts.offset(); 3631 } 3632 } 3633 controller.toPhase(Phase.PARSED); 3634 TreePath path = controller.getTreeUtilities().pathFor(offset); 3635 if (upToOffset) { 3636 TreePath treePath = path; 3637 while (treePath != null) { 3638 TreePath pPath = treePath.getParentPath(); 3639 TreePath gpPath = pPath != null ? pPath.getParentPath() : null; 3640 Env env = getEnvImpl(controller, path, treePath, pPath, gpPath, offset, prefix, upToOffset); 3641 if (env != null) 3642 return env; 3643 treePath = treePath.getParentPath(); 3644 } 3645 } else { 3646 if (Phase.RESOLVED.compareTo(controller.getPhase()) > 0) { 3647 LinkedList<TreePath> reversePath = new LinkedList<TreePath>(); 3648 TreePath treePath = path; 3649 while (treePath != null) { 3650 reversePath.addFirst(treePath); 3651 treePath = treePath.getParentPath(); 3652 } 3653 for (TreePath tp : reversePath) { 3654 TreePath pPath = tp.getParentPath(); 3655 TreePath gpPath = pPath != null ? pPath.getParentPath() : null; 3656 Env env = getEnvImpl(controller, path, tp, pPath, gpPath, offset, prefix, upToOffset); 3657 if (env != null) 3658 return env; 3659 } 3660 } 3661 } 3662 return new Env(offset, prefix, controller, path, controller.getTrees().getSourcePositions(), null); 3663 } 3664 3665 private Env getEnvImpl(CompilationController controller, TreePath orig, TreePath path, TreePath pPath, TreePath gpPath, int offset, String prefix, boolean upToOffset) throws IOException { 3666 Tree tree = path != null ? path.getLeaf() : null; 3667 Tree parent = pPath != null ? pPath.getLeaf() : null; 3668 Tree grandParent = gpPath != null ? gpPath.getLeaf() : null; 3669 SourcePositions sourcePositions = controller.getTrees().getSourcePositions(); 3670 CompilationUnitTree root = controller.getCompilationUnit(); 3671 if (parent != null && tree.getKind() == Tree.Kind.BLOCK && (parent.getKind() == Tree.Kind.METHOD || parent.getKind() == Tree.Kind.CLASS)) { 3672 controller.toPhase(Phase.ELEMENTS_RESOLVED); 3673 TreeUtilities tu = controller.getTreeUtilities(); 3674 int blockPos = (int)sourcePositions.getStartPosition(root, tree); 3675 String blockText = controller.getText().substring(blockPos, upToOffset ? offset : (int)sourcePositions.getEndPosition(root, tree)); 3676 final SourcePositions[] sp = new SourcePositions[1]; 3677 final BlockTree block = (BlockTree)(((BlockTree)tree).isStatic() ? tu.parseStaticBlock(blockText, sp) : tu.parseStatement(blockText, sp)); 3678 if (block == null) 3679 return null; 3680 sourcePositions = new SourcePositionsImpl(block, sourcePositions, sp[0], blockPos, upToOffset ? offset : -1); 3681 Scope scope = controller.getTrees().getScope(path); 3682 path = tu.pathFor(new TreePath(pPath, block), offset, sourcePositions); 3683 if (upToOffset) { 3684 Tree last = path.getLeaf(); 3685 List<? extends StatementTree> stmts = null; 3686 switch (path.getLeaf().getKind()) { 3687 case BLOCK: 3688 stmts = ((BlockTree)path.getLeaf()).getStatements(); 3689 break; 3690 case FOR_LOOP: 3691 stmts = ((ForLoopTree)path.getLeaf()).getInitializer(); 3692 break; 3693 case ENHANCED_FOR_LOOP: 3694 stmts = Collections.singletonList(((EnhancedForLoopTree)path.getLeaf()).getStatement()); 3695 break; 3696 case METHOD: 3697 stmts = ((MethodTree)path.getLeaf()).getParameters(); 3698 break; 3699 } 3700 if (stmts != null) { 3701 for (StatementTree st : stmts) { 3702 if (sourcePositions.getEndPosition(root, st) <= offset) 3703 last = st; 3704 } 3705 } 3706 scope = tu.attributeTreeTo(block, scope, last); 3707 } else { 3708 tu.attributeTreeTo(block, scope, block); 3709 } 3710 return new Env(offset, prefix, controller, path, sourcePositions, scope); 3711 } else if (grandParent != null && grandParent.getKind() == Tree.Kind.CLASS && 3712 parent != null && parent.getKind() == Tree.Kind.VARIABLE && unwrapErrTree(((VariableTree)parent).getInitializer()) == tree) { 3713 controller.toPhase(Phase.ELEMENTS_RESOLVED); 3714 TreeUtilities tu = controller.getTreeUtilities(); 3715 final int initPos = (int)sourcePositions.getStartPosition(root, tree); 3716 String initText = controller.getText().substring(initPos, upToOffset ? offset : (int)sourcePositions.getEndPosition(root, tree)); 3717 final SourcePositions[] sp = new SourcePositions[1]; 3718 final ExpressionTree init = tu.parseVariableInitializer(initText, sp); 3719 final ExpressionStatementTree fake = new ExpressionStatementTree() { 3720 public Object accept(TreeVisitor v, Object p) { 3721 return v.visitExpressionStatement(this, p); 3722 } 3723 public ExpressionTree getExpression() { 3724 return init; 3725 } 3726 public Kind getKind() { 3727 return Tree.Kind.EXPRESSION_STATEMENT; 3728 } 3729 }; 3730 sourcePositions = new SourcePositionsImpl(fake, sourcePositions, sp[0], initPos, upToOffset ? offset : -1); 3731 Scope scope = controller.getTrees().getScope(path); 3732 path = tu.pathFor(new TreePath(pPath, fake), offset, sourcePositions); 3733 if (upToOffset && sp[0].getEndPosition(root, init) + initPos > offset) { 3734 scope = tu.attributeTreeTo(init, scope, path.getLeaf()); 3735 } else { 3736 tu.attributeTree(init, scope); 3737 } 3738 return new Env(offset, prefix, controller, path, sourcePositions, scope); 3739 } else if (parent != null && parent.getKind() == Tree.Kind.CLASS && tree.getKind() == Tree.Kind.VARIABLE && 3740 ((VariableTree)tree).getInitializer() != null && orig == path && sourcePositions.getStartPosition(root, ((VariableTree)tree).getInitializer()) <= offset) { 3741 controller.toPhase(Phase.ELEMENTS_RESOLVED); 3742 TreeUtilities tu = controller.getTreeUtilities(); 3743 tree = ((VariableTree)tree).getInitializer(); 3744 final int initPos = (int)sourcePositions.getStartPosition(root, tree); 3745 String initText = controller.getText().substring(initPos, offset); 3746 final SourcePositions[] sp = new SourcePositions[1]; 3747 final ExpressionTree init = tu.parseVariableInitializer(initText, sp); 3748 Scope scope = controller.getTrees().getScope(new TreePath(path, tree)); 3749 final ExpressionStatementTree fake = new ExpressionStatementTree() { 3750 public Object accept(TreeVisitor v, Object p) { 3751 return v.visitExpressionStatement(this, p); 3752 } 3753 public ExpressionTree getExpression() { 3754 return init; 3755 } 3756 public Kind getKind() { 3757 return Tree.Kind.EXPRESSION_STATEMENT; 3758 } 3759 }; 3760 sourcePositions = new SourcePositionsImpl(fake, sourcePositions, sp[0], initPos, offset); 3761 path = tu.pathFor(new TreePath(path, fake), offset, sourcePositions); 3762 tu.attributeTree(init, scope); 3763 return new Env(offset, prefix, controller, path, sourcePositions, scope); 3764 } 3765 return null; 3766 } 3767 3768 private class SourcePositionsImpl extends TreeScanner<Void , Tree> implements SourcePositions { 3769 3770 private Tree root; 3771 private SourcePositions original; 3772 private SourcePositions modified; 3773 private int startOffset; 3774 private int endOffset; 3775 3776 private boolean found; 3777 3778 private SourcePositionsImpl(Tree root, SourcePositions original, SourcePositions modified, int startOffset, int endOffset) { 3779 this.root = root; 3780 this.original = original; 3781 this.modified = modified; 3782 this.startOffset = startOffset; 3783 this.endOffset = endOffset; 3784 } 3785 3786 public long getStartPosition(CompilationUnitTree compilationUnitTree, Tree tree) { 3787 if (tree == root) 3788 return startOffset; 3789 found = false; 3790 scan(root, tree); 3791 return found ? modified.getStartPosition(compilationUnitTree, tree) + startOffset : original.getStartPosition(compilationUnitTree, tree); 3792 } 3793 3794 public long getEndPosition(CompilationUnitTree compilationUnitTree, Tree tree) { 3795 if (endOffset >= 0 && (tree == root)) 3796 return endOffset; 3797 found = false; 3798 scan(root, tree); 3799 return found ? modified.getEndPosition(compilationUnitTree, tree) + startOffset : original.getEndPosition(compilationUnitTree, tree); 3800 } 3801 3802 public Void scan(Tree node, Tree p) { 3803 if (node == p) 3804 found = true; 3805 else 3806 super.scan(node, p); 3807 return null; 3808 } 3809 } 3810 3811 private class Env { 3812 private int offset; 3813 private String prefix; 3814 private CompilationController controller; 3815 private TreePath path; 3816 private SourcePositions sourcePositions; 3817 private Scope scope; 3818 private Collection<? extends Element> refs = null; 3819 private boolean insideForEachExpressiion = false; 3820 private Set<? extends TypeMirror> smartTypes = null; 3821 3822 private Env(int offset, String prefix, CompilationController controller, TreePath path, SourcePositions sourcePositions, Scope scope) { 3823 this.offset = offset; 3824 this.prefix = prefix; 3825 this.controller = controller; 3826 this.path = path; 3827 this.sourcePositions = sourcePositions; 3828 this.scope = scope; 3829 } 3830 3831 public int getOffset() { 3832 return offset; 3833 } 3834 3835 public String getPrefix() { 3836 return prefix; 3837 } 3838 3839 public CompilationController getController() { 3840 return controller; 3841 } 3842 3843 public CompilationUnitTree getRoot() { 3844 return path.getCompilationUnit(); 3845 } 3846 3847 public TreePath getPath() { 3848 return path; 3849 } 3850 3851 public SourcePositions getSourcePositions() { 3852 return sourcePositions; 3853 } 3854 3855 public Scope getScope() throws IOException { 3856 if (scope == null) { 3857 controller.toPhase(Phase.ELEMENTS_RESOLVED); 3858 scope = controller.getTreeUtilities().scopeFor(offset); 3859 } 3860 return scope; 3861 } 3862 3863 public Collection<? extends Element> getForwardReferences() { 3864 if (refs == null) 3865 refs = Utilities.getForwardReferences(path, offset, sourcePositions, controller.getTrees()); 3866 return refs; 3867 } 3868 3869 public void insideForEachExpressiion() { 3870 this.insideForEachExpressiion = true; 3871 } 3872 3873 public boolean isInsideForEachExpressiion() { 3874 return insideForEachExpressiion; 3875 } 3876 3877 public Set<? extends TypeMirror> getSmartTypes() throws IOException { 3878 if (smartTypes == null) 3879 smartTypes = JavaCompletionQuery.this.getSmartTypes(this); 3880 return smartTypes; 3881 } 3882 } 3883 } 3884} 3885 | Popular Tags |