2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 package com
.intellij
.psi
.impl
.source
.resolve
;
22 import com
.intellij
.openapi
.components
.ServiceManager
;
23 import com
.intellij
.openapi
.diagnostic
.Logger
;
24 import com
.intellij
.openapi
.project
.Project
;
25 import com
.intellij
.openapi
.util
.Key
;
26 import com
.intellij
.psi
.PsiEllipsisType
;
27 import com
.intellij
.psi
.PsiExpression
;
28 import com
.intellij
.psi
.PsiType
;
29 import com
.intellij
.psi
.PsiVariable
;
30 import com
.intellij
.psi
.impl
.PsiManagerEx
;
31 import com
.intellij
.util
.ConcurrencyUtil
;
32 import com
.intellij
.util
.Function
;
33 import com
.intellij
.util
.containers
.ConcurrentWeakHashMap
;
34 import org
.jetbrains
.annotations
.NonNls
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
40 import java
.util
.concurrent
.ConcurrentMap
;
42 public class JavaResolveCache
{
43 private static final Logger LOG
= Logger
.getInstance("#com.intellij.psi.impl.source.resolve.JavaResolveCache");
45 public static JavaResolveCache
getInstance(Project project
) {
46 return ServiceManager
.getService(project
, JavaResolveCache
.class);
49 private final ConcurrentMap
<PsiExpression
, PsiType
> myCalculatedTypes
= new ConcurrentWeakHashMap
<PsiExpression
, PsiType
>();
50 private static final Key
<ResolveCache
.MapPair
<PsiVariable
, Object
>> VAR_TO_CONST_VALUE_MAP_KEY
= Key
.create("ResolveCache.VAR_TO_CONST_VALUE_MAP_KEY");
52 private final Map
<PsiVariable
,Object
> myVarToConstValueMap1
;
53 private final Map
<PsiVariable
,Object
> myVarToConstValueMap2
;
55 private static final Object NULL
= Key
.create("NULL");
56 private static final PsiType NULL_TYPE
= new PsiEllipsisType(PsiType
.NULL
){
57 public boolean isValid() {
62 public String
getPresentableText() {
67 public JavaResolveCache(PsiManagerEx manager
) {
68 ResolveCache cache
= manager
.getResolveCache();
70 myVarToConstValueMap1
= cache
.getOrCreateWeakMap(VAR_TO_CONST_VALUE_MAP_KEY
, true);
71 myVarToConstValueMap2
= cache
.getOrCreateWeakMap(VAR_TO_CONST_VALUE_MAP_KEY
, false);
73 final Runnable cleanuper
= new Runnable() {
75 myCalculatedTypes
.clear();
79 cache
.addRunnableToRunOnDropCaches(cleanuper
);
80 manager
.registerRunnableToRunOnAnyChange(cleanuper
);
84 public <T
extends PsiExpression
> PsiType
getType(@NotNull T expr
, @NotNull Function
<T
, PsiType
> f
) {
85 PsiType type
= myCalculatedTypes
.get(expr
);
91 type
= ConcurrencyUtil
.cacheOrGet(myCalculatedTypes
, expr
, type
);
93 if (!type
.isValid()) {
94 LOG
.error("Type is invalid: " + type
+"; expr: '"+expr
+"' is "+(expr
.isValid() ?
"valid":"invalid"));
96 return type
== NULL_TYPE ?
null : type
;
100 public Object
computeConstantValueWithCaching(PsiVariable variable
, ConstValueComputer computer
, Set
<PsiVariable
> visitedVars
){
101 boolean physical
= variable
.isPhysical();
103 Object cached
= (physical ? myVarToConstValueMap1
: myVarToConstValueMap2
).get(variable
);
104 if (cached
== NULL
) return null;
105 if (cached
!= null) return cached
;
107 Object result
= computer
.execute(variable
, visitedVars
);
109 (physical ? myVarToConstValueMap1
: myVarToConstValueMap2
).put(variable
, result
!= null ? result
: NULL
);
114 public interface ConstValueComputer
{
115 Object
execute(PsiVariable variable
, Set
<PsiVariable
> visitedVars
);