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