@Override
  public <K> Collection<K> getAllKeys(final StubIndexKey<K, ?> indexKey, @NotNull Project project) {
    FileBasedIndex.getInstance()
        .ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, GlobalSearchScope.allScope(project));

    final MyIndex<K> index = (MyIndex<K>) myIndices.get(indexKey);
    try {
      return index.getAllKeys();
    } catch (StorageException e) {
      forceRebuild(e);
    } catch (RuntimeException e) {
      final Throwable cause = e.getCause();
      if (cause instanceof IOException || cause instanceof StorageException) {
        forceRebuild(e);
      }
      throw e;
    }
    return Collections.emptyList();
  }
 public <K> void updateIndex(
     StubIndexKey key,
     int fileId,
     final Map<K, TIntArrayList> oldValues,
     Map<K, TIntArrayList> newValues) {
   try {
     final MyIndex<K> index = (MyIndex<K>) myIndices.get(key);
     index.updateWithMap(
         fileId,
         newValues,
         new Callable<Collection<K>>() {
           @Override
           public Collection<K> call() throws Exception {
             return oldValues.keySet();
           }
         });
   } catch (StorageException e) {
     LOG.info(e);
     requestRebuild();
   }
 }
 public void flush(StubIndexKey key) throws StorageException {
   final MyIndex<?> index = myIndices.get(key);
   index.flush();
 }
  @Override
  public <Key, Psi extends PsiElement> Collection<Psi> get(
      @NotNull final StubIndexKey<Key, Psi> indexKey,
      @NotNull final Key key,
      final Project project,
      final GlobalSearchScope scope) {
    FileBasedIndex.getInstance().ensureUpToDate(StubUpdatingIndex.INDEX_ID, project, scope);

    final PersistentFS fs = (PersistentFS) ManagingFS.getInstance();
    final PsiManager psiManager = PsiManager.getInstance(project);

    final List<Psi> result = new ArrayList<Psi>();
    final MyIndex<Key> index = (MyIndex<Key>) myIndices.get(indexKey);

    try {
      try {
        // disable up-to-date check to avoid locks on attempt to acquire index write lock while
        // holding at the same time the readLock for this index
        FileBasedIndex.disableUpToDateCheckForCurrentThread();
        index.getReadLock().lock();
        final ValueContainer<TIntArrayList> container = index.getData(key);

        container.forEach(
            new ValueContainer.ContainerAction<TIntArrayList>() {
              @Override
              public void perform(final int id, final TIntArrayList value) {
                final VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id);
                if (file != null && (scope == null || scope.contains(file))) {
                  StubTree stubTree = null;

                  final PsiFile _psifile = psiManager.findFile(file);
                  PsiFileWithStubSupport psiFile = null;

                  if (_psifile != null && !(_psifile instanceof PsiPlainTextFile)) {
                    if (_psifile instanceof PsiFileWithStubSupport) {
                      psiFile = (PsiFileWithStubSupport) _psifile;
                      stubTree = psiFile.getStubTree();
                      if (stubTree == null && psiFile instanceof PsiFileImpl) {
                        stubTree = ((PsiFileImpl) psiFile).calcStubTree();
                      }
                    }
                  }

                  if (stubTree != null || psiFile != null) {
                    if (stubTree == null) {
                      stubTree = StubTreeLoader.getInstance().readFromVFile(project, file);
                      if (stubTree != null) {
                        final List<StubElement<?>> plained = stubTree.getPlainList();
                        for (int i = 0; i < value.size(); i++) {
                          final StubElement<?> stub = plained.get(value.get(i));
                          final ASTNode tree = psiFile.findTreeForStub(stubTree, stub);

                          if (tree != null) {
                            if (tree.getElementType() == stubType(stub)) {
                              result.add((Psi) tree.getPsi());
                            } else {
                              String persistedStubTree =
                                  ((PsiFileStubImpl) stubTree.getRoot()).printTree();

                              String stubTreeJustBuilt =
                                  ((PsiFileStubImpl)
                                          ((IStubFileElementType)
                                                  ((PsiFileImpl) psiFile).getContentElementType())
                                              .getBuilder()
                                              .buildStubTree(psiFile))
                                      .printTree();

                              StringBuilder builder = new StringBuilder();
                              builder.append("Oops\n");

                              builder.append("Recorded stub:-----------------------------------\n");
                              builder.append(persistedStubTree);
                              builder.append(
                                  "\nAST built stub: ------------------------------------\n");
                              builder.append(stubTreeJustBuilt);
                              builder.append("\n");
                              LOG.info(builder.toString());

                              // requestReindex() may want to acquire write lock (for indices not
                              // requiring content loading)
                              // thus, because here we are under read lock, need to use invoke later
                              ApplicationManager.getApplication()
                                  .invokeLater(
                                      new Runnable() {
                                        @Override
                                        public void run() {
                                          FileBasedIndex.getInstance().requestReindex(file);
                                        }
                                      },
                                      ModalityState.NON_MODAL);
                            }
                          }
                        }
                      }
                    } else {
                      final List<StubElement<?>> plained = stubTree.getPlainList();
                      for (int i = 0; i < value.size(); i++) {
                        result.add((Psi) plained.get(value.get(i)).getPsi());
                      }
                    }
                  }
                }
              }
            });
      } finally {
        index.getReadLock().unlock();
        FileBasedIndex.enableUpToDateCheckForCurrentThread();
      }
    } catch (StorageException e) {
      forceRebuild(e);
    } catch (RuntimeException e) {
      final Throwable cause = FileBasedIndex.getCauseToRebuildIndex(e);
      if (cause != null) {
        forceRebuild(cause);
      } else {
        throw e;
      }
    }

    return result;
  }