private Set getSmartTypesImpl()

in java/java.completion/src/org/netbeans/modules/java/completion/JavaCompletionTask.java [5758:6370]


    private Set<? extends TypeMirror> getSmartTypesImpl(Env env) throws IOException {
        int offset = env.getOffset();
        final CompilationController controller = env.getController();
        TreeUtilities tu = controller.getTreeUtilities();
        TreePath path = tu.pathFor(offset);
        Tree lastTree = null;
        int dim = 0;
        while (path != null) {
            Tree tree = path.getLeaf();
            switch (tree.getKind()) {
                case VARIABLE:
                    TypeMirror type = controller.getTrees().getTypeMirror(path);
                    if (type == null) {
                        return null;
                    }
                    while (dim-- > 0) {
                        if (type.getKind() == TypeKind.ARRAY) {
                            type = ((ArrayType) type).getComponentType();
                        } else {
                            return null;
                        }
                    }
                    return type != null ? Collections.singleton(type) : null;
                case ASSIGNMENT:
                    type = controller.getTrees().getTypeMirror(new TreePath(path, ((AssignmentTree) tree).getVariable()));
                    if (type == null) {
                        return null;
                    }
                    TreePath parentPath = path.getParentPath();
                    if (parentPath != null && parentPath.getLeaf().getKind() == Tree.Kind.ANNOTATION && type.getKind() == TypeKind.EXECUTABLE) {
                        type = ((ExecutableType) type).getReturnType();
                        while (dim-- > 0) {
                            if (type.getKind() == TypeKind.ARRAY) {
                                type = ((ArrayType) type).getComponentType();
                            } else {
                                return null;
                            }
                        }
                        if (type.getKind() == TypeKind.ARRAY) {
                            type = ((ArrayType) type).getComponentType();
                        }
                    }
                    return type != null ? Collections.singleton(type) : null;
                case RETURN:
                    TreePath methodOrLambdaPath = tu.getPathElementOfKind(EnumSet.of(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION), path);
                    if (methodOrLambdaPath == null) {
                        return null;
                    }
                    if (methodOrLambdaPath.getLeaf().getKind() == Tree.Kind.METHOD) {
                        Tree retTree = ((MethodTree) methodOrLambdaPath.getLeaf()).getReturnType();
                        if (retTree == null) {
                            return null;
                        }
                        type = controller.getTrees().getTypeMirror(new TreePath(methodOrLambdaPath, retTree));
                        if (type == null && JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) {
                            controller.toPhase(Phase.RESOLVED);
                            type = controller.getTrees().getTypeMirror(new TreePath(methodOrLambdaPath, retTree));
                        }
                        return type != null ? Collections.singleton(type) : null;
                    } else {
                        type = controller.getTrees().getTypeMirror(methodOrLambdaPath);
                        if (type != null && type.getKind() == TypeKind.DECLARED) {
                            ExecutableType descType = controller.getTypeUtilities().getDescriptorType((DeclaredType) type);
                            if (descType != null) {
                                return Collections.singleton(descType.getReturnType());
                            }
                        }
                    }
                    break;
                case THROW:
                    TreePath methodPath = tu.getPathElementOfKind(Tree.Kind.METHOD, path);
                    if (methodPath == null) {
                        return null;
                    }
                    HashSet<TypeMirror> ret = new HashSet<>();
                    Trees trees = controller.getTrees();
                    for (ExpressionTree thr : ((MethodTree) methodPath.getLeaf()).getThrows()) {
                        type = trees.getTypeMirror(new TreePath(methodPath, thr));
                        if (type == null && JavaSource.Phase.RESOLVED.compareTo(controller.getPhase()) > 0) {
                            controller.toPhase(Phase.RESOLVED);
                            type = trees.getTypeMirror(new TreePath(methodPath, thr));
                        }
                        if (type != null) {
                            ret.add(type);
                        }
                    }
                    return ret;
                case TRY:
                    TryTree tt = (TryTree) tree;
                    BlockTree tryBlock = tt.getBlock();
                    SourcePositions sourcePositions = env.getSourcePositions();
                    if (tryBlock != null && sourcePositions.getStartPosition(env.getRoot(), tryBlock) <= offset) {
                        return null;
                    }
                    TypeElement te = controller.getElements().getTypeElement("java.lang.AutoCloseable"); //NOI18N
                    return te != null ? Collections.singleton(controller.getTypes().getDeclaredType(te)) : null;
                case IF:
                    IfTree iff = (IfTree) tree;
                    return iff.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
                case WHILE_LOOP:
                    WhileLoopTree wl = (WhileLoopTree) tree;
                    return wl.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
                case DO_WHILE_LOOP:
                    DoWhileLoopTree dwl = (DoWhileLoopTree) tree;
                    return dwl.getCondition() == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
                case FOR_LOOP:
                    ForLoopTree fl = (ForLoopTree) tree;
                    Tree cond = fl.getCondition();
                    if (lastTree != null) {
                        if (cond instanceof ErroneousTree) {
                            Iterator<? extends Tree> itt = ((ErroneousTree) cond).getErrorTrees().iterator();
                            if (itt.hasNext()) {
                                cond = itt.next();
                            }
                        }
                        return cond == lastTree ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null;
                    }
                    sourcePositions = env.getSourcePositions();
                    CompilationUnitTree root = env.getRoot();
                    if (cond != null && sourcePositions.getEndPosition(root, cond) < offset) {
                        return null;
                    }
                    Tree lastInit = null;
                    for (Tree init : fl.getInitializer()) {
                        if (sourcePositions.getEndPosition(root, init) >= offset) {
                            return null;
                        }
                        lastInit = init;
                    }
                    String text;
                    if (lastInit == null) {
                        text = controller.getText().substring((int) sourcePositions.getStartPosition(root, fl), offset).trim();
                        int idx = text.indexOf('('); //NOI18N
                        if (idx >= 0) {
                            text = text.substring(idx + 1);
                        }
                    } else {
                        text = controller.getText().substring((int) sourcePositions.getEndPosition(root, lastInit), offset).trim();
                    }
                    return ";".equals(text) ? Collections.<TypeMirror>singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN)) : null; //NOI18N
                case ENHANCED_FOR_LOOP:
                    EnhancedForLoopTree efl = (EnhancedForLoopTree) tree;
                    Tree expr = efl.getExpression();
                    if (lastTree != null) {
                        if (expr instanceof ErroneousTree) {
                            Iterator<? extends Tree> itt = ((ErroneousTree) expr).getErrorTrees().iterator();
                            if (itt.hasNext()) {
                                expr = itt.next();
                            }
                        }
                        if (expr != lastTree) {
                            return null;
                        }
                    } else {
                        sourcePositions = env.getSourcePositions();
                        root = env.getRoot();
                        if (efl.getVariable() == null || sourcePositions.getEndPosition(root, efl.getVariable()) > offset) {
                            text = controller.getText().substring((int) sourcePositions.getStartPosition(root, efl), offset).trim();
                            int idx = text.indexOf('('); //NOI18N
                            if (idx >= 0) {
                                text = text.substring(idx + 1);
                            }
                        } else {
                            text = controller.getText().substring((int) sourcePositions.getEndPosition(root, efl.getVariable()), offset).trim();
                        }
                        if (!":".equals(text)) {
                            return null;
                        }
                    }
                    TypeMirror var = efl.getVariable() != null ? controller.getTrees().getTypeMirror(new TreePath(path, efl.getVariable())) : null;
                    return var != null ? Collections.singleton(var) : null;
                case SWITCH:
                    SwitchTree sw = (SwitchTree) tree;
                    if (sw.getExpression() != lastTree && sw.getExpression().getKind() != Tree.Kind.ERRONEOUS) {
                        return null;
                    }
                    ret = new HashSet<>();
                    Types types = controller.getTypes();
                    ret.add(controller.getTypes().getPrimitiveType(TypeKind.INT));
                    te = controller.getElements().getTypeElement("java.lang.Enum"); //NOI18N
                    if (te != null) {
                        ret.add(types.getDeclaredType(te));
                    }
                    if (controller.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
                        te = controller.getElements().getTypeElement("java.lang.String"); //NOI18N
                        if (te != null) {
                            ret.add(types.getDeclaredType(te));
                        }
                    }
                    return ret;
                case SWITCH_EXPRESSION:
                    SwitchExpressionTree sew = (SwitchExpressionTree) tree;
                    if (sew.getExpression() != lastTree && sew.getExpression().getKind() != Tree.Kind.ERRONEOUS) {
                        return null;
                    }
                    ret = new HashSet<>();
                    types = controller.getTypes();
                    ret.add(controller.getTypes().getPrimitiveType(TypeKind.INT));
                    te = controller.getElements().getTypeElement("java.lang.Enum"); //NOI18N
                    if (te != null) {
                        ret.add(types.getDeclaredType(te));
                    }
                    if (controller.getSourceVersion().compareTo(SourceVersion.RELEASE_7) >= 0) {
                        te = controller.getElements().getTypeElement("java.lang.String"); //NOI18N
                        if (te != null) {
                            ret.add(types.getDeclaredType(te));
                        }
                    }
                    return ret;
                case METHOD_INVOCATION:
                    MethodInvocationTree mi = (MethodInvocationTree) tree;
                    sourcePositions = env.getSourcePositions();
                    root = env.getRoot();
                    List<Tree> argTypes = getArgumentsUpToPos(env, mi.getArguments(), (int) sourcePositions.getEndPosition(root, mi.getMethodSelect()), lastTree != null ? (int) sourcePositions.getStartPosition(root, lastTree) : offset, true);
                    if (argTypes != null) {
                        TypeMirror[] args = new TypeMirror[argTypes.size()];
                        int j = 0;
                        for (Tree t : argTypes) {
                            args[j++] = controller.getTrees().getTypeMirror(new TreePath(path, t));
                        }
                        TypeMirror[] targs = null;
                        if (!mi.getTypeArguments().isEmpty()) {
                            targs = new TypeMirror[mi.getTypeArguments().size()];
                            j = 0;
                            for (Tree t : mi.getTypeArguments()) {
                                TypeMirror ta = controller.getTrees().getTypeMirror(new TreePath(path, t));
                                if (ta == null) {
                                    return null;
                                }
                                targs[j++] = ta;
                            }
                        }
                        Tree mid = mi.getMethodSelect();
                        path = new TreePath(path, mid);
                        TypeMirror typeMirror = controller.getTrees().getTypeMirror(path);
                        final ExecutableType midTM = typeMirror != null && typeMirror.getKind() == TypeKind.EXECUTABLE ? (ExecutableType) typeMirror : null;
                        final ExecutableElement midEl = midTM == null ? null : (ExecutableElement) controller.getTrees().getElement(path);
                        switch (mid.getKind()) {
                            case MEMBER_SELECT: {
                                String name = ((MemberSelectTree) mid).getIdentifier().toString();
                                ExpressionTree exp = ((MemberSelectTree) mid).getExpression();
                                path = new TreePath(path, exp);
                                final TypeMirror tm = controller.getTrees().getTypeMirror(path);
                                final Element el = controller.getTrees().getElement(path);
                                final Trees trs = controller.getTrees();
                                if (el != null && tm.getKind() == TypeKind.DECLARED) {
                                    final boolean isStatic = el.getKind().isClass() || el.getKind().isInterface() || el.getKind() == TYPE_PARAMETER;
                                    final boolean isSuperCall = el.getKind().isField() && el.getSimpleName().contentEquals(SUPER_KEYWORD);
                                    final Scope scope = env.getScope();
                                    TypeElement enclClass = scope.getEnclosingClass();
                                    final TypeMirror enclType = enclClass != null ? enclClass.asType() : null;
                                    ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
                                        @Override
                                        public boolean accept(Element e, TypeMirror t) {
                                            return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && trs.isAccessible(scope, e, (DeclaredType) (isSuperCall && enclType != null ? enclType : t));
                                        }
                                    };
                                    return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), name, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
                                }
                                return null;
                            }
                            case IDENTIFIER: {
                                String name = ((IdentifierTree) mid).getName().toString();
                                final Scope scope = env.getScope();
                                final Trees trs = controller.getTrees();
                                final TypeElement enclClass = scope.getEnclosingClass();
                                final boolean isStatic = enclClass != null ? (tu.isStaticContext(scope) || (env.getPath().getLeaf().getKind() == Tree.Kind.BLOCK && ((BlockTree) env.getPath().getLeaf()).isStatic())) : false;
                                if (SUPER_KEYWORD.equals(name) && enclClass != null) {
                                    ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
                                        @Override
                                        public boolean accept(Element e, TypeMirror t) {
                                            return e.getKind() == CONSTRUCTOR && trs.isAccessible(scope, e, (DeclaredType) t);
                                        }
                                    };
                                    TypeMirror superclass = enclClass.getSuperclass();
                                    return getMatchingArgumentTypes(superclass, controller.getElementUtilities().getMembers(superclass, acceptor), INIT, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
                                }
                                ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
                                    @Override
                                    public boolean accept(Element e, TypeMirror t) {
                                        return e.getKind() == METHOD && (!isStatic || e.getModifiers().contains(STATIC)) && trs.isAccessible(scope, e, (DeclaredType) t);
                                    }
                                };
                                return getMatchingArgumentTypes(enclClass != null ? enclClass.asType() : null, controller.getElementUtilities().getLocalMembersAndVars(scope, acceptor), THIS_KEYWORD.equals(name) ? INIT : name, args, targs, midEl, midTM, controller.getTypes(), controller.getTypeUtilities());
                            }
                        }
                    }
                    break;
                case NEW_CLASS:
                    NewClassTree nc = (NewClassTree) tree;
                    sourcePositions = env.getSourcePositions();
                    root = env.getRoot();
                    int idEndPos = (int) sourcePositions.getEndPosition(root, nc.getIdentifier());
                    if (idEndPos < 0) {
                        idEndPos = (int) sourcePositions.getStartPosition(root, nc);
                    }
                    if (idEndPos < 0 || idEndPos >= offset || controller.getText().substring(idEndPos, offset).indexOf('(') < 0) {
                        break;
                    }
                    argTypes = getArgumentsUpToPos(env, nc.getArguments(), idEndPos, lastTree != null ? (int) sourcePositions.getStartPosition(root, lastTree) : offset, true);
                    if (argTypes != null) {
                        trees = controller.getTrees();
                        TypeMirror[] args = new TypeMirror[argTypes.size()];
                        int j = 0;
                        for (Tree t : argTypes) {
                            args[j++] = trees.getTypeMirror(new TreePath(path, t));
                        }
                        TypeMirror[] targs = null;
                        if (!nc.getTypeArguments().isEmpty()) {
                            targs = new TypeMirror[nc.getTypeArguments().size()];
                            j = 0;
                            for (Tree t : nc.getTypeArguments()) {
                                TypeMirror ta = trees.getTypeMirror(new TreePath(path, t));
                                if (ta == null) {
                                    return null;
                                }
                                targs[j++] = ta;
                            }
                        }
                        Element elem = controller.getTrees().getElement(path);
                        ExecutableElement ncElem = elem != null && elem.getKind() == CONSTRUCTOR ? (ExecutableElement) elem : null;
                        TypeMirror ncTM = ncElem != null ? ncElem.asType() : null;
                        ExecutableType ncType = ncTM != null && ncTM.getKind() == TypeKind.EXECUTABLE ? (ExecutableType) ncTM : null;
                        Tree mid = nc.getIdentifier();
                        path = new TreePath(path, mid);
                        TypeMirror tm = trees.getTypeMirror(path);
                        if (tm != null && tm.getKind() == TypeKind.ERROR && path.getLeaf().getKind() == Tree.Kind.PARAMETERIZED_TYPE) {
                            path = new TreePath(path, ((ParameterizedTypeTree) path.getLeaf()).getType());
                            tm = trees.getTypeMirror(path);
                        }
                        final Element el = controller.getTrees().getElement(path);
                        final Trees trs = controller.getTrees();
                        if (el != null && tm.getKind() == TypeKind.DECLARED) {
                            final Scope scope = env.getScope();
                            final boolean isAnonymous = nc.getClassBody() != null || el.getKind().isInterface() || el.getModifiers().contains(ABSTRACT);
                            ElementUtilities.ElementAcceptor acceptor = new ElementUtilities.ElementAcceptor() {
                                @Override
                                public boolean accept(Element e, TypeMirror t) {
                                    return e.getKind() == CONSTRUCTOR && (trs.isAccessible(scope, e, (DeclaredType) t) || isAnonymous && e.getModifiers().contains(PROTECTED));
                                }
                            };
                            return getMatchingArgumentTypes(tm, controller.getElementUtilities().getMembers(tm, acceptor), INIT, args, targs, ncElem, ncType, controller.getTypes(), controller.getTypeUtilities());
                        }
                        return null;
                    }
                    break;
                case NEW_ARRAY:
                    NewArrayTree nat = (NewArrayTree) tree;
                    Tree arrayType = nat.getType();
                    if (arrayType == null) {
                        dim++;
                        break;
                    }
                    sourcePositions = env.getSourcePositions();
                    root = env.getRoot();
                    int typeEndPos = (int) sourcePositions.getEndPosition(root, arrayType);
                    if (typeEndPos > offset) {
                        break;
                    }
                    text = controller.getText().substring(typeEndPos, offset);
                    if (text.indexOf('{') >= 0) {
                        type = controller.getTrees().getTypeMirror(new TreePath(path, arrayType));
                        while (dim-- > 0) {
                            if (type.getKind() == TypeKind.ARRAY) {
                                type = ((ArrayType) type).getComponentType();
                            } else {
                                return null;
                            }
                        }
                        return type != null ? Collections.singleton(type) : null;
                    }
                    if (text.trim().endsWith("[")) //NOI18N
                    {
                        return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.INT));
                    }
                    return null;
                case LAMBDA_EXPRESSION:
                    LambdaExpressionTree let = (LambdaExpressionTree) tree;
                    int pos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), let.getBody());
                    if (offset <= pos && findLastNonWhitespaceToken(env, tree, offset).token().id() != JavaTokenId.ARROW
                            || lastTree != null && lastTree.getKind() == Tree.Kind.BLOCK) {
                        break;
                    }
                    type = controller.getTrees().getTypeMirror(path);
                    if (type != null && type.getKind() == TypeKind.DECLARED) {
                        ExecutableType descType = controller.getTypeUtilities().getDescriptorType((DeclaredType) type);
                        if (descType != null) {
                            return Collections.singleton(descType.getReturnType());
                        }
                    }
                    break;
                case CASE:
                    CaseTree ct = (CaseTree) tree;
                    ExpressionTree exp = ct.getExpression();
                    if (exp != null && env.getSourcePositions().getEndPosition(env.getRoot(), exp) >= offset) {
                        parentPath = path.getParentPath();
                        if (parentPath.getLeaf().getKind() == Tree.Kind.SWITCH) {
                            exp = ((SwitchTree) parentPath.getLeaf()).getExpression();
                            type = controller.getTrees().getTypeMirror(new TreePath(parentPath, exp));
                            return type != null ? Collections.singleton(type) : null;
                        }
                    }
                    return null;
                case ANNOTATION:
                    AnnotationTree ann = (AnnotationTree) tree;
                    pos = (int) env.getSourcePositions().getStartPosition(env.getRoot(), ann.getAnnotationType());
                    if (offset <= pos) {
                        break;
                    }
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), ann.getAnnotationType());
                    if (offset < pos) {
                        break;
                    }
                    text = controller.getText().substring(pos, offset).trim();
                    if ("(".equals(text) || text.endsWith("{") || text.endsWith(",")) { //NOI18N
                        TypeElement el = (TypeElement) controller.getTrees().getElement(new TreePath(path, ann.getAnnotationType()));
                        if (el != null) {
                            for (Element ee : el.getEnclosedElements()) {
                                if (ee.getKind() == METHOD && "value".contentEquals(ee.getSimpleName())) {
                                    type = ((ExecutableElement) ee).getReturnType();
                                    while (dim-- > 0) {
                                        if (type.getKind() == TypeKind.ARRAY) {
                                            type = ((ArrayType) type).getComponentType();
                                        } else {
                                            return null;
                                        }
                                    }
                                    if (type.getKind() == TypeKind.ARRAY) {
                                        type = ((ArrayType) type).getComponentType();
                                    }
                                    return type != null ? Collections.singleton(type) : null;
                                }
                            }
                        }
                    }
                    return null;
                case REMAINDER_ASSIGNMENT:
                case AND_ASSIGNMENT:
                case XOR_ASSIGNMENT:
                case OR_ASSIGNMENT:
                case LEFT_SHIFT_ASSIGNMENT:
                case RIGHT_SHIFT_ASSIGNMENT:
                case UNSIGNED_RIGHT_SHIFT_ASSIGNMENT:
                    CompoundAssignmentTree cat = (CompoundAssignmentTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
                    if (offset <= pos) {
                        break;
                    }
                    ret = new HashSet<>();
                    types = controller.getTypes();
                    ret.add(types.getPrimitiveType(TypeKind.BYTE));
                    ret.add(types.getPrimitiveType(TypeKind.CHAR));
                    ret.add(types.getPrimitiveType(TypeKind.INT));
                    ret.add(types.getPrimitiveType(TypeKind.LONG));
                    ret.add(types.getPrimitiveType(TypeKind.SHORT));
                    return ret;
                case LEFT_SHIFT:
                case RIGHT_SHIFT:
                case UNSIGNED_RIGHT_SHIFT:
                case AND:
                case OR:
                case XOR:
                case REMAINDER:
                    BinaryTree bt = (BinaryTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
                    if (offset <= pos) {
                        break;
                    }
                case BITWISE_COMPLEMENT:
                    ret = new HashSet<>();
                    types = controller.getTypes();
                    ret.add(types.getPrimitiveType(TypeKind.BYTE));
                    ret.add(types.getPrimitiveType(TypeKind.CHAR));
                    ret.add(types.getPrimitiveType(TypeKind.INT));
                    ret.add(types.getPrimitiveType(TypeKind.LONG));
                    ret.add(types.getPrimitiveType(TypeKind.SHORT));
                    return ret;
                case CONDITIONAL_AND:
                case CONDITIONAL_OR:
                    bt = (BinaryTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
                    if (offset <= pos) {
                        break;
                    }
                case LOGICAL_COMPLEMENT:
                    return Collections.singleton(controller.getTypes().getPrimitiveType(TypeKind.BOOLEAN));
                case PLUS:
                case EQUAL_TO:
                case NOT_EQUAL_TO:
                    bt = (BinaryTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
                    if (offset <= pos) {
                        break;
                    }
                    TypeMirror tm = controller.getTrees().getTypeMirror(new TreePath(path, bt.getLeftOperand()));
                    if (tm == null) {
                        return null;
                    }
                    if (tm.getKind().isPrimitive()) {
                        ret = new HashSet<>();
                        types = controller.getTypes();
                        ret.add(types.getPrimitiveType(TypeKind.BYTE));
                        ret.add(types.getPrimitiveType(TypeKind.CHAR));
                        ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
                        ret.add(types.getPrimitiveType(TypeKind.FLOAT));
                        ret.add(types.getPrimitiveType(TypeKind.INT));
                        ret.add(types.getPrimitiveType(TypeKind.LONG));
                        ret.add(types.getPrimitiveType(TypeKind.SHORT));
                        return ret;
                    }
                    return Collections.singleton(tm);
                case PLUS_ASSIGNMENT:
                    cat = (CompoundAssignmentTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
                    if (offset <= pos) {
                        break;
                    }
                    tm = controller.getTrees().getTypeMirror(new TreePath(path, cat.getVariable()));
                    if (tm == null) {
                        return null;
                    }
                    if (tm.getKind().isPrimitive()) {
                        ret = new HashSet<>();
                        types = controller.getTypes();
                        ret.add(types.getPrimitiveType(TypeKind.BYTE));
                        ret.add(types.getPrimitiveType(TypeKind.CHAR));
                        ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
                        ret.add(types.getPrimitiveType(TypeKind.FLOAT));
                        ret.add(types.getPrimitiveType(TypeKind.INT));
                        ret.add(types.getPrimitiveType(TypeKind.LONG));
                        ret.add(types.getPrimitiveType(TypeKind.SHORT));
                        return ret;
                    }
                    return Collections.singleton(tm);
                case MULTIPLY_ASSIGNMENT:
                case DIVIDE_ASSIGNMENT:
                case MINUS_ASSIGNMENT:
                    cat = (CompoundAssignmentTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), cat.getVariable());
                    if (offset <= pos) {
                        break;
                    }
                    ret = new HashSet<>();
                    types = controller.getTypes();
                    ret.add(types.getPrimitiveType(TypeKind.BYTE));
                    ret.add(types.getPrimitiveType(TypeKind.CHAR));
                    ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
                    ret.add(types.getPrimitiveType(TypeKind.FLOAT));
                    ret.add(types.getPrimitiveType(TypeKind.INT));
                    ret.add(types.getPrimitiveType(TypeKind.LONG));
                    ret.add(types.getPrimitiveType(TypeKind.SHORT));
                    return ret;
                case DIVIDE:
                case GREATER_THAN:
                case GREATER_THAN_EQUAL:
                case LESS_THAN:
                case LESS_THAN_EQUAL:
                case MINUS:
                case MULTIPLY:
                    bt = (BinaryTree) tree;
                    pos = (int) env.getSourcePositions().getEndPosition(env.getRoot(), bt.getLeftOperand());
                    if (offset <= pos) {
                        break;
                    }
                case PREFIX_INCREMENT:
                case PREFIX_DECREMENT:
                case UNARY_PLUS:
                case UNARY_MINUS:
                    ret = new HashSet<>();
                    types = controller.getTypes();
                    ret.add(types.getPrimitiveType(TypeKind.BYTE));
                    ret.add(types.getPrimitiveType(TypeKind.CHAR));
                    ret.add(types.getPrimitiveType(TypeKind.DOUBLE));
                    ret.add(types.getPrimitiveType(TypeKind.FLOAT));
                    ret.add(types.getPrimitiveType(TypeKind.INT));
                    ret.add(types.getPrimitiveType(TypeKind.LONG));
                    ret.add(types.getPrimitiveType(TypeKind.SHORT));
                    return ret;
                case EXPRESSION_STATEMENT:
                    exp = ((ExpressionStatementTree) tree).getExpression();
                    if (exp.getKind() == Tree.Kind.PARENTHESIZED) {
                        text = controller.getText().substring((int) env.getSourcePositions().getStartPosition(env.getRoot(), exp), offset).trim();
                        if (text.endsWith(")")) //NOI18N
                        {
                            return null;
                        }
                    } else if (exp.getKind() == Tree.Kind.ERRONEOUS) {
                        Iterator<? extends Tree> it = ((ErroneousTree) exp).getErrorTrees().iterator();
                        if (it.hasNext()) {
                            Tree t = it.next();
                            if (t.getKind() == Tree.Kind.IDENTIFIER && YIELD_KEYWORD.contentEquals(((IdentifierTree) t).getName())) {
                                TreePath sPath = tu.getPathElementOfKind(Tree.Kind.SWITCH_EXPRESSION, path);
                                if (sPath != null) {
                                    path = sPath;
                                }
                            }
                        }
                    }
                    break;
                case YIELD:
                    TreePath sPath = tu.getPathElementOfKind(Tree.Kind.SWITCH_EXPRESSION, path);
                    if (sPath != null) {
                        path = sPath;
                    }
                    break;
                case BLOCK:
                    return null;
            }
            lastTree = tree;
            path = path.getParentPath();
        }
        return null;
    }