601012827e5cd32f884cd9c71eebf80a0dd2ec9c
[idea/community.git] / java / java-impl / src / com / intellij / psi / impl / source / resolve / reference / impl / providers / JavaClassListReferenceProvider.java
1 /*
2  * Copyright 2000-2009 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.impl.source.resolve.reference.impl.providers;
17
18 import com.intellij.openapi.progress.ProgressManager;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.util.NotNullLazyValue;
21 import com.intellij.psi.PsiElement;
22 import com.intellij.psi.PsiPackage;
23 import com.intellij.psi.PsiReference;
24 import com.intellij.psi.search.GlobalSearchScope;
25 import com.intellij.psi.templateLanguages.OuterLanguageElement;
26 import com.intellij.psi.util.PsiTreeUtil;
27 import com.intellij.psi.xml.XmlTag;
28 import org.jetbrains.annotations.NotNull;
29
30 import java.util.*;
31
32 /**
33  * Created by IntelliJ IDEA.
34  * User: ik
35  * Date: 05.06.2003
36  * Time: 20:27:59
37  * To change this template use Options | File Templates.
38  */
39 public class JavaClassListReferenceProvider extends JavaClassReferenceProvider {
40
41   public JavaClassListReferenceProvider(final Project project) {
42     super(GlobalSearchScope.allScope(project), project);
43     setOption(ADVANCED_RESOLVE, Boolean.TRUE);
44   }
45
46   @NotNull
47   public PsiReference[] getReferencesByString(String str, PsiElement position, int offsetInPosition){
48     if (position instanceof XmlTag && ((XmlTag)position).getValue().getTextElements().length == 0) {
49       return PsiReference.EMPTY_ARRAY; 
50     }
51
52     if (str.length() < 2) {
53       return PsiReference.EMPTY_ARRAY;
54     }
55
56     if (position != null && PsiTreeUtil.getChildOfType(position, OuterLanguageElement.class) != null) {
57       return PsiReference.EMPTY_ARRAY;
58     }
59
60     NotNullLazyValue<Set<String>> topLevelPackages = new NotNullLazyValue<Set<String>>() {
61       @NotNull
62       @Override
63       protected Set<String> compute() {
64         final Set<String> knownTopLevelPackages = new HashSet<String>();
65         final List<PsiElement> defaultPackages = getDefaultPackages();
66         for (final PsiElement pack : defaultPackages) {
67           if (pack instanceof PsiPackage) {
68             knownTopLevelPackages.add(((PsiPackage)pack).getName());
69           }
70         }
71         return knownTopLevelPackages;
72       }
73     };
74     final List<PsiReference> results = new ArrayList<PsiReference>();
75
76     for(int dot = str.indexOf('.'); dot > 0; dot = str.indexOf('.', dot + 1)) {
77       int start = dot;
78       while (start > 0 && Character.isLetterOrDigit(str.charAt(start - 1))) start--;
79       if (dot == start) {
80         continue;
81       }
82       String candidate = str.substring(start, dot);
83       if (topLevelPackages.getValue().contains(candidate)) {
84         int end = dot;
85         while (end < str.length() - 1) {
86           end++;
87           char ch = str.charAt(end);
88           if (ch != '.' && !Character.isJavaIdentifierPart(ch)) {
89             break;
90           }
91         }
92         String s = str.substring(start, end + 1);
93         results.addAll(Arrays.asList(new JavaClassReferenceSet(s, position, offsetInPosition + start, false, this){
94           public boolean isSoft(){
95             return true;
96           }
97         }.getAllReferences()));
98         ProgressManager.checkCanceled();
99       }
100     }
101     return results.toArray(new PsiReference[results.size()]);
102   }
103 }