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