move the code for loading the stub tree from FileBasedIndex from StubTree to a separa...
[idea/community.git] / platform / lang-impl / src / com / intellij / psi / stubs / StubTreeLoaderImpl.java
1 /*
2  * Copyright 2000-2011 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.psi.stubs;
17
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.application.ModalityState;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.fileEditor.FileDocumentManager;
23 import com.intellij.openapi.project.DumbService;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.vfs.VirtualFile;
26 import com.intellij.psi.search.GlobalSearchScopes;
27 import com.intellij.util.indexing.FileBasedIndex;
28 import com.intellij.util.indexing.FileContent;
29 import com.intellij.util.indexing.FileContentImpl;
30 import org.jetbrains.annotations.Nullable;
31
32 import java.io.IOException;
33 import java.util.List;
34
35 /**
36  * @author yole
37  */
38 public class StubTreeLoaderImpl extends StubTreeLoader {
39   private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubTreeLoaderImpl");
40
41   @Nullable
42   public StubTree readOrBuild(Project project, final VirtualFile vFile) {
43     final StubTree fromIndices = readFromVFile(project, vFile);
44     if (fromIndices != null) {
45       return fromIndices;
46     }
47
48     if (!StubUpdatingIndex.canHaveStub(vFile)) {
49       return null;
50     }
51
52     try {
53       final FileContent fc = new FileContentImpl(vFile, vFile.contentsToByteArray());
54       fc.putUserData(FileBasedIndex.PROJECT, project);
55       final StubElement element = StubUpdatingIndex.buildStubTree(fc);
56       if (element instanceof PsiFileStub) {
57         return new StubTree((PsiFileStub)element);
58       }
59     }
60     catch (IOException e) {
61       throw new RuntimeException(e);
62     }
63
64     return null;
65   }
66
67   @Nullable
68   public StubTree readFromVFile(Project project, final VirtualFile vFile) {
69     if (DumbService.getInstance(project).isDumb()) {
70       return null;
71     }
72
73     final int id = Math.abs(FileBasedIndex.getFileId(vFile));
74     if (id > 0) {
75       final List<SerializedStubTree> datas = FileBasedIndex.getInstance().getValues(StubUpdatingIndex.INDEX_ID, id, GlobalSearchScopes
76           .fileScope(project, vFile));
77       final int size = datas.size();
78
79       if (size == 1) {
80         StubElement stub = datas.get(0).getStub();
81         return new StubTree((PsiFileStub)stub);
82       }
83       else if (size != 0) {
84         LOG.error("Twin stubs: " + vFile.getPresentableUrl() + " has " + size + " stub versions. Should only have one. id=" + id);
85
86         ApplicationManager.getApplication().invokeLater(new Runnable() {
87           public void run() {
88             final Document doc = FileDocumentManager.getInstance().getCachedDocument(vFile);
89             if (doc != null) {
90               FileDocumentManager.getInstance().saveDocument(doc);
91             }
92           }
93         }, ModalityState.NON_MODAL);
94
95         FileBasedIndex.getInstance().requestReindex(vFile);
96       }
97     }
98
99     return null;
100   }
101 }