@Override
 @Nullable
 public int[] getBackwardIds(@NotNull VirtualFileWithId file) {
   if (!isUpToDate()) return null;
   int fileId = getAbsId((VirtualFile) file);
   return storage.get(fileId);
 }
  public RefResolveServiceImpl(
      final Project project,
      final MessageBus messageBus,
      final PsiManager psiManager,
      StartupManager startupManager,
      ApplicationEx application,
      ProjectFileIndex projectFileIndex)
      throws IOException {
    super(project);
    ((FutureTask) resolveProcess).run();
    myApplication = application;
    myProjectFileIndex = projectFileIndex;
    if (ENABLED) {
      log = new FileWriter(new File(getStorageDirectory(), "log.txt"));

      File dataFile = new File(getStorageDirectory(), "data");
      fileIsResolved = ConcurrentBitSet.readFrom(new File(getStorageDirectory(), "bitSet"));
      log("Read resolved file bitset: " + fileIsResolved);

      int maxId = FSRecords.getMaxId();
      PersistentIntList list = new PersistentIntList(dataFile, dataFile.exists() ? 0 : maxId);
      if (list.getSize() == maxId) {
        storage = list;
      } else {
        // just to be safe, re-resolve all if VFS files count changes since last restart
        list.dispose();
        storage = new PersistentIntList(dataFile, maxId);
        log(
            "VFS maxId changed: was "
                + list.getSize()
                + "; now: "
                + maxId
                + "; re-resolving everything");
        fileIsResolved.clear();
      }
      Disposer.register(this, storage);
      if (!application.isUnitTestMode()) {
        startupManager.runWhenProjectIsInitialized(
            () -> {
              initListeners(messageBus, psiManager);
              startThread();
            });
      }
      Disposer.register(
          this,
          new Disposable() {
            @Override
            public void dispose() {
              try {
                save();
                log.close();
              } catch (IOException e) {
                LOG.error(e);
              }
            }
          });
    } else {
      log = null;
      fileIsResolved = null;
      storage = null;
    }
  }
  @NotNull
  private TIntHashSet calcForwardRefs(
      @NotNull final VirtualFile virtualFile, @NotNull final ProgressIndicator indicator)
      throws IndexNotReadyException, ApplicationUtil.CannotRunReadActionException {

    final TIntHashSet forward = new TIntHashSet();

    final PsiFile psiFile =
        ApplicationUtil.tryRunReadAction(
            () -> {
              if (myProject.isDisposed()) throw new ProcessCanceledException();
              if (fileCount.incrementAndGet() % 100 == 0) {
                PsiManager.getInstance(myProject).dropResolveCaches();
                try {
                  storage.flush();
                  log.flush();
                } catch (IOException e) {
                  LOG.error(e);
                }
              }

              return PsiManager.getInstance(myProject).findFile(virtualFile);
            });
    final int fileId = getAbsId(virtualFile);
    if (psiFile != null) {
      bytesSize.addAndGet(virtualFile.getLength());
      final Set<PsiElement> resolved = new THashSet<PsiElement>();
      ApplicationUtil.tryRunReadAction(
          new Runnable() {
            @Override
            public void run() {
              indicator.checkCanceled();

              if (psiFile instanceof PsiJavaFile) {
                psiFile.accept(
                    new JavaRecursiveElementWalkingVisitor() {
                      @Override
                      public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
                        indicator.checkCanceled();
                        resolveReference(reference, resolved);

                        super.visitReferenceElement(reference);
                      }
                    });
              } else {
                psiFile.accept(
                    new PsiRecursiveElementWalkingVisitor() {
                      @Override
                      public void visitElement(PsiElement element) {
                        for (PsiReference reference : element.getReferences()) {
                          indicator.checkCanceled();
                          resolveReference(reference, resolved);
                        }
                        super.visitElement(element);
                      }
                    });
              }

              indicator.checkCanceled();
              for (PsiElement element : resolved) {
                PsiFile file = element.getContainingFile();
                addIdAndSuperClasses(file, forward);
              }
            }
          });
    }

    forward.remove(fileId);
    return forward;
  }
 private void save() throws IOException {
   log("Saving resolved file bitset: " + fileIsResolved);
   fileIsResolved.writeTo(new File(getStorageDirectory(), "bitSet"));
   log("list.size = " + storage.getSize());
 }