readOrBuild should read stub regardless of whether it's in allProject scope
[fedora-idea.git] / platform / lang-impl / src / com / intellij / psi / stubs / StubTree.java
blob11adfa763918c173ad3e3214b137f8291a5ba69e
1 /*
2 * @author max
3 */
4 package com.intellij.psi.stubs;
6 import com.intellij.openapi.application.ApplicationManager;
7 import com.intellij.openapi.application.ModalityState;
8 import com.intellij.openapi.diagnostic.Logger;
9 import com.intellij.openapi.editor.Document;
10 import com.intellij.openapi.fileEditor.FileDocumentManager;
11 import com.intellij.openapi.project.DumbService;
12 import com.intellij.openapi.project.Project;
13 import com.intellij.openapi.vfs.VirtualFile;
14 import com.intellij.psi.search.GlobalSearchScope;
15 import com.intellij.util.indexing.FileBasedIndex;
16 import com.intellij.util.indexing.FileContent;
17 import gnu.trove.TIntArrayList;
18 import org.jetbrains.annotations.NotNull;
19 import org.jetbrains.annotations.Nullable;
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
27 public class StubTree {
28 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubTree");
30 private final PsiFileStub myRoot;
31 private final List<StubElement<?>> myPlainList = new ArrayList<StubElement<?>>();
33 public StubTree(@NotNull final PsiFileStub root) {
34 myRoot = root;
35 enumerateStubs(root, myPlainList);
38 private static void enumerateStubs(final StubElement<?> root, final List<StubElement<?>> result) {
39 ((StubBase)root).id = result.size();
40 result.add(root);
41 for (StubElement child : root.getChildrenStubs()) {
42 enumerateStubs(child, result);
46 @NotNull
47 public PsiFileStub getRoot() {
48 return myRoot;
51 public List<StubElement<?>> getPlainList() {
52 return myPlainList;
55 @NotNull
56 public Map<StubIndexKey, Map<Object, TIntArrayList>> indexStubTree() {
57 final Map<StubIndexKey, Map<Object, TIntArrayList>> result = new HashMap<StubIndexKey, Map<Object, TIntArrayList>>();
59 for (int i = 0; i < myPlainList.size(); i++) {
60 StubElement<?> stub = myPlainList.get(i);
61 final StubSerializer serializer = SerializationManager.getInstance().getSerializer(stub);
62 final int stubIdx = i;
63 serializer.indexStub(stub, new IndexSink() {
64 public void occurrence(@NotNull final StubIndexKey indexKey, @NotNull final Object value) {
65 Map<Object, TIntArrayList> map = result.get(indexKey);
66 if (map == null) {
67 map = new HashMap<Object, TIntArrayList>();
68 result.put(indexKey, map);
71 TIntArrayList list = map.get(value);
72 if (list == null) {
73 list = new TIntArrayList();
74 map.put(value, list);
76 list.add(stubIdx);
78 });
81 return result;
84 @Nullable
85 public static StubTree readOrBuild(Project project, final VirtualFile vFile) {
86 final StubTree fromIndices = readFromVFile(project, vFile);
87 if (fromIndices != null) {
88 return fromIndices;
91 if (!StubUpdatingIndex.canHaveStub(vFile)) {
92 return null;
95 try {
96 final FileContent fc = new FileContent(vFile, vFile.contentsToByteArray());
97 fc.putUserData(FileBasedIndex.PROJECT, project);
98 final StubElement element = StubUpdatingIndex.buildStubTree(fc);
99 if (element instanceof PsiFileStub) {
100 return new StubTree((PsiFileStub)element);
103 catch (IOException e) {
104 throw new RuntimeException(e);
107 return null;
110 @Nullable
111 public static StubTree readFromVFile(Project project, final VirtualFile vFile) {
112 if (DumbService.getInstance(project).isDumb()) {
113 return null;
116 final int id = Math.abs(FileBasedIndex.getFileId(vFile));
117 if (id > 0) {
118 final List<SerializedStubTree> datas = FileBasedIndex.getInstance().getValues(StubUpdatingIndex.INDEX_ID, id, GlobalSearchScope.fileScope(project, vFile));
119 final int size = datas.size();
121 if (size == 1) {
122 StubElement stub = datas.get(0).getStub();
123 return new StubTree((PsiFileStub)stub);
125 else if (size != 0) {
126 LOG.error("Twin stubs: " + vFile.getPresentableUrl() + " has " + size + " stub versions. Should only have one. id=" + id);
128 ApplicationManager.getApplication().invokeLater(new Runnable() {
129 public void run() {
130 final Document doc = FileDocumentManager.getInstance().getCachedDocument(vFile);
131 if (doc != null) {
132 FileDocumentManager.getInstance().saveDocument(doc);
135 }, ModalityState.NON_MODAL);
137 FileBasedIndex.getInstance().requestReindex(vFile);
141 return null;