@Override protected String stubTreeAndIndexDoNotMatch( StubTree stubTree, PsiFileWithStubSupport psiFile, List<StubElement<?>> plained, VirtualFile virtualFile, StubTree stubTreeFromIndex) { String details = "Please report the problem to JetBrains with the file attached"; details += "\npsiFile" + psiFile; details += "\npsiFile.class" + psiFile.getClass(); details += "\npsiFile.lang" + psiFile.getLanguage(); String fileText = psiFile instanceof PsiCompiledElement ? "compiled" : psiFile.getText(); return LogMessageEx.createEvent( "PSI and index do not match", details, new Attachment( virtualFile != null ? virtualFile.getPath() + "_file.txt" : "vFile.txt", fileText), new Attachment("stubTree.txt", ((PsiFileStubImpl) stubTree.getRoot()).printTree()), new Attachment( "stubTreeFromIndex.txt", stubTreeFromIndex == null ? "null" : ((PsiFileStubImpl) stubTreeFromIndex.getRoot()).printTree())) .toString(); }
private void clearStub(@NotNull String reason) { StubTree stubHolder = SoftReference.dereference(myStub); if (stubHolder != null) { ((PsiFileStubImpl<?>) stubHolder.getRoot()).clearPsi(reason); } myStub = null; }
@Override @NotNull public StubTree getStubTree() { ApplicationManager.getApplication().assertReadAccessAllowed(); StubTree stubTree = dereference(myStub); if (stubTree != null) return stubTree; // build newStub out of lock to avoid deadlock StubTree newStubTree = (StubTree) StubTreeLoader.getInstance().readOrBuild(getProject(), getVirtualFile(), this); if (newStubTree == null) { if (LOG.isDebugEnabled()) { LOG.debug("No stub for class file in index: " + getVirtualFile().getPresentableUrl()); } newStubTree = new StubTree(new PsiJavaFileStubImpl("corrupted.classfiles", true)); } synchronized (myStubLock) { stubTree = dereference(myStub); if (stubTree != null) return stubTree; stubTree = newStubTree; @SuppressWarnings("unchecked") PsiFileStubImpl<PsiFile> fileStub = (PsiFileStubImpl) stubTree.getRoot(); fileStub.setPsi(this); myStub = new SoftReference<StubTree>(stubTree); } return stubTree; }
@Override @NotNull public ASTNode getNode() { ASTNode node = myNode; if (node == null) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiFileImpl file = (PsiFileImpl) getContainingFile(); synchronized (file.getStubLock()) { node = myNode; if (node == null) { NonCancelableSection criticalSection = ProgressIndicatorProvider.startNonCancelableSectionIfSupported(); try { if (!file.isValid()) throw new PsiInvalidElementAccessException(this); FileElement treeElement = file.getTreeElement(); StubTree stubTree = file.getStubTree(); if (treeElement != null) { return notBoundInExistingAst(file, treeElement, stubTree); } final FileElement fileElement = file.loadTreeElement(); node = myNode; if (node == null) { @NonNls String message = "Failed to bind stub to AST for element " + getClass() + " in " + (file.getVirtualFile() == null ? "<unknown file>" : file.getVirtualFile().getPath()) + "\nFile stub tree:\n" + (stubTree != null ? StringUtil.trimLog( ((PsiFileStubImpl) stubTree.getRoot()).printTree(), 1024) : " is null") + "\nLoaded file AST:\n" + StringUtil.trimLog(DebugUtil.treeToString(fileElement, true), 1024); throw new IllegalArgumentException(message); } } finally { criticalSection.done(); } } } } return node; }
@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; } }
@Override public void onContentReload() { ApplicationManager.getApplication().assertWriteAccessAllowed(); synchronized (myStubLock) { StubTree stubTree = dereference(myStub); myStub = null; if (stubTree != null) { //noinspection unchecked ((PsiFileStubImpl) stubTree.getRoot()).clearPsi("cls onContentReload"); } } ClsPackageStatementImpl packageStatement = new ClsPackageStatementImpl(this); synchronized (myMirrorLock) { putUserData(CLS_DOCUMENT_LINK_KEY, null); myMirrorFileElement = null; myPackageStatement = packageStatement; } myLanguageLevel = null; }
@Nullable public StubElement getStub() { StubTree stubHolder = getStubTree(); return stubHolder != null ? stubHolder.getRoot() : null; }