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