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.lazy.descriptors;
018
019 import com.google.common.collect.Sets;
020 import com.intellij.openapi.util.Computable;
021 import com.intellij.util.Function;
022 import com.intellij.util.containers.ContainerUtil;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.psi.*;
027 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
028 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
029 import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProvider;
030 import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull;
031 import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
032 import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
033 import org.jetbrains.jet.lang.resolve.name.LabelName;
034 import org.jetbrains.jet.lang.resolve.name.Name;
035 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
036
037 import java.util.Collection;
038 import java.util.Collections;
039 import java.util.List;
040 import java.util.Set;
041
042 import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
043 import static org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager.ReferenceKind.STRONG;
044
045 public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, DP extends DeclarationProvider> implements JetScope {
046 protected final ResolveSession resolveSession;
047 protected final DP declarationProvider;
048 protected final D thisDescriptor;
049
050 private final MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> classDescriptors;
051 private final MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> objectDescriptors;
052
053 private final MemoizedFunctionToNotNull<Name, Set<FunctionDescriptor>> functionDescriptors;
054 private final MemoizedFunctionToNotNull<Name, Set<VariableDescriptor>> propertyDescriptors;
055
056 private static class AllDescriptors {
057 private final Collection<DeclarationDescriptor> all = Sets.newLinkedHashSet();
058 private final Collection<ClassDescriptor> objects = Sets.newLinkedHashSet();
059 }
060
061 private final NotNullLazyValue<AllDescriptors> allDescriptors;
062
063 protected AbstractLazyMemberScope(
064 @NotNull ResolveSession resolveSession,
065 @NotNull DP declarationProvider,
066 @NotNull D thisDescriptor
067 ) {
068 this.resolveSession = resolveSession;
069 this.declarationProvider = declarationProvider;
070 this.thisDescriptor = thisDescriptor;
071
072 StorageManager storageManager = resolveSession.getStorageManager();
073 this.classDescriptors = storageManager.createMemoizedFunction(new Function<Name, List<ClassDescriptor>>() {
074 @Override
075 public List<ClassDescriptor> fun(Name name) {
076 return resolveClassOrObjectDescriptor(name, false);
077 }
078 }, STRONG);
079 this.objectDescriptors = storageManager.createMemoizedFunction(new Function<Name, List<ClassDescriptor>>() {
080 @Override
081 public List<ClassDescriptor> fun(Name name) {
082 return resolveClassOrObjectDescriptor(name, true);
083 }
084 }, STRONG);
085
086 this.functionDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<FunctionDescriptor>>() {
087 @Override
088 public Set<FunctionDescriptor> fun(Name name) {
089 return doGetFunctions(name);
090 }
091 }, STRONG);
092 this.propertyDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<VariableDescriptor>>() {
093 @Override
094 public Set<VariableDescriptor> fun(Name name) {
095 return doGetProperties(name);
096 }
097 }, STRONG);
098
099 this.allDescriptors = storageManager.createLazyValue(new Computable<AllDescriptors>() {
100 @Override
101 public AllDescriptors compute() {
102 return computeAllDescriptors();
103 }
104 });
105 }
106
107 @Nullable
108 private List<ClassDescriptor> resolveClassOrObjectDescriptor(@NotNull final Name name, final boolean object) {
109 Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name);
110
111 return ContainerUtil.mapNotNull(classOrObjectDeclarations, new Function<JetClassOrObject, ClassDescriptor>() {
112 @Override
113 public ClassDescriptor fun(JetClassOrObject classOrObject) {
114 if (object != declaresObjectOrEnumConstant(classOrObject)) return null;
115
116 return new LazyClassDescriptor(resolveSession, thisDescriptor, name,
117 JetClassInfoUtil.createClassLikeInfo(classOrObject));
118 }
119 });
120 }
121
122 private static boolean declaresObjectOrEnumConstant(JetClassOrObject declaration) {
123 return declaration instanceof JetObjectDeclaration || declaration instanceof JetEnumEntry;
124 }
125
126 @Override
127 public ClassifierDescriptor getClassifier(@NotNull Name name) {
128 return first(classDescriptors.fun(name));
129 }
130
131 @Override
132 public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
133 return first(objectDescriptors.fun(name));
134 }
135
136 private static <T> T first(@NotNull List<T> list) {
137 if (list.isEmpty()) return null;
138 return list.get(0);
139 }
140
141 @NotNull
142 @Override
143 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
144 return functionDescriptors.fun(name);
145 }
146
147 @NotNull
148 private Set<FunctionDescriptor> doGetFunctions(@NotNull Name name) {
149 Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
150
151 Collection<JetNamedFunction> declarations = declarationProvider.getFunctionDeclarations(name);
152 for (JetNamedFunction functionDeclaration : declarations) {
153 JetScope resolutionScope = getScopeForMemberDeclarationResolution(functionDeclaration);
154 result.add(resolveSession.getInjector().getDescriptorResolver().resolveFunctionDescriptorWithAnnotationArguments(thisDescriptor, resolutionScope,
155 functionDeclaration,
156 resolveSession.getTrace()));
157 }
158
159 getNonDeclaredFunctions(name, result);
160
161 return result;
162 }
163
164 @NotNull
165 protected abstract JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration);
166
167 protected abstract void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set<FunctionDescriptor> result);
168
169 @NotNull
170 @Override
171 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
172 return propertyDescriptors.fun(name);
173 }
174
175 @NotNull
176 public Set<VariableDescriptor> doGetProperties(@NotNull Name name) {
177 Set<VariableDescriptor> result = Sets.newLinkedHashSet();
178
179 Collection<JetProperty> declarations = declarationProvider.getPropertyDeclarations(name);
180 for (JetProperty propertyDeclaration : declarations) {
181 JetScope resolutionScope = getScopeForMemberDeclarationResolution(propertyDeclaration);
182 PropertyDescriptor propertyDescriptor =
183 resolveSession.getInjector().getDescriptorResolver().resolvePropertyDescriptor(thisDescriptor, resolutionScope,
184 propertyDeclaration,
185 resolveSession.getTrace());
186 result.add(propertyDescriptor);
187 resolveSession.getInjector().getAnnotationResolver().resolveAnnotationsArguments(propertyDescriptor, resolveSession.getTrace(), resolutionScope);
188 }
189
190 // Objects are also properties
191 Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name);
192 for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) {
193 if (declaresObjectOrEnumConstant(classOrObjectDeclaration)) {
194 ClassDescriptor classifier = getObjectDescriptor(name);
195 if (classifier == null) {
196 throw new IllegalStateException("Object declaration " + name + " found in the DeclarationProvider " + declarationProvider + " but not in the scope " + this);
197 }
198 VariableDescriptor propertyDescriptor = resolveSession.getInjector().getDescriptorResolver()
199 .resolveObjectDeclaration(thisDescriptor, classOrObjectDeclaration, classifier, resolveSession.getTrace());
200 result.add(propertyDescriptor);
201 }
202 }
203
204 getNonDeclaredProperties(name, result);
205
206 return result;
207 }
208
209 protected abstract void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result);
210
211 @NotNull
212 @Override
213 public Collection<ClassDescriptor> getObjectDescriptors() {
214 return allDescriptors.compute().objects;
215 }
216
217 @Override
218 public VariableDescriptor getLocalVariable(@NotNull Name name) {
219 return null;
220 }
221
222 @NotNull
223 @Override
224 public DeclarationDescriptor getContainingDeclaration() {
225 return thisDescriptor;
226 }
227
228 @NotNull
229 @Override
230 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
231 // A member scope has no labels
232 return Collections.emptySet();
233 }
234
235 @Override
236 public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) {
237 throw new UnsupportedOperationException(); // TODO
238 }
239
240 @NotNull
241 @Override
242 public Collection<DeclarationDescriptor> getAllDescriptors() {
243 return allDescriptors.compute().all;
244 }
245
246 @NotNull
247 private AllDescriptors computeAllDescriptors() {
248 AllDescriptors result = new AllDescriptors();
249 for (JetDeclaration declaration : declarationProvider.getAllDeclarations()) {
250 if (declaration instanceof JetEnumEntry) {
251 JetEnumEntry jetEnumEntry = (JetEnumEntry) declaration;
252 Name name = safeNameForLazyResolve(jetEnumEntry);
253 if (name != null) {
254 result.all.addAll(getProperties(name));
255 result.objects.add(getObjectDescriptor(name));
256 }
257 }
258 else if (declaration instanceof JetObjectDeclaration) {
259 JetObjectDeclaration objectDeclaration = (JetObjectDeclaration) declaration;
260 Name name = safeNameForLazyResolve(objectDeclaration.getNameAsDeclaration());
261 if (name != null) {
262 result.all.addAll(getProperties(name));
263 result.objects.add(getObjectDescriptor(name));
264 }
265 }
266 else if (declaration instanceof JetClassOrObject) {
267 JetClassOrObject classOrObject = (JetClassOrObject) declaration;
268 Name name = safeNameForLazyResolve(classOrObject.getNameAsName());
269 if (name != null) {
270 result.all.addAll(classDescriptors.fun(name));
271 }
272 }
273 else if (declaration instanceof JetFunction) {
274 JetFunction function = (JetFunction) declaration;
275 result.all.addAll(getFunctions(safeNameForLazyResolve(function)));
276 }
277 else if (declaration instanceof JetProperty) {
278 JetProperty property = (JetProperty) declaration;
279 result.all.addAll(getProperties(safeNameForLazyResolve(property)));
280 }
281 else if (declaration instanceof JetParameter) {
282 JetParameter parameter = (JetParameter) declaration;
283 Name name = safeNameForLazyResolve(parameter);
284 result.all.addAll(getProperties(name));
285 }
286 else if (declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) {
287 // Do nothing for typedefs as they are not supported.
288 // MultiDeclarations are not supported on global level too.
289 }
290 else {
291 throw new IllegalArgumentException("Unsupported declaration kind: " + declaration);
292 }
293 }
294 addExtraDescriptors(result.all);
295 return result;
296 }
297
298 protected abstract void addExtraDescriptors(@NotNull Collection<DeclarationDescriptor> result);
299
300 @NotNull
301 @Override
302 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
303 ReceiverParameterDescriptor receiver = getImplicitReceiver();
304 if (receiver != null) {
305 return Collections.singletonList(receiver);
306 }
307 return Collections.emptyList();
308 }
309
310 @Nullable
311 protected abstract ReceiverParameterDescriptor getImplicitReceiver();
312
313 // Do not change this, override in concrete subclasses:
314 // it is very easy to compromise laziness of this class, and fail all the debugging
315 // a generic implementation can't do this properly
316 @Override
317 public abstract String toString();
318
319 @NotNull
320 @Override
321 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
322 return getAllDescriptors();
323 }
324 }