1 package com
.intellij
.psi
.impl
.meta
;
3 import com
.intellij
.openapi
.Disposable
;
4 import com
.intellij
.openapi
.extensions
.Extensions
;
5 import com
.intellij
.openapi
.progress
.ProgressManager
;
6 import com
.intellij
.openapi
.util
.Disposer
;
7 import com
.intellij
.openapi
.util
.Key
;
8 import com
.intellij
.openapi
.util
.UserDataCache
;
9 import com
.intellij
.psi
.PsiElement
;
10 import com
.intellij
.psi
.filters
.ElementFilter
;
11 import com
.intellij
.psi
.meta
.MetaDataRegistrar
;
12 import com
.intellij
.psi
.meta
.PsiMetaData
;
13 import com
.intellij
.psi
.meta
.MetaDataContributor
;
14 import com
.intellij
.psi
.util
.CachedValue
;
15 import com
.intellij
.psi
.util
.CachedValueProvider
;
16 import org
.jetbrains
.annotations
.NotNull
;
17 import org
.jetbrains
.annotations
.Nullable
;
19 import java
.util
.ArrayList
;
20 import java
.util
.List
;
23 * Created by IntelliJ IDEA.
27 * To change this template use Options | File Templates.
29 public class MetaRegistry
extends MetaDataRegistrar
{
30 private static final List
<MyBinding
> ourBindings
= new ArrayList
<MyBinding
>();
31 private static boolean ourContributorsLoaded
= false;
33 private static final Key
<CachedValue
<PsiMetaData
>> META_DATA_KEY
= Key
.create("META DATA KEY");
35 public static void bindDataToElement(final PsiElement element
, final PsiMetaData data
){
36 CachedValue
<PsiMetaData
> value
=
37 element
.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider
<PsiMetaData
>() {
38 public Result
<PsiMetaData
> compute() {
40 return new Result
<PsiMetaData
>(data
, data
.getDependences());
43 element
.putUserData(META_DATA_KEY
, value
);
46 public static PsiMetaData
getMeta(final PsiElement element
) {
47 final PsiMetaData base
= getMetaBase(element
);
48 return base
!= null ? base
: null;
51 private static UserDataCache
<CachedValue
<PsiMetaData
>, PsiElement
, Object
> ourCachedMetaCache
=
52 new UserDataCache
<CachedValue
<PsiMetaData
>, PsiElement
, Object
>() {
53 protected CachedValue
<PsiMetaData
> compute(final PsiElement element
, Object p
) {
54 return element
.getManager().getCachedValuesManager()
55 .createCachedValue(new CachedValueProvider
<PsiMetaData
>() {
56 public Result
<PsiMetaData
> compute() {
58 ensureContributorsLoaded();
59 for (final MyBinding binding
: ourBindings
) {
60 if (binding
.myFilter
.isClassAcceptable(element
.getClass()) && binding
.myFilter
.isAcceptable(element
, element
.getParent())) {
61 final PsiMetaData data
= binding
.myDataClass
.newInstance();
63 return new Result
<PsiMetaData
>(data
, data
.getDependences());
66 } catch (IllegalAccessException iae
) {
67 throw new RuntimeException(iae
);
69 catch (InstantiationException ie
) {
70 throw new RuntimeException(ie
);
73 return new Result
<PsiMetaData
>(null, element
);
79 private static void ensureContributorsLoaded() {
80 if (!ourContributorsLoaded
) {
81 ourContributorsLoaded
= true;
82 for(MetaDataContributor contributor
: Extensions
.getExtensions(MetaDataContributor
.EP_NAME
)) {
83 contributor
.contributeMetaData(MetaDataRegistrar
.getInstance());
89 public static PsiMetaData
getMetaBase(final PsiElement element
) {
90 ProgressManager
.getInstance().checkCanceled();
91 return ourCachedMetaCache
.get(META_DATA_KEY
, element
, null).getValue();
94 public static <T
extends PsiMetaData
> void addMetadataBinding(ElementFilter filter
, Class
<T
> aMetadataClass
, Disposable parentDisposable
) {
95 final MyBinding binding
= new MyBinding(filter
, aMetadataClass
);
97 Disposer
.register(parentDisposable
, new Disposable() {
98 public void dispose() {
99 ourBindings
.remove(binding
);
104 public static <T
extends PsiMetaData
> void addMetadataBinding(ElementFilter filter
, Class
<T
> aMetadataClass
) {
105 addBinding(new MyBinding(filter
, aMetadataClass
));
108 private static void addBinding(final MyBinding binding
) {
109 ourBindings
.add(0, binding
);
112 public <T
extends PsiMetaData
> void registerMetaData(ElementFilter filter
, Class
<T
> metadataDescriptorClass
) {
113 addMetadataBinding(filter
, metadataDescriptorClass
);
116 private static class MyBinding
{
117 ElementFilter myFilter
;
118 Class
<PsiMetaData
> myDataClass
;
120 public <T
extends PsiMetaData
> MyBinding(@NotNull ElementFilter filter
, @NotNull Class
<T
> dataClass
) {
122 myDataClass
= (Class
)dataClass
;