示例#1
0
  @Override
  public ASTNode findTreeForStub(StubTree tree, StubElement<?> stub) {
    final Iterator<StubElement<?>> stubs = tree.getPlainList().iterator();
    final StubElement<?> root = stubs.next();
    final CompositeElement ast = calcTreeElement();
    if (root == stub) return ast;

    return findTreeForStub(ast, stubs, stub);
  }
示例#2
0
  @Nullable
  public static PsiElement restoreFromStubIndex(
      PsiFileWithStubSupport fileImpl,
      int index,
      @NotNull IStubElementType elementType,
      boolean throwIfNull) {
    if (fileImpl == null) {
      if (throwIfNull) throw new AssertionError("Null file");
      return null;
    }
    StubTree tree = fileImpl.getStubTree();

    boolean foreign = tree == null;
    if (foreign) {
      if (fileImpl instanceof PsiFileImpl) {
        // Note: as far as this is a realization of StubIndexReference
        // fileImpl#getContentElementType() must be instance of IStubFileElementType
        tree = ((PsiFileImpl) fileImpl).calcStubTree();
      } else {
        if (throwIfNull) throw new AssertionError("Not PsiFileImpl: " + fileImpl.getClass());
        return null;
      }
    }

    List<StubElement<?>> list = tree.getPlainList();
    if (index >= list.size()) {
      if (throwIfNull) throw new AssertionError("Too large index: " + index + ">=" + list.size());
      return null;
    }
    StubElement stub = list.get(index);

    if (stub.getStubType() != elementType) {
      if (throwIfNull)
        throw new AssertionError(
            "Element type mismatch: " + stub.getStubType() + "!=" + elementType);
      return null;
    }

    if (foreign) {
      final PsiElement cachedPsi = ((StubBase) stub).getCachedPsi();
      if (cachedPsi != null) return cachedPsi;

      final ASTNode ast = fileImpl.findTreeForStub(tree, stub);
      if (ast != null) {
        return ast.getPsi();
      }

      if (throwIfNull) throw new AssertionError("No AST for stub");
      return null;
    }
    return stub.getPsi();
  }
示例#3
0
  public static int calcStubIndex(@NotNull StubBasedPsiElement psi) {
    if (psi instanceof PsiFile) {
      return 0;
    }

    final StubElement liveStub = psi.getStub();
    if (liveStub != null) {
      return ((StubBase) liveStub).id;
    }

    PsiFileImpl file = (PsiFileImpl) psi.getContainingFile();
    final StubTree stubTree = file.calcStubTree();
    for (StubElement<?> stb : stubTree.getPlainList()) {
      if (stb.getPsi() == psi) {
        return ((StubBase) stb).id;
      }
    }

    return -1; // it is possible via custom stub builder intentionally not producing stubs for
    // stubbed elements
  }
示例#4
0
  protected void reportStubAstMismatch(String message, StubTree stubTree, Document cachedDocument) {
    rebuildStub();
    clearStub("stub-psi mismatch");
    scheduleDropCachesWithInvalidStubPsi();

    String msg = message;
    msg += "\n file=" + this;
    msg += ", modStamp=" + getModificationStamp();
    msg += "\n stub debugInfo=" + stubTree.getDebugInfo();
    msg += "\n document before=" + cachedDocument;

    ObjectStubTree latestIndexedStub =
        StubTreeLoader.getInstance().readFromVFile(getProject(), getVirtualFile());
    msg += "\nlatestIndexedStub=" + latestIndexedStub;
    if (latestIndexedStub != null) {
      msg +=
          "\n   same size="
              + (stubTree.getPlainList().size() == latestIndexedStub.getPlainList().size());
      msg += "\n   debugInfo=" + latestIndexedStub.getDebugInfo();
    }

    FileViewProvider viewProvider = getViewProvider();
    msg += "\n viewProvider=" + viewProvider;
    msg += "\n viewProvider stamp: " + viewProvider.getModificationStamp();

    VirtualFile file = viewProvider.getVirtualFile();
    msg += "; file stamp: " + file.getModificationStamp();
    msg += "; file modCount: " + file.getModificationCount();

    Document document = FileDocumentManager.getInstance().getCachedDocument(file);
    if (document != null) {
      msg += "\n doc saved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document);
      msg += "; doc stamp: " + document.getModificationStamp();
      msg += "; doc size: " + document.getTextLength();
      msg += "; committed: " + PsiDocumentManager.getInstance(getProject()).isCommitted(document);
    }

    throw new AssertionError(msg + "\n------------\n");
  }
示例#5
0
  private List<Pair<StubBasedPsiElementBase, CompositeElement>> calcStubAstBindings(
      final ASTNode root, final Document cachedDocument) {
    final StubTree stubTree = derefStub();
    if (stubTree == null) {
      return Collections.emptyList();
    }

    final Iterator<StubElement<?>> stubs = stubTree.getPlainList().iterator();
    stubs.next(); // Skip file stub;
    final List<Pair<StubBasedPsiElementBase, CompositeElement>> result =
        ContainerUtil.newArrayList();
    final StubBuilder builder = ((IStubFileElementType) getContentElementType()).getBuilder();

    LazyParseableElement.setSuppressEagerPsiCreation(true);
    try {
      ((TreeElement) root)
          .acceptTree(
              new RecursiveTreeElementWalkingVisitor() {
                @Override
                protected void visitNode(TreeElement node) {
                  CompositeElement parent = node.getTreeParent();
                  if (parent != null
                      && builder.skipChildProcessingWhenBuildingStubs(parent, node)) {
                    return;
                  }

                  IElementType type = node.getElementType();
                  if (type instanceof IStubElementType
                      && ((IStubElementType) type).shouldCreateStub(node)) {
                    if (!stubs.hasNext()) {
                      reportStubAstMismatch(
                          "Stub list is less than AST, last AST element: "
                              + node.getElementType()
                              + " "
                              + node,
                          stubTree,
                          cachedDocument);
                    }

                    final StubElement stub = stubs.next();
                    if (stub.getStubType() != node.getElementType()) {
                      reportStubAstMismatch(
                          "Stub and PSI element type mismatch in "
                              + getName()
                              + ": stub "
                              + stub
                              + ", AST "
                              + node.getElementType()
                              + "; "
                              + node,
                          stubTree,
                          cachedDocument);
                    }

                    PsiElement psi = stub.getPsi();
                    assert psi != null
                        : "Stub " + stub + " (" + stub.getClass() + ") has returned null PSI";
                    result.add(Pair.create((StubBasedPsiElementBase) psi, (CompositeElement) node));
                  }

                  super.visitNode(node);
                }
              });
    } finally {
      LazyParseableElement.setSuppressEagerPsiCreation(false);
    }
    if (stubs.hasNext()) {
      reportStubAstMismatch(
          "Stub list in " + getName() + " has more elements than PSI", stubTree, cachedDocument);
    }
    return result;
  }