public @NotNull Pair<@Nullable StubTree, @Nullable FileElement> getStubTreeOrFileElement() {
    assertReadAccessAllowed();

    StubTree derefd = derefStub();
    FileElement treeElement = getTreeElement();
    if (derefd != null || treeElement != null) {
      return Pair.create(derefd, treeElement);
    }

    if (Boolean.TRUE.equals(getUserData(BUILDING_STUB)) || myLoadingAst || getElementTypeForStubBuilder() == null) {
      return Pair.empty();
    }

    VirtualFile vFile = getVirtualFile();

    ObjectStubTree<?> tree = StubTreeLoader.getInstance().readOrBuild(getProject(), vFile, this);
    if (!(tree instanceof StubTree)) return Pair.empty();
    FileViewProvider viewProvider = getViewProvider();
    List<Pair<IStubFileElementType<?>, PsiFile>> roots = StubTreeBuilder.getStubbedRoots(viewProvider);

    try {
      synchronized (myPsiLock) {
        FileElement treeElementOnLock = getTreeElement();
        StubTree dereferencedOnLock = derefStub();
        if (dereferencedOnLock != null || treeElementOnLock != null) {
          return Pair.create(dereferencedOnLock, treeElementOnLock);
        }

        PsiFileStubImpl<?> baseRoot = (PsiFileStubImpl<?>)((StubTree)tree).getRoot();
        if (!baseRoot.rootsAreSet()) {
          LOG.error("Stub roots must be set when stub tree was read or built with StubTreeLoader");
          return Pair.empty();
        }
        PsiFileStub<?>[] stubRoots = baseRoot.getStubRoots();
        if (stubRoots.length != roots.size()) {
          com.intellij.util.Function<PsiFileStub<?>, String> stubToString =
            stub -> "{" + stub.getClass().getSimpleName() + " " + stub.getType().getLanguage() + "}";
          LOG.error("readOrBuilt roots = " + StringUtil.join(stubRoots, stubToString, ", ") + "; " +
                    StubTreeLoader.getFileViewProviderMismatchDiagnostics(viewProvider));
          rebuildStub();
          return Pair.empty();
        }

        StubTree result = null;
        for (int i = 0; i < roots.size(); i++) {
          PsiFileImpl eachPsiRoot = (PsiFileImpl)roots.get(i).second;
          if (eachPsiRoot.derefStub() == null) {
            StubTree stubTree = eachPsiRoot.setStubTree(stubRoots[i]);
            if (eachPsiRoot == this) {
              result = stubTree;
            }
          }
        }

        assert result != null : "Current file not in root list: " + roots + ", vp=" + viewProvider;
        return Pair.create(result, null);
      }
    }
    catch (StubTreeLoader.StubTreeAndIndexUnmatchCoarseException e) {
      throw e.createCompleteException();
    }
  }
public @NotNull Pair<@Nullable StubTree, @Nullable FileElement> getStubTreeOrFileElement()