001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.resolve.java.scope;
018
019 import com.google.common.collect.Lists;
020 import com.google.common.collect.Maps;
021 import com.google.common.collect.Sets;
022 import com.intellij.openapi.progress.ProgressIndicatorProvider;
023 import com.intellij.openapi.util.Condition;
024 import com.intellij.psi.PsiElement;
025 import com.intellij.util.containers.ContainerUtil;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.jet.lang.descriptors.*;
029 import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
030 import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
031 import org.jetbrains.jet.lang.resolve.java.provider.ClassPsiDeclarationProvider;
032 import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers;
033 import org.jetbrains.jet.lang.resolve.java.provider.PackagePsiDeclarationProvider;
034 import org.jetbrains.jet.lang.resolve.java.provider.PsiDeclarationProvider;
035 import org.jetbrains.jet.lang.resolve.name.Name;
036 import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
037
038 import java.util.*;
039
040 public abstract class JavaBaseScope extends JetScopeImpl {
041
042 @NotNull
043 protected final JavaSemanticServices semanticServices;
044 @NotNull
045 protected final PsiDeclarationProvider declarationProvider;
046 @NotNull
047 private final Map<Name, Set<FunctionDescriptor>> functionDescriptors = Maps.newHashMap();
048 @NotNull
049 private final Map<Name, Set<VariableDescriptor>> propertyDescriptors = Maps.newHashMap();
050 @Nullable
051 private Collection<DeclarationDescriptor> allDescriptors = null;
052 @Nullable
053 private Set<ClassDescriptor> objectDescriptors = null;
054 @NotNull
055 protected final ClassOrNamespaceDescriptor descriptor;
056
057 private Collection<ClassDescriptor> innerClasses = null;
058
059
060 protected JavaBaseScope(
061 @NotNull ClassOrNamespaceDescriptor descriptor,
062 @NotNull JavaSemanticServices semanticServices,
063 @NotNull PsiDeclarationProvider declarationProvider
064 ) {
065 this.semanticServices = semanticServices;
066 this.declarationProvider = declarationProvider;
067 this.descriptor = descriptor;
068 }
069
070 @NotNull
071 @Override
072 public DeclarationDescriptor getContainingDeclaration() {
073 return descriptor;
074 }
075
076 @NotNull
077 @Override
078 public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
079 Set<VariableDescriptor> cached = propertyDescriptors.get(name);
080 if (cached != null) return cached;
081
082 if (allDescriptorsComputed()) {
083 return Collections.emptySet();
084 }
085
086 Set<VariableDescriptor> computedDescriptors = computePropertyDescriptors(name);
087 propertyDescriptors.put(name, computedDescriptors);
088 return computedDescriptors;
089 }
090
091 @NotNull
092 private Set<VariableDescriptor> computePropertyDescriptors(@NotNull Name name) {
093 return getResolver().resolveFieldGroupByName(name, declarationProvider, descriptor);
094 }
095
096 @NotNull
097 @Override
098 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
099 Set<FunctionDescriptor> cached = functionDescriptors.get(name);
100 if (cached != null) return cached;
101
102 if (allDescriptorsComputed()) {
103 return Collections.emptySet();
104 }
105
106 Set<FunctionDescriptor> computedDescriptors = computeFunctionDescriptor(name);
107 functionDescriptors.put(name, computedDescriptors);
108 return computedDescriptors;
109 }
110
111 @NotNull
112 protected abstract Set<FunctionDescriptor> computeFunctionDescriptor(@NotNull Name name);
113
114 @NotNull
115 @Override
116 public Collection<DeclarationDescriptor> getAllDescriptors() {
117 if (allDescriptorsComputed()) {
118 return allDescriptors;
119 }
120
121 allDescriptors = computeAllDescriptors();
122
123 return allDescriptors;
124 }
125
126 private boolean allDescriptorsComputed() {
127 return allDescriptors != null;
128 }
129
130 @NotNull
131 protected Collection<DeclarationDescriptor> computeAllDescriptors() {
132 Collection<DeclarationDescriptor> result = Sets.newHashSet();
133 result.addAll(computeFieldAndFunctionDescriptors());
134 result.addAll(filterObjects(getInnerClasses(), false));
135 return result;
136 }
137
138 @NotNull
139 @Override
140 public Set<ClassDescriptor> getObjectDescriptors() {
141 if (objectDescriptors == null) {
142 objectDescriptors = new HashSet<ClassDescriptor>(filterObjects(getInnerClasses(), true));
143 }
144 return objectDescriptors;
145 }
146
147 @NotNull
148 protected abstract Collection<ClassDescriptor> computeInnerClasses();
149
150 @NotNull
151 private Collection<DeclarationDescriptor> computeFieldAndFunctionDescriptors() {
152 Collection<DeclarationDescriptor> result = Lists.newArrayList();
153 for (NamedMembers members : declarationProvider.getMembersCache().allMembers()) {
154 Name name = members.getName();
155 ProgressIndicatorProvider.checkCanceled();
156 result.addAll(getFunctions(name));
157 ProgressIndicatorProvider.checkCanceled();
158 result.addAll(getProperties(name));
159 }
160 return result;
161 }
162
163 @NotNull
164 protected JavaDescriptorResolver getResolver() {
165 return semanticServices.getDescriptorResolver();
166 }
167
168 //TODO: remove this method
169 @NotNull
170 public PsiElement getPsiElement() {
171 if (declarationProvider instanceof ClassPsiDeclarationProvider) {
172 return ((ClassPsiDeclarationProvider) declarationProvider).getPsiClass();
173 }
174 if (declarationProvider instanceof PackagePsiDeclarationProvider) {
175 return ((PackagePsiDeclarationProvider) declarationProvider).getPsiPackage();
176 }
177 throw new IllegalStateException();
178 }
179
180 @NotNull
181 protected Collection<ClassDescriptor> getInnerClasses() {
182 if (innerClasses == null) {
183 innerClasses = computeInnerClasses();
184 }
185 return innerClasses;
186 }
187
188 private static <T extends ClassDescriptor> Collection<T> filterObjects(Collection<T> classes, final boolean objects) {
189 return ContainerUtil.filter(classes, new Condition<T>() {
190 @Override
191 public boolean value(T classDescriptor) {
192 return classDescriptor.getKind().isObject() == objects;
193 }
194 });
195 }
196 }