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
;
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
) {
35 enumerateStubs(root
, myPlainList
);
38 private static void enumerateStubs(final StubElement
<?
> root
, final List
<StubElement
<?
>> result
) {
39 ((StubBase
)root
).id
= result
.size();
41 for (StubElement child
: root
.getChildrenStubs()) {
42 enumerateStubs(child
, result
);
47 public PsiFileStub
getRoot() {
51 public List
<StubElement
<?
>> getPlainList() {
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
);
67 map
= new HashMap
<Object
, TIntArrayList
>();
68 result
.put(indexKey
, map
);
71 TIntArrayList list
= map
.get(value
);
73 list
= new TIntArrayList();
85 public static StubTree
readOrBuild(Project project
, final VirtualFile vFile
) {
86 final StubTree fromIndices
= readFromVFile(project
, vFile
);
87 if (fromIndices
!= null) {
91 if (!StubUpdatingIndex
.canHaveStub(vFile
)) {
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
);
111 public static StubTree
readFromVFile(Project project
, final VirtualFile vFile
) {
112 if (DumbService
.getInstance(project
).isDumb()) {
116 final int id
= Math
.abs(FileBasedIndex
.getFileId(vFile
));
118 final List
<SerializedStubTree
> datas
= FileBasedIndex
.getInstance().getValues(StubUpdatingIndex
.INDEX_ID
, id
, GlobalSearchScope
.fileScope(project
, vFile
));
119 final int size
= datas
.size();
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() {
130 final Document doc
= FileDocumentManager
.getInstance().getCachedDocument(vFile
);
132 FileDocumentManager
.getInstance().saveDocument(doc
);
135 }, ModalityState
.NON_MODAL
);
137 FileBasedIndex
.getInstance().requestReindex(vFile
);