List<ResolveResult[]> (@NotNull PsiReferenceExpressionImpl expression, @NotNull PsiFile containingFile) { // to avoid SOE, resolve all qualifiers starting from the innermost PsiElement qualifier = expression.getQualifier(); if (qualifier == null) return Collections.emptyList(); List<ResolveResult[]> qualifiers = new SmartList<>(); ResolveCache resolveCache = ResolveCache.getInstance(containingFile.getProject()); boolean physical = containingFile.isPhysical(); qualifier.accept(new JavaRecursiveElementWalkingVisitor() { @Override public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) { if (!(expression instanceof PsiReferenceExpressionImpl)) { return; } ResolveResult[] cachedResults = resolveCache.getCachedResults(expression, physical, false, true); if (cachedResults != null) { return; } visitElement(expression); } @Override protected void elementFinished(@NotNull PsiElement element) { if (!(element instanceof PsiReferenceExpressionImpl)) return; PsiReferenceExpressionImpl expression = (PsiReferenceExpressionImpl)element; qualifiers.add(resolveCache.resolveWithCaching(expression, INSTANCE, true, false, containingFile)); } // walk only qualifiers, not their arguments and other associated stuff @Override public void visitExpressionList(@NotNull PsiExpressionList list) { } @Override public void visitLambdaExpression(@NotNull PsiLambdaExpression expression) { } @Override public void visitClass(@NotNull PsiClass aClass) { } }); return qualifiers; }