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