in java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java [1579:1960]
private void insideMemberSelect(Env env) throws IOException {
int offset = env.getOffset();
String prefix = env.getPrefix();
TreePath path = env.getPath();
MemberSelectTree fa = (MemberSelectTree) path.getLeaf();
CompilationController controller = env.getController();
CompilationUnitTree root = env.getRoot();
SourcePositions sourcePositions = env.getSourcePositions();
int expEndPos = (int) sourcePositions.getEndPosition(root, fa.getExpression());
boolean afterDot = false;
boolean afterLt = false;
int openLtNum = 0;
JavaTokenId lastNonWhitespaceTokenId = null;
TokenSequence<JavaTokenId> ts = controller.getTokenHierarchy().tokenSequence(JavaTokenId.language());
ts.move(expEndPos);
while (ts.moveNext()) {
if (ts.offset() >= offset) {
break;
}
switch (ts.token().id()) {
case DOUBLE_LITERAL:
case FLOAT_LITERAL:
case FLOAT_LITERAL_INVALID:
case LONG_LITERAL:
case ELLIPSIS:
if (ts.offset() != expEndPos || ts.token().text().charAt(0) != '.') {
break;
}
case DOT:
afterDot = true;
break;
case LT:
afterLt = true;
openLtNum++;
break;
case GT:
openLtNum--;
break;
case GTGT:
openLtNum -= 2;
break;
case GTGTGT:
openLtNum -= 3;
break;
}
switch (ts.token().id()) {
case WHITESPACE:
case LINE_COMMENT:
case BLOCK_COMMENT:
case JAVADOC_COMMENT:
case JAVADOC_COMMENT_LINE_RUN:
break;
default:
lastNonWhitespaceTokenId = ts.token().id();
}
}
if (!afterDot) {
if (expEndPos <= offset) {
insideExpression(env, new TreePath(path, fa.getExpression()));
}
return;
}
if (openLtNum > 0) {
switch (lastNonWhitespaceTokenId) {
case QUESTION:
addKeyword(env, EXTENDS_KEYWORD, SPACE, false);
addKeyword(env, SUPER_KEYWORD, SPACE, false);
break;
case LT:
case COMMA:
addClassTypes(env, null);
break;
case EXTENDS:
case SUPER:
addClassTypes(env, null);
break;
}
} else if (lastNonWhitespaceTokenId != JavaTokenId.STAR) {
controller.toPhase(Phase.RESOLVED);
if (withinModuleName(env)) {
String fqnPrefix = fa.getExpression().toString() + '.';
anchorOffset = (int) sourcePositions.getStartPosition(root, fa);
addModuleNames(env, fqnPrefix, true);
return;
}
TreePath parentPath = path.getParentPath();
Tree parent = parentPath != null ? parentPath.getLeaf() : null;
TreePath grandParentPath = parentPath != null ? parentPath.getParentPath() : null;
Tree grandParent = grandParentPath != null ? grandParentPath.getLeaf() : null;
ExpressionTree exp = fa.getExpression();
TreePath expPath = new TreePath(path, exp);
TypeMirror type = controller.getTrees().getTypeMirror(expPath);
TypeMirror tempSwitchSelectorType;
AddSwitchRelatedItem switchItemAdder = addSwitchItemDefault;
AddSwitchRelatedItem tempSwitchItemAdder;
if (type != null) {
Element el = controller.getTrees().getElement(expPath);
TreeUtilities tu = controller.getTreeUtilities();
EnumSet<ElementKind> kinds;
DeclaredType baseType = null;
Set<TypeMirror> exs = null;
boolean inImport = false;
boolean insideNew = false;
boolean srcOnly = false;
if (TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind()) && ((ClassTree) parent).getExtendsClause() == fa) {
kinds = EnumSet.of(CLASS);
env.afterExtends();
} else if (TreeUtilities.CLASS_TREE_KINDS.contains(parent.getKind()) && ((ClassTree) parent).getImplementsClause().contains(fa)) {
kinds = EnumSet.of(INTERFACE);
} else if (parent.getKind() == Kind.PACKAGE) {
kinds = EnumSet.noneOf(ElementKind.class);
srcOnly = true;
} else if (parent.getKind() == Tree.Kind.IMPORT) {
inImport = true;
kinds = ((ImportTree) parent).isStatic() ? EnumSet.of(CLASS, ENUM, INTERFACE, ANNOTATION_TYPE, RECORD, FIELD, METHOD, ENUM_CONSTANT, RECORD_COMPONENT) : EnumSet.of(CLASS, ANNOTATION_TYPE, ENUM, INTERFACE, RECORD);
} else if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa) {
insideNew = true;
kinds = EnumSet.of(CLASS, INTERFACE, ANNOTATION_TYPE, RECORD);
if (grandParent.getKind() == Tree.Kind.THROW) {
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
}
} else if (parent.getKind() == Tree.Kind.PARAMETERIZED_TYPE && ((ParameterizedTypeTree) parent).getTypeArguments().contains(fa)) {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE);
} else if (parent.getKind() == Tree.Kind.ANNOTATION || parent.getKind() == Tree.Kind.TYPE_ANNOTATION) {
if (((AnnotationTree) parent).getAnnotationType() == fa) {
kinds = EnumSet.of(ANNOTATION_TYPE);
} else {
Iterator<? extends ExpressionTree> it = ((AnnotationTree) parent).getArguments().iterator();
if (it.hasNext()) {
ExpressionTree et = it.next();
if (et == fa || (et.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) et).getExpression() == fa)) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
}
}
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD, FIELD, METHOD, ENUM_CONSTANT, RECORD_COMPONENT);
}
} else if (parent.getKind() == Tree.Kind.ASSIGNMENT && ((AssignmentTree) parent).getExpression() == fa && grandParent != null && grandParent.getKind() == Tree.Kind.ANNOTATION) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
} else if (parent.getKind() == Tree.Kind.VARIABLE && ((VariableTree) parent).getType() == fa) {
if (grandParent.getKind() == Tree.Kind.CATCH) {
kinds = EnumSet.of(CLASS, INTERFACE);
if (!options.contains(Options.ALL_COMPLETION)) {
exs = controller.getTreeUtilities().getUncaughtExceptions(grandParentPath.getParentPath());
}
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD);
}
} else if (parent.getKind() == Tree.Kind.METHOD && ((MethodTree) parent).getThrows().contains(fa)) {
Types types = controller.getTypes();
if (!options.contains(Options.ALL_COMPLETION) && ((MethodTree) parent).getBody() != null) {
controller.toPhase(Phase.RESOLVED);
exs = controller.getTreeUtilities().getUncaughtExceptions(new TreePath(path, ((MethodTree) parent).getBody()));
Trees trees = controller.getTrees();
for (ExpressionTree thr : ((MethodTree) parent).getThrows()) {
if (sourcePositions.getEndPosition(root, thr) >= offset) {
break;
}
TypeMirror t = trees.getTypeMirror(new TreePath(path, thr));
for (Iterator<TypeMirror> it = exs.iterator(); it.hasNext();) {
if (types.isSubtype(it.next(), t)) {
it.remove();
}
}
}
}
kinds = EnumSet.of(CLASS, INTERFACE);
TypeElement te = controller.getElements().getTypeElement("java.lang.Throwable"); //NOI18N
if (te != null) {
baseType = controller.getTypes().getDeclaredType(te);
}
} else if (parent.getKind() == Tree.Kind.METHOD && ((MethodTree) parent).getDefaultValue() == fa) {
if (type.getKind() == TypeKind.ERROR && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el instanceof PackageElement) {
addPackageContent(env, (PackageElement) el, EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD), null, false, false);
} else if (type.getKind() == TypeKind.DECLARED) {
addMemberConstantsAndTypes(env, (DeclaredType) type, el);
}
return;
} else if (parent.getKind() == Tree.Kind.TYPE_PARAMETER) {
TypeParameterTree tpt = (TypeParameterTree) parent;
Trees trees = controller.getTrees();
boolean first = true;
for (Tree bound : tpt.getBounds()) {
int pos = (int) sourcePositions.getEndPosition(root, bound);
if (offset <= pos) {
break;
}
first = false;
env.addToExcludes(trees.getElement(new TreePath(parentPath, bound)));
}
kinds = first ? EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE) : EnumSet.of(ANNOTATION_TYPE, INTERFACE);
} else if (parent.getKind() == Tree.Kind.AND) {
TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, ((BinaryTree) parent).getLeftOperand()));
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) tm).asElement());
kinds = EnumSet.of(INTERFACE, ANNOTATION_TYPE);
} else if (tm != null && tm.getKind() == TypeKind.INTERSECTION) {
for (TypeMirror bound : ((IntersectionType) tm).getBounds()) {
if (bound.getKind() == TypeKind.DECLARED) {
env.addToExcludes(((DeclaredType) bound).asElement());
}
}
kinds = EnumSet.of(INTERFACE, ANNOTATION_TYPE);
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD, FIELD, METHOD, ENUM_CONSTANT, RECORD_COMPONENT);
}
} else if (afterLt) {
kinds = EnumSet.of(METHOD);
} else if (parent.getKind() == Tree.Kind.ENHANCED_FOR_LOOP && ((EnhancedForLoopTree) parent).getExpression() == fa) {
env.insideForEachExpression();
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD, FIELD, METHOD, ENUM_CONSTANT, RECORD_COMPONENT);
} else if (tu.getPathElementOfKind(Tree.Kind.EXPORTS, path) != null) {
kinds = EnumSet.noneOf(ElementKind.class);
srcOnly = true;
} else if (tu.getPathElementOfKind(Tree.Kind.PROVIDES, path) != null) {
kinds = withinProvidesService(env) ? EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE) : EnumSet.of(CLASS);
} else if (tu.getPathElementOfKind(Tree.Kind.USES, path) != null) {
kinds = EnumSet.of(ANNOTATION_TYPE, CLASS, INTERFACE);
} else if (parent.getKind() == Kind.CONSTANT_CASE_LABEL &&
grandParent != null &&
grandParent.getKind() == Kind.CASE &&
(tempSwitchSelectorType = getSwitchSelectorType(env, grandParentPath.getParentPath())) != null &&
tempSwitchSelectorType.getKind() == TypeKind.DECLARED &&
(tempSwitchItemAdder = itemAdderForSwitchOrNull(env, grandParentPath.getParentPath())) != null) {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD, ENUM_CONSTANT);
baseType = (DeclaredType) tempSwitchSelectorType;
switchItemAdder = tempSwitchItemAdder;
} else {
kinds = EnumSet.of(CLASS, ENUM, ANNOTATION_TYPE, INTERFACE, RECORD, FIELD, METHOD, ENUM_CONSTANT, RECORD_COMPONENT);
}
switch (type.getKind()) {
case TYPEVAR:
while (type != null && type.getKind() == TypeKind.TYPEVAR) {
type = ((TypeVariable) type).getUpperBound();
}
if (type == null) {
return;
}
type = controller.getTypes().capture(type);
case ARRAY:
case DECLARED:
case UNION:
case BOOLEAN:
case BYTE:
case CHAR:
case DOUBLE:
case FLOAT:
case INT:
case LONG:
case SHORT:
case VOID:
boolean b = exp.getKind() == Tree.Kind.PARENTHESIZED || exp.getKind() == Tree.Kind.TYPE_CAST;
while (b) {
if (exp.getKind() == Tree.Kind.PARENTHESIZED) {
exp = ((ParenthesizedTree) exp).getExpression();
expPath = new TreePath(expPath, exp);
} else if (exp.getKind() == Tree.Kind.TYPE_CAST) {
exp = ((TypeCastTree) exp).getExpression();
expPath = new TreePath(expPath, exp);
} else {
b = false;
}
}
el = controller.getTrees().getElement(expPath);
if (el != null && (el.getKind().isClass() || el.getKind().isInterface())) {
if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa && prefix != null) {
String typeName = controller.getElementUtilities().getElementName(el, true) + "." + prefix; //NOI18N
TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass());
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
addMembers(env, tm, ((DeclaredType) tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport, insideNew, false, false, switchItemAdder);
}
}
}
if (exs != null && !exs.isEmpty()) {
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED) {
Element e = ((DeclaredType) ex).asElement();
if (e.getEnclosingElement() == el && startsWith(env, e.getSimpleName().toString()) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && !Utilities.isExcluded(((TypeElement)e).getQualifiedName())) {
env.addToExcludes(e);
results.add(itemFactory.createTypeItem(env.getController(), (TypeElement) e, (DeclaredType) ex, anchorOffset, null, elements.isDeprecated(e), insideNew, insideNew || env.isInsideClass(), true, true, false));
}
}
}
} else {
if (el == null) {
if (exp.getKind() == Tree.Kind.ARRAY_TYPE) {
TypeMirror tm = type;
while (tm.getKind() == TypeKind.ARRAY) {
tm = ((ArrayType) tm).getComponentType();
}
if (tm.getKind().isPrimitive()) {
el = controller.getTypes().boxedClass((PrimitiveType) tm);
} else if (tm.getKind() == TypeKind.DECLARED) {
el = ((DeclaredType) tm).asElement();
}
} else if (exp.getKind() == Tree.Kind.PRIMITIVE_TYPE) {
if (type.getKind().isPrimitive()) {
el = controller.getTypes().boxedClass((PrimitiveType) type);
} else if (type.getKind() == TypeKind.VOID) {
el = controller.getElements().getTypeElement("java.lang.Void"); //NOI18N
}
}
}
addMembers(env, type, el, kinds, baseType, inImport, insideNew, false, false, switchItemAdder);
}
break;
default:
el = controller.getTrees().getElement(expPath);
if (type.getKind() == TypeKind.ERROR && el != null && el.getKind().isClass()) {
el = controller.getElements().getPackageElement(((TypeElement) el).getQualifiedName());
}
if (el != null && el.getKind() == PACKAGE) {
if (parent.getKind() == Tree.Kind.NEW_CLASS && ((NewClassTree) parent).getIdentifier() == fa && prefix != null) {
String typeName = controller.getElementUtilities().getElementName(el, true) + "." + prefix; //NOI18N
TypeMirror tm = controller.getTreeUtilities().parseType(typeName, env.getScope().getEnclosingClass());
if (tm != null && tm.getKind() == TypeKind.DECLARED) {
addMembers(env, tm, ((DeclaredType) tm).asElement(), EnumSet.of(CONSTRUCTOR), null, inImport, insideNew, false, false, switchItemAdder);
}
}
if (exs != null && !exs.isEmpty()) {
Elements elements = controller.getElements();
for (TypeMirror ex : exs) {
if (ex.getKind() == TypeKind.DECLARED) {
Element e = ((DeclaredType) ex).asElement();
if (e.getEnclosingElement() == el && startsWith(env, e.getSimpleName().toString()) && (Utilities.isShowDeprecatedMembers() || !elements.isDeprecated(e)) && !Utilities.isExcluded(((TypeElement)e).getQualifiedName())) {
env.addToExcludes(e);
switchItemAdder.addTypeItem(env.getController(), (TypeElement) e, (DeclaredType) ex, anchorOffset, env.getReferencesCount(), elements.isDeprecated(e), false, env.isInsideClass(), true, true, false);
}
}
}
}
addPackageContent(env, (PackageElement) el, kinds, baseType, insideNew, srcOnly, switchItemAdder);
if (results.isEmpty() && ((PackageElement) el).getQualifiedName() == el.getSimpleName()) {
// no package content? Check for unimported class
ClassIndex ci = controller.getClasspathInfo().getClassIndex();
if (el.getEnclosedElements().isEmpty() && ci.getPackageNames(el.getSimpleName() + ".", true, EnumSet.allOf(ClassIndex.SearchScope.class)).isEmpty()) {
Trees trees = controller.getTrees();
Scope scope = env.getScope();
for (ElementHandle<TypeElement> teHandle : ci.getDeclaredTypes(el.getSimpleName().toString(), ClassIndex.NameKind.SIMPLE_NAME, EnumSet.allOf(ClassIndex.SearchScope.class))) {
TypeElement te = teHandle.resolve(controller);
if (te != null && trees.isAccessible(scope, te)) {
addMembers(env, te.asType(), te, kinds, baseType, inImport, insideNew, true, false, switchItemAdder);
}
}
}
}
}
}
} else if (parent.getKind() == Tree.Kind.COMPILATION_UNIT && ((CompilationUnitTree) parent).getPackageName() == fa) {
PackageElement pe = controller.getElements().getPackageElement(fullName(exp));
if (pe != null) {
addPackageContent(env, pe, EnumSet.of(ElementKind.PACKAGE), null, false, true);
}
}
}
}