@NotNull public static <T extends PsiElement> List<T> getStubChildrenOfTypeAsList( @Nullable PsiElement element, @NotNull Class<T> aClass) { if (element == null) return Collections.emptyList(); StubElement<?> stub = null; if (element instanceof PsiFileImpl) stub = ((PsiFileImpl) element).getStub(); else if (element instanceof StubBasedPsiElement) stub = ((StubBasedPsiElement) element).getStub(); if (stub == null) { return getChildrenOfTypeAsList(element, aClass); } List<T> result = new SmartList<T>(); for (StubElement childStub : stub.getChildrenStubs()) { PsiElement child = childStub.getPsi(); if (aClass.isInstance(child)) { //noinspection unchecked result.add((T) child); } } return result; }
@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(); }
private static PsiClass findClass(String fqn, StubElement<?> stub) { if (stub instanceof PsiClassStub && Comparing.equal(fqn, ((PsiClassStub) stub).getQualifiedName())) { return (PsiClass) stub.getPsi(); } for (StubElement child : stub.getChildrenStubs()) { PsiClass answer = findClass(fqn, child); if (answer != null) return answer; } return null; }
@Override public boolean isValid() { T stub = myStub; if (stub != null) { StubElement parent = stub.getParentStub(); if (parent == null) { LOG.error("No parent for stub " + stub + " of class " + stub.getClass()); return false; } PsiElement psi = parent.getPsi(); return psi != null && psi.isValid(); } return super.isValid(); }
@Nullable public <Psi extends PsiElement> Psi getStubOrPsiChild( final IStubElementType<? extends StubElement, Psi> elementType) { T stub = myStub; if (stub != null) { final StubElement<Psi> element = stub.findChildStubByType(elementType); if (element != null) { return element.getPsi(); } } else { final ASTNode childNode = getNode().findChildByType(elementType); if (childNode != null) { return (Psi) childNode.getPsi(); } } return null; }
@Nullable public static <T extends PsiElement> T getStubChildOfType( @Nullable PsiElement element, @NotNull Class<T> aClass) { if (element == null) return null; StubElement<?> stub = element instanceof StubBasedPsiElement ? ((StubBasedPsiElement) element).getStub() : null; if (stub == null) { return getChildOfType(element, aClass); } for (StubElement childStub : stub.getChildrenStubs()) { PsiElement child = childStub.getPsi(); if (aClass.isInstance(child)) { //noinspection unchecked return (T) child; } } return null; }
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 }
@Override @NotNull public PsiFile getContainingFile() { StubElement stub = myStub; if (stub != null) { while (!(stub instanceof PsiFileStub)) { stub = stub.getParentStub(); } PsiFile psi = (PsiFile) stub.getPsi(); if (psi == null) { throw new PsiInvalidElementAccessException(this, "no psi for file stub " + stub, null); } return psi; } PsiFile file = super.getContainingFile(); if (file == null) { throw new PsiInvalidElementAccessException(this); } return file; }
@Nullable public PsiAnnotation findAnnotation(@NotNull @NonNls String qualifiedName) { final GrModifierListStub stub = getStub(); if (stub != null) { for (StubElement stubElement : stub.getChildrenStubs()) { final PsiElement child = stubElement.getPsi(); if (child instanceof PsiAnnotation && qualifiedName.equals(((PsiAnnotation) child).getQualifiedName())) { return (PsiAnnotation) child; } } } else { PsiElement child = getFirstChild(); while (child != null) { if (child instanceof PsiAnnotation && qualifiedName.equals(((PsiAnnotation) child).getQualifiedName())) { return (PsiAnnotation) child; } child = child.getNextSibling(); } } return null; }