diff --git a/java/java-psi-api/src/com/intellij/psi/CommonClassNames.java b/platform/core-api/src/com/intellij/psi/CommonClassNames.java similarity index 100% rename from java/java-psi-api/src/com/intellij/psi/CommonClassNames.java rename to platform/core-api/src/com/intellij/psi/CommonClassNames.java diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIdList.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubIdList.java similarity index 100% rename from platform/lang-impl/src/com/intellij/psi/stubs/StubIdList.java rename to platform/indexing-impl/src/com/intellij/psi/stubs/StubIdList.java diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java new file mode 100644 index 000000000000..6986f31cd0b9 --- /dev/null +++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java @@ -0,0 +1,123 @@ +package com.intellij.psi.stubs; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiPlainTextFile; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.PsiFileWithStubSupport; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Author: dmitrylomov + */ +public abstract class StubProcessingHelperBase { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubProcessingHelperBase"); + + private static IElementType stubType(@NotNull final StubElement stub) { + if (stub instanceof PsiFileStub) { + return ((PsiFileStub)stub).getType(); + } + + return stub.getStubType(); + } + + public boolean processStubsInFile(final Project project, final VirtualFile file, StubIdList value, final Processor processor) { + StubTree stubTree = null; + + final PsiFile _psifile = PsiManager.getInstance(project).findFile(file); + PsiFileWithStubSupport psiFile = null; + + if (_psifile != null && !(_psifile instanceof PsiPlainTextFile)) { + if (_psifile instanceof PsiFileWithStubSupport) { + psiFile = (PsiFileWithStubSupport)_psifile; + stubTree = psiFile.getStubTree(); + if (stubTree == null && psiFile instanceof PsiFileImpl) { + stubTree = ((PsiFileImpl)psiFile).calcStubTree(); + } + } + } + + if (stubTree == null && psiFile == null) { + return true; + } + if (stubTree == null) { + ObjectStubTree objectStubTree = StubTreeLoader.getInstance().readFromVFile(project, file); + if (!(objectStubTree instanceof ObjectStubTree)) { + return true; + } + stubTree = (StubTree)objectStubTree; + final List> plained = stubTree.getPlainList(); + for (int i = 0, size = value.size(); i < size; i++) { + final StubElement stub = plained.get(value.get(i)); + final ASTNode tree = psiFile.findTreeForStub(stubTree, stub); + + if (tree != null) { + if (tree.getElementType() == stubType(stub)) { + Psi psi = (Psi)tree.getPsi(); + if (!processor.process(psi)) return false; + } + else { + String persistedStubTree = ((PsiFileStubImpl)stubTree.getRoot()).printTree(); + + String stubTreeJustBuilt = + ((PsiFileStubImpl)((IStubFileElementType)((PsiFileImpl)psiFile).getContentElementType()).getBuilder() + .buildStubTree(psiFile)).printTree(); + + StringBuilder builder = new StringBuilder(); + builder.append("Oops\n"); + + + builder.append("Recorded stub:-----------------------------------\n"); + builder.append(persistedStubTree); + builder.append("\nAST built stub: ------------------------------------\n"); + builder.append(stubTreeJustBuilt); + builder.append("\n"); + LOG.info(builder.toString()); + onInternalError(file); + } + } + } + } + else { + final List> plained = stubTree.getPlainList(); + for (int i = 0, size = value.size(); i < size; i++) { + final int stubTreeIndex = value.get(i); + if (stubTreeIndex >= plained.size()) { + final VirtualFile virtualFile = psiFile.getVirtualFile(); + StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file); + LOG.error(stubTreeAndIndexDoNotMatch(stubTree, psiFile, plained, virtualFile, stubTreeFromIndex)); + + onInternalError(file); + + break; + } + Psi psi = (Psi)plained.get(stubTreeIndex).getPsi(); + if (!processor.process(psi)) return false; + } + } + return true; + } + + /*** + * Returns a message to log when stub tree and index do not match + */ + protected abstract String stubTreeAndIndexDoNotMatch(StubTree stubTree, + PsiFileWithStubSupport psiFile, + List> plained, + VirtualFile virtualFile, + StubTree stubTreeFromIndex); + + protected abstract void onInternalError(VirtualFile file); + + +} diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java index 16f42a68b06c..530a40b3caad 100644 --- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java @@ -19,11 +19,7 @@ */ package com.intellij.psi.stubs; -import com.intellij.diagnostic.LogMessageEx; -import com.intellij.diagnostic.errordialog.Attachment; -import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.components.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; @@ -33,14 +29,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.ManagingFS; import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; -import com.intellij.psi.PsiPlainTextFile; -import com.intellij.psi.impl.source.PsiFileImpl; -import com.intellij.psi.impl.source.PsiFileWithStubSupport; import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.tree.IStubFileElementType; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; @@ -76,6 +66,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe private final Map, MyIndex> myIndices = new THashMap, MyIndex>(); private final TObjectIntHashMap> myIndexIdToVersionMap = new TObjectIntHashMap>(); + private final StubProcessingHelper myStubProcessingHelper; + private StubIndexState myPreviouslyRegistered; public StubIndexImpl(FileBasedIndex fileBasedIndex /* need this to ensure initialization order*/ ) throws IOException { @@ -96,6 +88,8 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe } } dropUnregisteredIndices(); + + myStubProcessingHelper = new StubProcessingHelper(fileBasedIndex); } @Nullable @@ -228,98 +222,9 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe if (file == null || scope != null && !scope.contains(file)) { return true; } - StubTree stubTree = null; - - final PsiFile _psifile = psiManager.findFile(file); - PsiFileWithStubSupport psiFile = null; - - if (_psifile != null && !(_psifile instanceof PsiPlainTextFile)) { - if (_psifile instanceof PsiFileWithStubSupport) { - psiFile = (PsiFileWithStubSupport)_psifile; - stubTree = psiFile.getStubTree(); - if (stubTree == null && psiFile instanceof PsiFileImpl) { - stubTree = ((PsiFileImpl)psiFile).calcStubTree(); - } - } - } - - if (stubTree == null && psiFile == null) { - return true; - } - if (stubTree == null) { - ObjectStubTree objectStubTree = StubTreeLoader.getInstance().readFromVFile(project, file); - if (!(objectStubTree instanceof ObjectStubTree)) { - return true; - } - stubTree = (StubTree)objectStubTree; - final List> plained = stubTree.getPlainList(); - for (int i = 0, size = value.size(); i < size; i++) { - final StubElement stub = plained.get(value.get(i)); - final ASTNode tree = psiFile.findTreeForStub(stubTree, stub); - - if (tree != null) { - if (tree.getElementType() == stubType(stub)) { - Psi psi = (Psi)tree.getPsi(); - if (!processor.process(psi)) return false; - } - else { - String persistedStubTree = ((PsiFileStubImpl)stubTree.getRoot()).printTree(); - - String stubTreeJustBuilt = - ((PsiFileStubImpl)((IStubFileElementType)((PsiFileImpl)psiFile).getContentElementType()).getBuilder() - .buildStubTree(psiFile)).printTree(); - - StringBuilder builder = new StringBuilder(); - builder.append("Oops\n"); - - - builder.append("Recorded stub:-----------------------------------\n"); - builder.append(persistedStubTree); - builder.append("\nAST built stub: ------------------------------------\n"); - builder.append(stubTreeJustBuilt); - builder.append("\n"); - LOG.info(builder.toString()); - - // requestReindex() may want to acquire write lock (for indices not requiring content loading) - // thus, because here we are under read lock, need to use invoke later - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - fileBasedIndex.requestReindex(file); - } - }, ModalityState.NON_MODAL); - } - } - } - } - else { - final List> plained = stubTree.getPlainList(); - for (int i = 0, size = value.size(); i < size; i++) { - final int stubTreeIndex = value.get(i); - if (stubTreeIndex >= plained.size()) { - final VirtualFile virtualFile = psiFile.getVirtualFile(); - StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file); - LOG.error(LogMessageEx.createEvent("PSI and index do not match: PSI " + psiFile + ", first stub " + plained.get(0), - "Please report the problem to JetBrains with the file attached", - new Attachment(virtualFile != null ? virtualFile.getPath() : "vFile.txt", psiFile.getText()), - new Attachment("stubTree.txt", ((PsiFileStubImpl)stubTree.getRoot()).printTree()), - new Attachment("stubTreeFromIndex.txt", stubTreeFromIndex == null ? "null" : ((PsiFileStubImpl)stubTreeFromIndex.getRoot()).printTree()))); - - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - fileBasedIndex.requestReindex(file); - } - }, ModalityState.NON_MODAL); - - break; - } - Psi psi = (Psi)plained.get(stubTreeIndex).getPsi(); - if (!processor.process(psi)) return false; - } - } - return true; + return myStubProcessingHelper.processStubsInFile(project, file, value, processor); } + }); } finally { @@ -343,14 +248,6 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe return true; } - private static IElementType stubType(@NotNull final StubElement stub) { - if (stub instanceof PsiFileStub) { - return ((PsiFileStub)stub).getType(); - } - - return stub.getStubType(); - } - private static void forceRebuild(@NotNull Throwable e) { LOG.info(e); FileBasedIndex.getInstance().scheduleRebuild(StubUpdatingIndex.INDEX_ID, e); diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java new file mode 100644 index 000000000000..df8976983a03 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java @@ -0,0 +1,68 @@ +package com.intellij.psi.stubs; + +import com.intellij.diagnostic.LogMessageEx; +import com.intellij.diagnostic.errordialog.Attachment; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.IdeaLoggingEvent; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiPlainTextFile; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.psi.impl.source.PsiFileWithStubSupport; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.util.Processor; +import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.FileBasedIndexImpl; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * Author: dmitrylomov + */ +public class StubProcessingHelper extends StubProcessingHelperBase { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubProcessingHelper"); + private final FileBasedIndex myFileBasedIndex; + + public StubProcessingHelper(FileBasedIndex fileBasedIndex) { + myFileBasedIndex = fileBasedIndex; + } + + @Override + protected void onInternalError(final VirtualFile file) { + // requestReindex() may want to acquire write lock (for indices not requiring content loading) + // thus, because here we are under read lock, need to use invoke later + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + myFileBasedIndex.requestReindex(file); + } + }, ModalityState.NON_MODAL); + } + + + protected String stubTreeAndIndexDoNotMatch(StubTree stubTree, + PsiFileWithStubSupport psiFile, + List> plained, + VirtualFile virtualFile, + StubTree stubTreeFromIndex) { + return LogMessageEx.createEvent("PSI and index do not match: PSI " + psiFile + ", first stub " + plained.get(0), + "Please report the problem to JetBrains with the file attached", + new Attachment(virtualFile != null ? virtualFile.getPath() : "vFile.txt", + psiFile.getText()), new Attachment("stubTree.txt", + ((PsiFileStubImpl)stubTree + .getRoot()).printTree()), + new Attachment("stubTreeFromIndex.txt", stubTreeFromIndex == null + ? "null" + : ((PsiFileStubImpl)stubTreeFromIndex + .getRoot()).printTree())).toString(); + } + +}