private FileTrees reconcilePsi(@Nullable StubTree stubTree, @Nullable FileElement astRoot, boolean takePsiFromStubs)
    throws StubTreeLoader.StubTreeAndIndexUnmatchCoarseException {
    assert stubTree != null || astRoot != null;

    if ((stubTree == null || astRoot == null) && !hasCachedPsi()) {
      // there's only one source of PSI, nothing to reconcile
      return new FileTrees(myFile, myStub, myTreeElementPointer, null);
    }

    List<StubElement<?>> stubList = stubTree == null ? null : stubTree.getPlainList();
    List<CompositeElement> nodeList = astRoot == null ? null : astRoot.getStubbedSpine().getSpineNodes();
    List<PsiElement> srcSpine = stubList == null || nodeList == null
                                ? null
                                : getAllSpinePsi(takePsiFromStubs ? stubTree.getSpine() : astRoot.getStubbedSpine());

    try {
      return DebugUtil.performPsiModification("reconcilePsi", () -> {
        if (myRefToPsi != null) {
          assert myRefToPsi.length == (stubList != null ? stubList.size() : nodeList.size())
            : "Cached PSI count doesn't match actual one. " +
              "myRefToPsi.length=" + myRefToPsi.length + ", " +
              "stubList.size=" + (stubList == null ? "null" : stubList.size()) + ", " +
              "nodeList.size=" + (nodeList == null ? "null" : nodeList.size());
          bindSubstratesToCachedPsi(stubList, nodeList);
        }

        if (stubList != null && nodeList != null) {
          assert stubList.size() == nodeList.size() : "Stub count (" + stubList.size() + ") doesn't match " +
                                                      "stubbed node length (" + nodeList.size() + ")";

          FileTrees result = switchToSpineRefs(srcSpine);
          bindStubsWithAst(srcSpine, stubList, nodeList, takePsiFromStubs);
          return result;
        }
        return this;
      });
    }
    catch (Throwable e) {
      myFile.clearContent(PsiFileImpl.STUB_PSI_MISMATCH);
      myFile.rebuildStub();
      throw StubTreeLoader.getInstance().createCoarseExceptionStubTreeAndIndexDoNotMatch(stubTree, myFile, e, FileTreesPsiReconciliation);
    }
  }
private FileTrees reconcilePsi(@Nullable StubTree stubTree, @Nullable FileElement astRoot, boolean takePsiFromStubs)