KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > java > JavaCompletionProvider


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

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 JavaDoc;
26 import java.util.*;
27 import java.util.logging.Logger JavaDoc;
28 import java.util.logging.Level JavaDoc;
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 JavaDoc;
36 import javax.swing.text.BadLocationException JavaDoc;
37 import javax.swing.text.Document JavaDoc;
38 import javax.swing.text.JTextComponent JavaDoc;
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 /**
58  *
59  * @author Dusan Balek
60  */

61 public class JavaCompletionProvider implements CompletionProvider {
62     
63     public int getAutoQueryTypes(JTextComponent JavaDoc component, String JavaDoc 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 JavaDoc 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 JavaDoc {
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 JavaDoc ERROR = "<error>"; //NOI18N
99
private static final String JavaDoc INIT = "<init>"; //NOI18N
100
private static final String JavaDoc SPACE = " "; //NOI18N
101
private static final String JavaDoc COLON = ":"; //NOI18N
102
private static final String JavaDoc SEMI = ";"; //NOI18N
103
private static final String JavaDoc EMPTY = ""; //NOI18N
104

105         private static final String JavaDoc ABSTRACT_KEYWORD = "abstract"; //NOI18N
106
private static final String JavaDoc ASSERT_KEYWORD = "assert"; //NOI18N
107
private static final String JavaDoc BOOLEAN_KEYWORD = "boolean"; //NOI18N
108
private static final String JavaDoc BREAK_KEYWORD = "break"; //NOI18N
109
private static final String JavaDoc BYTE_KEYWORD = "byte"; //NOI18N
110
private static final String JavaDoc CASE_KEYWORD = "case"; //NOI18N
111
private static final String JavaDoc CATCH_KEYWORD = "catch"; //NOI18N
112
private static final String JavaDoc CHAR_KEYWORD = "char"; //NOI18N
113
private static final String JavaDoc CLASS_KEYWORD = "class"; //NOI18N
114
private static final String JavaDoc CONTINUE_KEYWORD = "continue"; //NOI18N
115
private static final String JavaDoc DEFAULT_KEYWORD = "default"; //NOI18N
116
private static final String JavaDoc DOUBLE_KEYWORD = "double"; //NOI18N
117
private static final String JavaDoc ENUM_KEYWORD = "enum"; //NOI18N
118
private static final String JavaDoc EXTENDS_KEYWORD = "extends"; //NOI18N
119
private static final String JavaDoc FALSE_KEYWORD = "false"; //NOI18N
120
private static final String JavaDoc FINAL_KEYWORD = "final"; //NOI18N
121
private static final String JavaDoc FINALLY_KEYWORD = "finally"; //NOI18N
122
private static final String JavaDoc FLOAT_KEYWORD = "float"; //NOI18N
123
private static final String JavaDoc FOR_KEYWORD = "for"; //NOI18N
124
private static final String JavaDoc IF_KEYWORD = "if"; //NOI18N
125
private static final String JavaDoc IMPLEMENTS_KEYWORD = "implements"; //NOI18N
126
private static final String JavaDoc IMPORT_KEYWORD = "import"; //NOI18N
127
private static final String JavaDoc INSTANCEOF_KEYWORD = "instanceof"; //NOI18N
128
private static final String JavaDoc INT_KEYWORD = "int"; //NOI18N
129
private static final String JavaDoc INTERFACE_KEYWORD = "interface"; //NOI18N
130
private static final String JavaDoc LONG_KEYWORD = "long"; //NOI18N
131
private static final String JavaDoc NATIVE_KEYWORD = "native"; //NOI18N
132
private static final String JavaDoc NEW_KEYWORD = "new"; //NOI18N
133
private static final String JavaDoc NULL_KEYWORD = "null"; //NOI18N
134
private static final String JavaDoc PACKAGE_KEYWORD = "package"; //NOI18N
135
private static final String JavaDoc PRIVATE_KEYWORD = "private"; //NOI18N
136
private static final String JavaDoc PROTECTED_KEYWORD = "protected"; //NOI18N
137
private static final String JavaDoc PUBLIC_KEYWORD = "public"; //NOI18N
138
private static final String JavaDoc RETURN_KEYWORD = "return"; //NOI18N
139
private static final String JavaDoc SHORT_KEYWORD = "short"; //NOI18N
140
private static final String JavaDoc STATIC_KEYWORD = "static"; //NOI18N
141
private static final String JavaDoc STRICT_KEYWORD = "strictfp"; //NOI18N
142
private static final String JavaDoc SUPER_KEYWORD = "super"; //NOI18N
143
private static final String JavaDoc SWITCH_KEYWORD = "switch"; //NOI18N
144
private static final String JavaDoc SYNCHRONIZED_KEYWORD = "synchronized"; //NOI18N
145
private static final String JavaDoc THIS_KEYWORD = "this"; //NOI18N
146
private static final String JavaDoc THROW_KEYWORD = "throw"; //NOI18N
147
private static final String JavaDoc THROWS_KEYWORD = "throws"; //NOI18N
148
private static final String JavaDoc TRANSIENT_KEYWORD = "transient"; //NOI18N
149
private static final String JavaDoc TRUE_KEYWORD = "true"; //NOI18N
150
private static final String JavaDoc TRY_KEYWORD = "try"; //NOI18N
151
private static final String JavaDoc VOID_KEYWORD = "void"; //NOI18N
152
private static final String JavaDoc VOLATILE_KEYWORD = "volatile"; //NOI18N
153
private static final String JavaDoc WHILE_KEYWORD = "while"; //NOI18N
154

155         private static final String JavaDoc[] PRIM_KEYWORDS = new String JavaDoc[] {
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 JavaDoc[] STATEMENT_KEYWORDS = new String JavaDoc[] {
161             FOR_KEYWORD, SWITCH_KEYWORD, SYNCHRONIZED_KEYWORD, TRY_KEYWORD,
162             VOID_KEYWORD, WHILE_KEYWORD
163         };
164         
165         private static final String JavaDoc[] STATEMENT_SPACE_KEYWORDS = new String JavaDoc[] {
166             ASSERT_KEYWORD, NEW_KEYWORD, THROW_KEYWORD
167         };
168         
169         private static final String JavaDoc[] BLOCK_KEYWORDS = new String JavaDoc[] {
170             ASSERT_KEYWORD, CLASS_KEYWORD, FINAL_KEYWORD, NEW_KEYWORD,
171             THROW_KEYWORD
172         };
173
174         private static final String JavaDoc[] CLASS_BODY_KEYWORDS = new String JavaDoc[] {
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 JavaDoc toolTip;
183         private CompletionDocumentation documentation;
184         private int anchorOffset;
185
186         private JTextComponent JavaDoc component;
187
188         private int queryType;
189         private int caretOffset;
190         private String JavaDoc 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 JavaDoc
200         protected void preQueryUpdate(JTextComponent JavaDoc 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 JavaDoc e) {
207                 }
208             }
209             Completion.get().hideCompletion();
210         }
211         
212         @Override JavaDoc
213         protected void prepareQuery(JTextComponent JavaDoc component) {
214             this.component = component;
215         }
216
217         @Override JavaDoc
218         protected void query(CompletionResultSet resultSet, Document JavaDoc 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")); //NOI18N
235
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 JavaDoc ioe) {
251                 Exceptions.printStackTrace(ioe);
252             } finally {
253                 resultSet.finish();
254             }
255         }
256         
257         @Override JavaDoc
258         protected boolean canFilter(JTextComponent JavaDoc 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 JavaDoc prefix = component.getDocument().getText(offset, newOffset - offset);
269                             filterPrefix = getJavaIdentifierPart(prefix);
270                             if (filterPrefix != null && filterPrefix.length() == 0)
271                                 anchorOffset = newOffset;
272                         } catch (BadLocationException JavaDoc 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 JavaDoc ex) {}
286                 return (filterPrefix != null && filterPrefix.indexOf(',') == -1 && filterPrefix.indexOf('(') == -1 && filterPrefix.indexOf(')') == -1); // NOI18N
287
}
288             return false;
289         }
290         
291         @Override JavaDoc
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 JavaDoc ex) {
307                 Exceptions.printStackTrace(ex);
308             }
309             resultSet.finish();
310         }
311         
312         public void run(CompilationController controller) throws Exception JavaDoc {
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 JavaDoc {
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 JavaDoc>> 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 JavaDoc 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); //NOI18N
406
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 JavaDoc>> 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); //NOI18N
437
return;
438                     }
439                 }
440                 lastTree = tree;
441                 path = path.getParentPath();
442             }
443         }
444         
445         private void resolveDocumentation(CompilationController controller) throws IOException JavaDoc {
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 JavaDoc {
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 JavaDoc {
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 JavaDoc 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 JavaDoc {
644             int offset = env.getOffset();
645             String JavaDoc 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 JavaDoc headerText = controller.getText().substring(startPos, offset);
655             int idx = headerText.indexOf('{'); //NOI18N
656
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(",")) { //NOI18N
673
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('>'); //NOI18N
703
if (idx > -1) { //NOI18N
704
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 JavaDoc {
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 JavaDoc 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("=")) { //NOI18N
784
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 JavaDoc {
793             int offset = env.getOffset();
794             String JavaDoc 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(",")) { //NOI18N
829
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); //NOI18N
848
}
849                 return;
850             }
851             String JavaDoc headerText = controller.getText().substring(startPos, offset);
852             int parStart = headerText.indexOf('('); //NOI18N
853
if (parStart >= 0) {
854                 int parEnd = headerText.indexOf(')', parStart); //NOI18N
855
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); //NOI18N
867
} 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)) { //NOI18N
884
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 JavaDoc {
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 JavaDoc {
961             int offset = env.getOffset();
962             String JavaDoc 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 JavaDoc> names = new HashSet<String JavaDoc>();
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 JavaDoc name = e.getSimpleName().toString();
1009                        if (hasOnlyValue < 2)
1010                            hasOnlyValue += "value".equals(name) ? 1 : 2; //NOI18N
1011
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 JavaDoc {
1021            int offset = env.getOffset();
1022            String JavaDoc 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 JavaDoc {
1046            int offset = env.getOffset();
1047            String JavaDoc 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 JavaDoc {
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 JavaDoc text = env.getController().getText().substring(blockPos, offset);
1073            if (text.indexOf('{') < 0) { //NOI18N
1074
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 JavaDoc 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 JavaDoc {
1111            int offset = env.getOffset();
1112            String JavaDoc 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")); //NOI18N
1202
} 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")); //NOI18N
1240
} 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")); //NOI18N
1257
} 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 JavaDoc typeName = Utilities.getElementName(el, true) + "." + prefix; //NOI18N
1298
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 JavaDoc typeName = Utilities.getElementName(el, true) + "." + prefix; //NOI18N
1325
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 JavaDoc {
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 JavaDoc {
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 JavaDoc 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; //NOI18N
1379
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 JavaDoc {
1405            int offset = env.getOffset();
1406            TreePath path = env.getPath();
1407            String JavaDoc 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); //NOI18N
1420
}
1421        }
1422        
1423        private void insideIf(Env env) throws IOException JavaDoc {
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 JavaDoc {
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 JavaDoc {
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 JavaDoc text = env.getController().getText().substring(lastTreePos, offset).trim();
1476                if (";".equals(text)) { //NOI18N
1477
localResult(env);
1478                    addValueKeywords(env);
1479                } else if (text.endsWith(")")) { //NOI18N
1480
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 JavaDoc {
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())) { //NOI18N
1510
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(")")) { //NOI18N
1517
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 JavaDoc {
1527            int offset = env.getOffset();
1528            String JavaDoc 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 JavaDoc {
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 JavaDoc {
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 JavaDoc {
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 JavaDoc {
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 JavaDoc aatText = env.getController().getText().substring(aaTextStart, offset);
1612                    int bPos = aatText.indexOf('['); //NOI18N
1613
if (bPos > -1) {
1614                        localResult(env);
1615                        addValueKeywords(env);
1616                    }
1617                }
1618            }
1619        }
1620        
1621        private void insideNewArray(Env env) throws IOException JavaDoc {
1622            int offset = env.getOffset();
1623            TreePath path = env.getPath();
1624            NewArrayTree nat = (NewArrayTree)path.getLeaf();
1625            if (nat.getInitializers() != null) { // UFFF!!!!
1626
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 JavaDoc text = env.getController().getText().substring(lastPos, offset).trim();
1639                    if (",".equals(text)) { //NOI18N
1640
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 JavaDoc {
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 JavaDoc asText = env.getController().getText().substring(asTextStart, offset);
1683                    int eqPos = asText.indexOf('='); //NOI18N
1684
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 JavaDoc {
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 JavaDoc catText = env.getController().getText().substring(catTextStart, offset);
1708                    int eqPos = catText.indexOf('='); //NOI18N
1709
if (eqPos > -1) {
1710                        localResult(env);
1711                        addValueKeywords(env);
1712                    }
1713                }
1714            }
1715        }
1716        
1717        private void insideBinaryTree(Env env) throws IOException JavaDoc {
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 JavaDoc 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 JavaDoc {
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 JavaDoc coText = env.getController().getText().substring(coTextStart, env.getOffset()).trim();
1742                if (coText.endsWith("?") || coText.endsWith(":")) { //NOI18N
1743
localResult(env);
1744                    addValueKeywords(env);
1745                }
1746            }
1747        }
1748        
1749        private void insideExpressionStatement(Env env) throws IOException JavaDoc {
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 JavaDoc {
1833            int offset = env.getOffset();
1834            String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc {
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 JavaDoc {
2039            int offset = env.getOffset();
2040            final String JavaDoc 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 JavaDoc {
2123            int offset = env.getOffset();
2124            final String JavaDoc 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 JavaDoc 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 JavaDoc {
2219            int offset = env.getOffset();
2220            final String JavaDoc 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 JavaDoc {
2267            Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null;
2268            int offset = env.getOffset();
2269            final String JavaDoc 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 JavaDoc 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 JavaDoc {
2321            Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null;
2322            int offset = env.getOffset();
2323            final String JavaDoc 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 JavaDoc 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 JavaDoc prefix = env.getPrefix();
2410            Elements elements = env.getController().getElements();
2411            for(Element e : elem.getEnclosedElements()) {
2412                if (e.getKind() == ENUM_CONSTANT) {
2413                    String JavaDoc 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 JavaDoc {
2421            Set<? extends TypeMirror> smartTypes = queryType == COMPLETION_QUERY_TYPE ? env.getSmartTypes() : null;
2422            int offset = env.getOffset();
2423            String JavaDoc 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 JavaDoc 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 JavaDoc pkgName = pe.getQualifiedName() + "."; //NOI18N
2438
if (prefix != null && prefix.length() > 0)
2439                pkgName += prefix;
2440            addPackages(env, pkgName);
2441        }
2442        
2443        private void addPackages(Env env, String JavaDoc fqnPrefix) {
2444            int offset = env.getOffset();
2445            if (fqnPrefix == null)
2446                fqnPrefix = EMPTY;
2447            for (String JavaDoc 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 JavaDoc {
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 JavaDoc {
2465            int offset = env.getOffset();
2466            final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc {
2527            int offset = env.getOffset();
2528            String JavaDoc 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 JavaDoc kw, String JavaDoc 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 JavaDoc> kws = new ArrayList<String JavaDoc>();
2630            int offset = env.getOffset();
2631            String JavaDoc 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 JavaDoc 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 JavaDoc prefix = env.getPrefix();
2676            for (String JavaDoc 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 JavaDoc prefix = env.getPrefix();
2685            for (String JavaDoc kw : STATEMENT_KEYWORDS) {
2686                if (Utilities.startsWith(kw, prefix))
2687                    results.add(JavaCompletionItem.createKeywordItem(kw, null, offset, false));
2688            }
2689            for (String JavaDoc 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 JavaDoc 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 JavaDoc prefix = env.getPrefix();
2741            for (String JavaDoc kw : STATEMENT_KEYWORDS) {
2742                if (Utilities.startsWith(kw, prefix))
2743                    results.add(JavaCompletionItem.createKeywordItem(kw, null, offset, false));
2744            }
2745            for (String JavaDoc 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 JavaDoc 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 JavaDoc {
2778            int offset = env.getOffset();
2779            String JavaDoc 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 JavaDoc prefix = env.getPrefix();
2805            for (String JavaDoc 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 JavaDoc prefix = env.getPrefix();
2814            List<String JavaDoc> kws = new ArrayList<String JavaDoc>();
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 JavaDoc 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 JavaDoc prefix = env.getPrefix();
2834            List<String JavaDoc> kws = new ArrayList<String JavaDoc>();
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 JavaDoc kw : kws) {
2863                if (Utilities.startsWith(kw, prefix))
2864                    results.add(JavaCompletionItem.createKeywordItem(kw, SPACE, offset, false));
2865            }
2866            for (String JavaDoc 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 JavaDoc {
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 JavaDoc text = controller.getText().substring(caretOffset, nextMemberPos);
2898                int idx = text.indexOf('\n'); // NOI18N
2899
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 JavaDoc 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 JavaDoc simpleName) throws IOException JavaDoc {
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 JavaDoc simpleName) throws IOException JavaDoc {
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")); //NOI18N
3035
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(); //NOI18N
3038
} 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 JavaDoc getJavaIdentifierPart(String JavaDoc 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 JavaDoc 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 JavaDoc {
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 JavaDoc text = null;
3171                        if (lastInit == null) {
3172                            text = controller.getText().substring((int)sourcePositions.getStartPosition(root, fl), offset).trim();
3173                            int idx = text.indexOf('('); //NOI18N
3174
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; //NOI18N
3180
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('('); //NOI18N
3198
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 JavaDoc 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 JavaDoc 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("[")) //NOI18N
3330
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(",")) { //NOI18N
3353
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(")")) //NOI18N
3460
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 JavaDoc<? 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 JavaDoc text = env.getController().getText().substring(startPos, position).trim();
3506                if ("(".equals(text) || ",".equals(text)) //NOI18N
3507
return ret;
3508            }
3509            return null;
3510        }
3511        
3512        private List<List<String JavaDoc>> getMatchingParams(TypeMirror type, Iterable JavaDoc<? extends Element> elements, String JavaDoc name, TypeMirror[] argTypes, Types types) {
3513            List<List<String JavaDoc>> ret = new ArrayList<List<String JavaDoc>>();
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 JavaDoc>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 JavaDoc> paramStrings = new ArrayList<String JavaDoc>(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 JavaDoc sb = new StringBuffer JavaDoc();
3542                                    sb.append(Utilities.getTypeName(tIt.next(), false));
3543                                    if (varArgs && !tIt.hasNext())
3544                                        sb.delete(sb.length() - 2, sb.length()).append("..."); //NOI18N
3545
CharSequence JavaDoc veName = ve.getSimpleName();
3546                                    if (veName != null && veName.length() > 0) {
3547                                        sb.append(" "); // NOI18N
3548
sb.append(veName);
3549                                    }
3550                                    if (it.hasNext()) {
3551                                        sb.append(", "); // NOI18N
3552
}
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 JavaDoc<? extends Element> elements, String JavaDoc 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 JavaDoc {
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 JavaDoc {
3620            int offset = caretOffset;
3621            String JavaDoc prefix = null;
3622            if (upToOffset && offset > 0) {
3623                TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
3624                if (ts.move(offset) == 0) // When right at the token end
3625
ts.movePrevious(); // Move to previous token
3626
else
3627                    ts.moveNext(); // otherwise move to the token that "contains" the offset
3628
if (ts.offset() < offset && (ts.token().id() == JavaTokenId.IDENTIFIER || "keyword".equals(ts.token().id().primaryCategory()))) { //TODO: Use isKeyword(...) when available
3629
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 JavaDoc prefix, boolean upToOffset) throws IOException JavaDoc {
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 JavaDoc 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 JavaDoc 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 JavaDoc accept(TreeVisitor v, Object JavaDoc 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 JavaDoc 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 JavaDoc accept(TreeVisitor v, Object JavaDoc 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 JavaDoc, 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc {
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 JavaDoc {
3878                if (smartTypes == null)
3879                    smartTypes = JavaCompletionQuery.this.getSmartTypes(this);
3880                return smartTypes;
3881            }
3882        }
3883    }
3884}
3885
Popular Tags