001 /*
002 * Copyright 2010-2014 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 kotlin.Function0;
023 import kotlin.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.*;
041
042 import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
043
044 public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, DP extends DeclarationProvider> implements JetScope {
045 protected final ResolveSession resolveSession;
046 protected final DP declarationProvider;
047 protected final D thisDescriptor;
048
049 private final MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> classDescriptors;
050
051 private final MemoizedFunctionToNotNull<Name, Set<FunctionDescriptor>> functionDescriptors;
052 private final MemoizedFunctionToNotNull<Name, Set<VariableDescriptor>> propertyDescriptors;
053
054 private final NotNullLazyValue<Collection<DeclarationDescriptor>> descriptorsFromDeclaredElements;
055 private final NotNullLazyValue<Collection<DeclarationDescriptor>> extraDescriptors;
056
057 protected AbstractLazyMemberScope(
058 @NotNull ResolveSession resolveSession,
059 @NotNull DP declarationProvider,
060 @NotNull D thisDescriptor
061 ) {
062 this.resolveSession = resolveSession;
063 this.declarationProvider = declarationProvider;
064 this.thisDescriptor = thisDescriptor;
065
066 StorageManager storageManager = resolveSession.getStorageManager();
067 this.classDescriptors = storageManager.createMemoizedFunction(new Function1<Name, List<ClassDescriptor>>() {
068 @Override
069 public List<ClassDescriptor> invoke(Name name) {
070 return resolveClassDescriptor(name);
071 }
072 });
073
074 this.functionDescriptors = storageManager.createMemoizedFunction(new Function1<Name, Set<FunctionDescriptor>>() {
075 @Override
076 public Set<FunctionDescriptor> invoke(Name name) {
077 return doGetFunctions(name);
078 }
079 });
080 this.propertyDescriptors = storageManager.createMemoizedFunction(new Function1<Name, Set<VariableDescriptor>>() {
081 @Override
082 public Set<VariableDescriptor> invoke(Name name) {
083 return doGetProperties(name);
084 }
085 });
086
087 this.descriptorsFromDeclaredElements = storageManager.createLazyValue(new Function0<Collection<DeclarationDescriptor>>() {
088 @Override
089 public Collection<DeclarationDescriptor> invoke() {
090 return computeDescriptorsFromDeclaredElements();
091 }
092 });
093 this.extraDescriptors = storageManager.createLazyValue(new Function0<Collection<DeclarationDescriptor>>() {
094 @Override
095 public Collection<DeclarationDescriptor> invoke() {
096 return computeExtraDescriptors();
097 }
098 });
099 }
100
101 @Nullable
102 private List<ClassDescriptor> resolveClassDescriptor(@NotNull final Name name) {
103 Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name);
104
105 return ContainerUtil.mapNotNull(classOrObjectDeclarations, new Function<JetClassOrObject, ClassDescriptor>() {
106 @Override
107 public ClassDescriptor fun(JetClassOrObject classOrObject) {
108 return new LazyClassDescriptor(resolveSession, thisDescriptor, name, JetClassInfoUtil.createClassLikeInfo(classOrObject));
109 }
110 });
111 }
112
113 @Override
114 public ClassifierDescriptor getClassifier(@NotNull Name name) {
115 return first(classDescriptors.invoke(name));
116 }
117
118 private static <T> T first(@NotNull List<T> list) {
119 if (list.isEmpty()) return null;
120 return list.get(0);
121 }
122
123 @NotNull
124 @Override
125 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
126 return functionDescriptors.invoke(name);
127 }
128
129 @NotNull
130 private Set<FunctionDescriptor> doGetFunctions(@NotNull Name name) {
131 Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
132
133 Collection<JetNamedFunction> declarations = declarationProvider.getFunctionDeclarations(name);
134 for (JetNamedFunction functionDeclaration : declarations) {
135 JetScope resolutionScope = getScopeForMemberDeclarationResolution(functionDeclaration);
136 result.add(resolveSession.getDescriptorResolver().resolveFunctionDescriptorWithAnnotationArguments(
137 thisDescriptor, resolutionScope,
138 functionDeclaration,
139 resolveSession.getTrace(),
140 // this relies on the assumption that a lazily resolved declaration is not a local one,
141 // thus doesn't have a surrounding data flow
142 DataFlowInfo.EMPTY)
143 );
144 }
145
146 getNonDeclaredFunctions(name, result);
147
148 return result;
149 }
150
151 @NotNull
152 protected abstract JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration);
153
154 protected abstract void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set<FunctionDescriptor> result);
155
156 @NotNull
157 @Override
158 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
159 return propertyDescriptors.invoke(name);
160 }
161
162 @NotNull
163 public Set<VariableDescriptor> doGetProperties(@NotNull Name name) {
164 Set<VariableDescriptor> result = Sets.newLinkedHashSet();
165
166 Collection<JetProperty> declarations = declarationProvider.getPropertyDeclarations(name);
167 for (JetProperty propertyDeclaration : declarations) {
168 JetScope resolutionScope = getScopeForMemberDeclarationResolution(propertyDeclaration);
169 PropertyDescriptor propertyDescriptor =
170 resolveSession.getDescriptorResolver().resolvePropertyDescriptor(
171 thisDescriptor, resolutionScope,
172 propertyDeclaration,
173 resolveSession.getTrace(),
174 // this relies on the assumption that a lazily resolved declaration is not a local one,
175 // thus doesn't have a surrounding data flow
176 DataFlowInfo.EMPTY);
177 result.add(propertyDescriptor);
178 resolveSession.getAnnotationResolver().resolveAnnotationsArguments(propertyDescriptor, resolveSession.getTrace(), resolutionScope);
179 }
180
181 getNonDeclaredProperties(name, result);
182
183 return result;
184 }
185
186 protected abstract void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result);
187
188 @Override
189 public VariableDescriptor getLocalVariable(@NotNull Name name) {
190 return null;
191 }
192
193 @NotNull
194 @Override
195 public DeclarationDescriptor getContainingDeclaration() {
196 return thisDescriptor;
197 }
198
199 @NotNull
200 @Override
201 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
202 // A member scope has no labels
203 return Collections.emptySet();
204 }
205
206 @NotNull
207 @Override
208 public Collection<DeclarationDescriptor> getAllDescriptors() {
209 Collection<DeclarationDescriptor> result = new LinkedHashSet<DeclarationDescriptor>(descriptorsFromDeclaredElements.invoke());
210 result.addAll(extraDescriptors.invoke());
211 return result;
212 }
213
214 @NotNull
215 private Collection<DeclarationDescriptor> computeDescriptorsFromDeclaredElements() {
216 List<JetDeclaration> declarations = declarationProvider.getAllDeclarations();
217 ArrayList<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>(declarations.size());
218 for (JetDeclaration declaration : declarations) {
219 if (declaration instanceof JetClassOrObject) {
220 JetClassOrObject classOrObject = (JetClassOrObject) declaration;
221 result.addAll(classDescriptors.invoke(safeNameForLazyResolve(classOrObject.getNameAsName())));
222 }
223 else if (declaration instanceof JetFunction) {
224 JetFunction function = (JetFunction) declaration;
225 result.addAll(getFunctions(safeNameForLazyResolve(function)));
226 }
227 else if (declaration instanceof JetProperty) {
228 JetProperty property = (JetProperty) declaration;
229 result.addAll(getProperties(safeNameForLazyResolve(property)));
230 }
231 else if (declaration instanceof JetParameter) {
232 JetParameter parameter = (JetParameter) declaration;
233 result.addAll(getProperties(safeNameForLazyResolve(parameter)));
234 }
235 else if (declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) {
236 // Do nothing for typedefs as they are not supported.
237 // MultiDeclarations are not supported on global level too.
238 }
239 else {
240 throw new IllegalArgumentException("Unsupported declaration kind: " + declaration);
241 }
242 }
243 result.trimToSize();
244 return result;
245 }
246
247 @NotNull
248 protected abstract Collection<DeclarationDescriptor> computeExtraDescriptors();
249
250 @NotNull
251 @Override
252 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
253 ReceiverParameterDescriptor receiver = getImplicitReceiver();
254 if (receiver != null) {
255 return Collections.singletonList(receiver);
256 }
257 return Collections.emptyList();
258 }
259
260 @Nullable
261 protected abstract ReceiverParameterDescriptor getImplicitReceiver();
262
263 // Do not change this, override in concrete subclasses:
264 // it is very easy to compromise laziness of this class, and fail all the debugging
265 // a generic implementation can't do this properly
266 @Override
267 public abstract String toString();
268
269 @NotNull
270 @Override
271 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
272 return getAllDescriptors();
273 }
274
275 @Override
276 public void printScopeStructure(@NotNull Printer p) {
277 p.println(getClass().getSimpleName(), " {");
278 p.pushIndent();
279
280 p.println("thisDescriptor = ", thisDescriptor);
281
282 p.popIndent();
283 p.println("}");
284 }
285 }