JSResolveUtil.java

1    /* 
2     * Copyright 2000-2005 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.lang.javascript.psi; 
17    
18   import com.intellij.psi.PsiElement; 
19   import com.intellij.psi.PsiFile; 
20   import com.intellij.psi.PsiNamedElement; 
21   import com.intellij.psi.PsiSubstitutor; 
22   import com.intellij.psi.scope.PsiScopeProcessor; 
23   import org.jetbrains.annotations.Nullable; 
24   import org.jetbrains.annotations.NotNull; 
25    
26   import java.util.ArrayList; 
27   import java.util.List; 
28    
29   /** 
30    * @author max 
31    */ 
32   public class JSResolveUtil { 
33     private JSResolveUtil() {} 
34    
35     @Nullable 
36     public static PsiElement treeWalkUp(PsiScopeProcessor processor, PsiElement elt, PsiElement lastParent, PsiElement place) { 
37       if (elt == null) return null; 
38    
39       PsiElement cur = elt; 
40       do { 
41         if (!cur.processDeclarations(processor, PsiSubstitutor.EMPTY, cur == elt ? lastParent : null, place)) { 
42           if (processor instanceof ResolveProcessor) { 
43             return ((ResolveProcessor)processor).getResult(); 
44           } 
45         } 
46         if(cur instanceof PsiFile) break; 
47         if (cur instanceof JSStatement && cur.getContext() instanceof JSIfStatement) { 
48           // Do not try to resolve variables from then branch in else branch.  
49           break; 
50         } 
51    
52    
53         cur = cur.getPrevSibling(); 
54       } while (cur != null); 
55    
56       final PsiElement func = processFunctionDeclarations(processor, elt.getContext()); 
57       if (func != null) return func; 
58    
59       return treeWalkUp(processor, elt.getContext(), elt, place); 
60     } 
61    
62     @Nullable 
63     private static PsiElement processFunctionDeclarations(final @NotNull PsiScopeProcessor processor, final @Nullable PsiElement context) { 
64       if (context != null) { 
65         PsiElement cur = context.getLastChild(); 
66         while (cur != null) { 
67           if (cur instanceof JSFunction) { 
68             if (!processor.execute(cur, PsiSubstitutor.EMPTY)) { 
69               if (processor instanceof ResolveProcessor) { 
70                 return ((ResolveProcessor)processor).getResult(); 
71               } 
72             } 
73           } 
74           cur = cur.getPrevSibling(); 
75         } 
76       } 
77       return null; 
78     } 
79    
80     public static class ResolveProcessor implements PsiScopeProcessor { 
81       private String myName; 
82       private PsiElement myResult = null; 
83    
84       public ResolveProcessor(final String name) { 
85         myName = name; 
86       } 
87    
88       public PsiElement getResult() { 
89         return myResult; 
90       } 
91    
92       public boolean execute(PsiElement element, PsiSubstitutor substitutor) { 
93         if (element instanceof PsiNamedElement && 
94             element instanceof JSElement 
95            ) { 
96           if (myName.equals(((PsiNamedElement)element).getName())) { 
97             myResult = element; 
98             return false; 
99           } 
100        } 
101   
102        return true; 
103      } 
104   
105      public <T> T getHint(Class<T> hintClass) { 
106        return null; 
107      } 
108   
109      public void handleEvent(Event event, Object associated) { 
110      } 
111    } 
112   
113    public static class VariantsProcessor implements PsiScopeProcessor { 
114      private List<PsiElement> myNames = new ArrayList<PsiElement>(); 
115   
116      public VariantsProcessor() { 
117      } 
118   
119      public PsiElement[] getResult() { 
120        return myNames.toArray(new PsiElement[myNames.size()]); 
121      } 
122   
123      public boolean execute(PsiElement element, PsiSubstitutor substitutor) { 
124        if (element instanceof PsiNamedElement && 
125            element instanceof JSElement 
126           ) { 
127          myNames.add(element); 
128        } 
129   
130        return true; 
131      } 
132   
133      public <T> T getHint(Class<T> hintClass) { 
134        return null; 
135      } 
136   
137      public void handleEvent(Event event, Object associated) { 
138      } 
139    } 
140  } 
141