public StubTree calcStubTree() { FileElement fileElement = calcTreeElement(); synchronized (myStubFromTreeLock) { SoftReference<StubTree> ref = fileElement.getUserData(STUB_TREE_IN_PARSED_TREE); StubTree tree = SoftReference.dereference(ref); if (tree == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); IElementType contentElementType = getContentElementType(); if (!(contentElementType instanceof IStubFileElementType)) { VirtualFile vFile = getVirtualFile(); String message = "ContentElementType: " + contentElementType + "; file: " + this + "\n\t" + "Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = " + Boolean.TRUE.equals(getUserData(BUILDING_STUB)) + "\n\t" + "getTreeElement() = " + getTreeElement() + "\n\t" + "vFile instanceof VirtualFileWithId = " + (vFile instanceof VirtualFileWithId) + "\n\t" + "StubUpdatingIndex.canHaveStub(vFile) = " + StubTreeLoader.getInstance().canHaveStub(vFile); rebuildStub(); throw new AssertionError(message); } StubElement currentStubTree = ((IStubFileElementType) contentElementType).getBuilder().buildStubTree(this); if (currentStubTree == null) { throw new AssertionError( "Stub tree wasn't built for " + contentElementType + "; file: " + this); } tree = new StubTree((PsiFileStub) currentStubTree); tree.setDebugInfo("created in calcStubTree"); try { TreeUtil.bindStubsToTree(this, tree); } catch (TreeUtil.StubBindingException e) { rebuildStub(); throw new RuntimeException("Stub and PSI element type mismatch in " + getName(), e); } fileElement.putUserData(STUB_TREE_IN_PARSED_TREE, new SoftReference<StubTree>(tree)); } return tree; } }
@Override @Nullable public StubTree getStubTree() { ApplicationManager.getApplication().assertReadAccessAllowed(); if (Boolean.TRUE.equals(getUserData(BUILDING_STUB))) return null; final StubTree derefd = derefStub(); if (derefd != null) return derefd; if (getTreeElement() != null) return null; if (!(getContentElementType() instanceof IStubFileElementType)) return null; final VirtualFile vFile = getVirtualFile(); if (!(vFile instanceof VirtualFileWithId)) return null; final PsiFile stubBindingRoot = getViewProvider().getStubBindingRoot(); if (stubBindingRoot != this) { LOG.error( "Attempted to create stubs for non-root file: " + this + ", stub binding root: " + stubBindingRoot); return null; } ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), vFile, this); if (!(tree instanceof StubTree)) return null; StubTree stubHolder = (StubTree) tree; synchronized (PsiLock.LOCK) { if (getTreeElement() != null) return null; final StubTree derefdOnLock = derefStub(); if (derefdOnLock != null) return derefdOnLock; //noinspection unchecked ((StubBase) stubHolder.getRoot()).setPsi(this); myStub = new SoftReference<StubTree>(stubHolder); return stubHolder; } }