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