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