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.base.Predicate;
020 import com.google.common.collect.Collections2;
021 import com.google.common.collect.Lists;
022 import com.intellij.psi.PsiElement;
023 import jet.Function0;
024 import jet.Function1;
025 import jet.Unit;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.jet.lang.descriptors.*;
029 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
030 import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase;
031 import org.jetbrains.jet.lang.psi.*;
032 import org.jetbrains.jet.lang.resolve.AnnotationResolver;
033 import org.jetbrains.jet.lang.resolve.BindingContext;
034 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
035 import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
036 import org.jetbrains.jet.lang.resolve.lazy.LazyDescriptor;
037 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
038 import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
039 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
040 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
041 import org.jetbrains.jet.lang.resolve.lazy.data.SyntheticClassObjectInfo;
042 import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider;
043 import org.jetbrains.jet.lang.resolve.name.Name;
044 import org.jetbrains.jet.lang.resolve.scopes.*;
045 import org.jetbrains.jet.lang.types.JetType;
046 import org.jetbrains.jet.lang.types.TypeConstructor;
047 import org.jetbrains.jet.lang.types.TypeUtils;
048 import org.jetbrains.jet.storage.NotNullLazyValue;
049 import org.jetbrains.jet.storage.NullableLazyValue;
050 import org.jetbrains.jet.storage.StorageManager;
051
052 import java.util.*;
053
054 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isSyntheticClassObject;
055 import static org.jetbrains.jet.lang.resolve.ModifiersChecker.*;
056 import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
057
058 public class LazyClassDescriptor extends ClassDescriptorBase implements LazyDescriptor, ClassDescriptor {
059 private static final Predicate<JetType> VALID_SUPERTYPE = new Predicate<JetType>() {
060 @Override
061 public boolean apply(JetType type) {
062 assert !type.isError() : "Error types must be filtered out in DescriptorResolver";
063 return TypeUtils.getClassDescriptor(type) != null;
064 }
065 };
066 private final ResolveSession resolveSession;
067 private final JetClassLikeInfo originalClassInfo;
068 private final ClassMemberDeclarationProvider declarationProvider;
069
070 private final LazyClassTypeConstructor typeConstructor;
071 private final Modality modality;
072 private final Visibility visibility;
073 private final ClassKind kind;
074 private final boolean isInner;
075
076 private final NotNullLazyValue<List<AnnotationDescriptor>> annotations;
077 private final NullableLazyValue<ClassDescriptor> classObjectDescriptor;
078
079 private final LazyClassMemberScope unsubstitutedMemberScope;
080
081 private final NotNullLazyValue<JetScope> scopeForClassHeaderResolution;
082 private final NotNullLazyValue<JetScope> scopeForMemberDeclarationResolution;
083 private final NotNullLazyValue<JetScope> scopeForPropertyInitializerResolution;
084
085 public LazyClassDescriptor(
086 @NotNull ResolveSession resolveSession,
087 @NotNull DeclarationDescriptor containingDeclaration,
088 @NotNull Name name,
089 @NotNull JetClassLikeInfo classLikeInfo
090 ) {
091 super(resolveSession.getStorageManager(), containingDeclaration, name);
092 this.resolveSession = resolveSession;
093
094 if (classLikeInfo.getCorrespondingClassOrObject() != null) {
095 this.resolveSession.getTrace().record(BindingContext.CLASS, classLikeInfo.getCorrespondingClassOrObject(), this);
096 }
097
098 this.originalClassInfo = classLikeInfo;
099 this.declarationProvider = resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);
100
101 this.unsubstitutedMemberScope = new LazyClassMemberScope(resolveSession, declarationProvider, this);
102
103 this.typeConstructor = new LazyClassTypeConstructor();
104
105 this.kind = classLikeInfo.getClassKind();
106
107 JetModifierList modifierList = classLikeInfo.getModifierList();
108 if (kind.isSingleton()) {
109 this.modality = Modality.FINAL;
110 }
111 else {
112 Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL;
113 this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
114 }
115 this.visibility = isSyntheticClassObject(this)
116 ? DescriptorUtils.getSyntheticClassObjectVisibility()
117 : resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this));
118 this.isInner = isInnerClass(modifierList);
119
120 StorageManager storageManager = resolveSession.getStorageManager();
121 this.annotations = storageManager.createLazyValue(new Function0<List<AnnotationDescriptor>>() {
122 @Override
123 public List<AnnotationDescriptor> invoke() {
124 return resolveAnnotations();
125 }
126 });
127 this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptor>() {
128 @Override
129 public ClassDescriptor invoke() {
130 return computeClassObjectDescriptor();
131 }
132 });
133 this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Function0<JetScope>() {
134 @Override
135 public JetScope invoke() {
136 return computeScopeForClassHeaderResolution();
137 }
138 });
139 this.scopeForMemberDeclarationResolution = storageManager.createLazyValue(new Function0<JetScope>() {
140 @Override
141 public JetScope invoke() {
142 return computeScopeForMemberDeclarationResolution();
143 }
144 });
145 this.scopeForPropertyInitializerResolution = storageManager.createLazyValue(new Function0<JetScope>() {
146 @Override
147 public JetScope invoke() {
148 return computeScopeForPropertyInitializerResolution();
149 }
150 });
151 }
152
153 @NotNull
154 @Override
155 protected JetScope getScopeForMemberLookup() {
156 return unsubstitutedMemberScope;
157 }
158
159 @NotNull
160 public JetScope getScopeForClassHeaderResolution() {
161 return scopeForClassHeaderResolution.invoke();
162 }
163
164 @NotNull
165 private JetScope computeScopeForClassHeaderResolution() {
166 WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with type parameters for " + getName());
167 for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
168 scope.addClassifierDescriptor(typeParameterDescriptor);
169 }
170 scope.changeLockLevel(WritableScope.LockLevel.READING);
171
172 PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
173
174 return new ChainedScope(this, "ScopeForClassHeaderResolution: " + getName(),
175 scope,
176 getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
177 }
178
179 @NotNull
180 public JetScope getScopeForMemberDeclarationResolution() {
181 return scopeForMemberDeclarationResolution.invoke();
182 }
183
184 @NotNull
185 private JetScope computeScopeForMemberDeclarationResolution() {
186 WritableScopeImpl thisScope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with 'this' for " + getName());
187 thisScope.addLabeledDeclaration(this);
188 thisScope.changeLockLevel(WritableScope.LockLevel.READING);
189
190 ClassDescriptor classObject = getClassObjectDescriptor();
191 JetScope classObjectAdapterScope = (classObject != null) ? new ClassObjectMixinScope(classObject) : JetScope.EMPTY;
192
193 return new ChainedScope(
194 this,
195 "ScopeForMemberDeclarationResolution: " + getName(),
196 thisScope,
197 getScopeForMemberLookup(),
198 getScopeForClassHeaderResolution(),
199 classObjectAdapterScope);
200 }
201
202 @NotNull
203 public JetScope getScopeForPropertyInitializerResolution() {
204 return scopeForPropertyInitializerResolution.invoke();
205 }
206
207 @NotNull
208 private JetScope computeScopeForPropertyInitializerResolution() {
209 ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
210 if (primaryConstructor == null) return getScopeForMemberDeclarationResolution();
211
212 WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with constructor parameters in " + getName());
213 for (ValueParameterDescriptor valueParameterDescriptor : primaryConstructor.getValueParameters()) {
214 scope.addVariableDescriptor(valueParameterDescriptor);
215 }
216 scope.changeLockLevel(WritableScope.LockLevel.READING);
217
218 return new ChainedScope(
219 this,
220 "ScopeForPropertyInitializerResolution: " + getName(),
221 scope, getScopeForMemberDeclarationResolution());
222 }
223
224 @NotNull
225 @Override
226 public Collection<ConstructorDescriptor> getConstructors() {
227 return unsubstitutedMemberScope.getConstructors();
228 }
229
230 @Override
231 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
232 return unsubstitutedMemberScope.getPrimaryConstructor();
233 }
234
235 @NotNull
236 @Override
237 public TypeConstructor getTypeConstructor() {
238 return typeConstructor;
239 }
240
241 @Override
242 public ClassDescriptor getClassObjectDescriptor() {
243 return classObjectDescriptor.invoke();
244 }
245
246 @Nullable
247 private ClassDescriptor computeClassObjectDescriptor() {
248 JetClassObject classObject = declarationProvider.getOwnerInfo().getClassObject();
249
250 JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
251 if (classObjectInfo != null) {
252 return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
253 }
254 return null;
255 }
256
257 @Nullable
258 public JetClassLikeInfo getClassObjectInfo(JetClassObject classObject) {
259 if (classObject != null) {
260 if (!DescriptorUtils.inStaticContext(this)) {
261 return null;
262 }
263 JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
264 if (objectDeclaration != null) {
265 return JetClassInfoUtil.createClassLikeInfo(objectDeclaration);
266 }
267 }
268 else if (getKind() == ClassKind.OBJECT || getKind() == ClassKind.ENUM_ENTRY || getKind() == ClassKind.ENUM_CLASS) {
269 return new SyntheticClassObjectInfo(originalClassInfo, this);
270 }
271 return null;
272 }
273
274 @NotNull
275 @Override
276 public ClassKind getKind() {
277 return kind;
278 }
279
280 @NotNull
281 @Override
282 public Modality getModality() {
283 return modality;
284 }
285
286 @NotNull
287 @Override
288 public Visibility getVisibility() {
289 return visibility;
290 }
291
292 @Override
293 public boolean isInner() {
294 return isInner;
295 }
296
297 @NotNull
298 @Override
299 public List<AnnotationDescriptor> getAnnotations() {
300 return annotations.invoke();
301 }
302
303 @NotNull
304 private List<AnnotationDescriptor> resolveAnnotations() {
305 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
306 JetModifierList modifierList = classInfo.getModifierList();
307 if (modifierList != null) {
308 AnnotationResolver annotationResolver = resolveSession.getInjector().getAnnotationResolver();
309 JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(classInfo.getScopeAnchor());
310 return annotationResolver.resolveAnnotationsWithArguments(scopeForDeclaration, modifierList, resolveSession.getTrace());
311 }
312 else {
313 return Collections.emptyList();
314 }
315 }
316
317 @Override
318 public String toString() {
319 return "lazy class " + getName().toString();
320 }
321
322 @Override
323 public void forceResolveAllContents() {
324 getAnnotations();
325 getClassObjectDescriptor();
326 getClassObjectType();
327 getConstructors();
328 getContainingDeclaration();
329 getThisAsReceiverParameter();
330 getKind();
331 getModality();
332 getName();
333 getOriginal();
334 getScopeForClassHeaderResolution();
335 getScopeForMemberDeclarationResolution();
336 ForceResolveUtil.forceResolveAllContents(getScopeForMemberLookup());
337 getScopeForPropertyInitializerResolution();
338 getUnsubstitutedInnerClassesScope();
339 ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
340 getUnsubstitutedPrimaryConstructor();
341 getVisibility();
342 }
343
344 private class LazyClassTypeConstructor implements LazyDescriptor, TypeConstructor {
345 private final NotNullLazyValue<Collection<JetType>> supertypes = resolveSession.getStorageManager().createLazyValueWithPostCompute(
346 new Function0<Collection<JetType>>() {
347 @Override
348 public Collection<JetType> invoke() {
349 if (resolveSession.isClassSpecial(DescriptorUtils.getFQName(LazyClassDescriptor.this))) {
350 return Collections.emptyList();
351 }
352
353 JetClassLikeInfo info = declarationProvider.getOwnerInfo();
354 if (info instanceof SyntheticClassObjectInfo) {
355 LazyClassDescriptor descriptor = ((SyntheticClassObjectInfo) info).getClassDescriptor();
356 if (descriptor.getKind().isSingleton()) {
357 return Collections.singleton(descriptor.getDefaultType());
358 }
359 }
360
361 JetClassOrObject classOrObject = info.getCorrespondingClassOrObject();
362 if (classOrObject == null) {
363 return Collections.emptyList();
364 }
365
366 List<JetType> allSupertypes = resolveSession.getInjector().getDescriptorResolver()
367 .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
368 resolveSession.getTrace());
369
370 return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
371 }
372 },
373 new Function1<Boolean, Collection<JetType>>() {
374 @Override
375 public Collection<JetType> invoke(Boolean firstTime) {
376 return Collections.emptyList();
377 }
378 },
379 new Function1<Collection<JetType>, Unit>() {
380 @Override
381 public Unit invoke(@NotNull Collection<JetType> supertypes) {
382 findAndDisconnectLoopsInTypeHierarchy(supertypes);
383 return Unit.VALUE;
384 }
385 });
386
387 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = resolveSession.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
388 @Override
389 public List<TypeParameterDescriptor> invoke() {
390 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
391 List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
392
393 List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
394 for (int i = 0; i < typeParameters.size(); i++) {
395 parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i));
396 }
397
398 return parameters;
399 }
400 });
401
402 @NotNull
403 @Override
404 public List<TypeParameterDescriptor> getParameters() {
405 return parameters.invoke();
406 }
407
408 @NotNull
409 @Override
410 public Collection<JetType> getSupertypes() {
411 return supertypes.invoke();
412 }
413
414 private void findAndDisconnectLoopsInTypeHierarchy(Collection<JetType> supertypes) {
415 for (Iterator<JetType> iterator = supertypes.iterator(); iterator.hasNext(); ) {
416 JetType supertype = iterator.next();
417 if (isReachable(supertype.getConstructor(), this, new HashSet<TypeConstructor>())) {
418 iterator.remove();
419 }
420 }
421 }
422
423 private boolean isReachable(TypeConstructor from, TypeConstructor to, Set<TypeConstructor> visited) {
424 if (!visited.add(from)) return false;
425 for (JetType supertype : from.getSupertypes()) {
426 TypeConstructor supertypeConstructor = supertype.getConstructor();
427 if (supertypeConstructor == to) {
428 return true;
429 }
430 if (isReachable(supertypeConstructor, to, visited)) {
431 return true;
432 }
433 }
434 return false;
435 }
436
437 @Override
438 public boolean isFinal() {
439 return !getModality().isOverridable();
440 }
441
442 @Override
443 public boolean isDenotable() {
444 return true;
445 }
446
447 @Override
448 public ClassifierDescriptor getDeclarationDescriptor() {
449 return LazyClassDescriptor.this;
450 }
451
452 @NotNull
453 @Override
454 public List<AnnotationDescriptor> getAnnotations() {
455 return Collections.emptyList(); // TODO
456 }
457
458 @Override
459 public String toString() {
460 return LazyClassDescriptor.this.getName().toString();
461 }
462
463 @Override
464 public void forceResolveAllContents() {
465 getAnnotations();
466 getSupertypes();
467 getParameters();
468 }
469 }
470
471 @NotNull
472 private ScopeProvider getScopeProvider() {
473 return resolveSession.getInjector().getScopeProvider();
474 }
475 }