001 /*
002 * Copyright 2010-2015 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.kotlin.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 com.intellij.psi.PsiNameIdentifierOwner;
024 import kotlin.collections.CollectionsKt;
025 import kotlin.Unit;
026 import kotlin.jvm.functions.Function0;
027 import kotlin.jvm.functions.Function1;
028 import org.jetbrains.annotations.Mutable;
029 import org.jetbrains.annotations.NotNull;
030 import org.jetbrains.annotations.Nullable;
031 import org.jetbrains.annotations.ReadOnly;
032 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
033 import org.jetbrains.kotlin.descriptors.*;
034 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
035 import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase;
036 import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
037 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
038 import org.jetbrains.kotlin.lexer.KtTokens;
039 import org.jetbrains.kotlin.name.Name;
040 import org.jetbrains.kotlin.psi.*;
041 import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
042 import org.jetbrains.kotlin.resolve.*;
043 import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
044 import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
045 import org.jetbrains.kotlin.resolve.lazy.LazyEntity;
046 import org.jetbrains.kotlin.resolve.lazy.data.KtClassInfoUtil;
047 import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo;
048 import org.jetbrains.kotlin.resolve.lazy.data.KtClassOrObjectInfo;
049 import org.jetbrains.kotlin.resolve.lazy.data.KtObjectInfo;
050 import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider;
051 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
052 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
053 import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinClass;
054 import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
055 import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
056 import org.jetbrains.kotlin.storage.NotNullLazyValue;
057 import org.jetbrains.kotlin.storage.NullableLazyValue;
058 import org.jetbrains.kotlin.storage.StorageManager;
059 import org.jetbrains.kotlin.types.*;
060
061 import java.util.ArrayList;
062 import java.util.Collection;
063 import java.util.Collections;
064 import java.util.List;
065
066 import static kotlin.collections.CollectionsKt.firstOrNull;
067 import static org.jetbrains.kotlin.diagnostics.Errors.CYCLIC_INHERITANCE_HIERARCHY;
068 import static org.jetbrains.kotlin.diagnostics.Errors.TYPE_PARAMETERS_IN_ENUM;
069 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE;
070 import static org.jetbrains.kotlin.resolve.ModifiersChecker.*;
071
072 public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDescriptorWithResolutionScopes, LazyEntity {
073 private static final Predicate<KotlinType> VALID_SUPERTYPE = new Predicate<KotlinType>() {
074 @Override
075 public boolean apply(KotlinType type) {
076 assert !type.isError() : "Error types must be filtered out in DescriptorResolver";
077 return TypeUtils.getClassDescriptor(type) != null;
078 }
079 };
080 private final LazyClassContext c;
081
082 private final ClassMemberDeclarationProvider declarationProvider;
083
084 private final LazyClassTypeConstructor typeConstructor;
085 private final Modality modality;
086 private final Visibility visibility;
087 private final NotNullLazyValue<ClassKind> kind;
088 private final NotNullLazyValue<Boolean> isInner;
089 private final NotNullLazyValue<Boolean> isData;
090
091 private final Annotations annotations;
092 private final Annotations danglingAnnotations;
093 private final NullableLazyValue<LazyClassDescriptor> companionObjectDescriptor;
094 private final MemoizedFunctionToNotNull<KtObjectDeclaration, ClassDescriptor> extraCompanionObjectDescriptors;
095
096 private final LazyClassMemberScope unsubstitutedMemberScope;
097 private final MemberScope staticScope;
098
099 private final NullableLazyValue<Void> forceResolveAllContents;
100 private final boolean isCompanionObject;
101
102 private final ClassResolutionScopesSupport resolutionScopesSupport;
103 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters;
104
105 private final NotNullLazyValue<LexicalScope> scopeForInitializerResolution;
106
107 public LazyClassDescriptor(
108 @NotNull final LazyClassContext c,
109 @NotNull DeclarationDescriptor containingDeclaration,
110 @NotNull Name name,
111 @NotNull final KtClassLikeInfo classLikeInfo
112 ) {
113 super(c.getStorageManager(), containingDeclaration, name,
114 KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject())
115 );
116 this.c = c;
117
118 KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
119 if (classOrObject != null) {
120 this.c.getTrace().record(BindingContext.CLASS, classOrObject, this);
121 }
122 this.c.getTrace().record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this);
123
124 this.declarationProvider = c.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);
125
126 this.unsubstitutedMemberScope = createMemberScope(c, this.declarationProvider);
127 this.staticScope = new StaticScopeForKotlinClass(this);
128
129 this.typeConstructor = new LazyClassTypeConstructor();
130
131 final ClassKind syntaxKind = classLikeInfo.getClassKind();
132 this.isCompanionObject = classLikeInfo instanceof KtObjectInfo && ((KtObjectInfo) classLikeInfo).isCompanionObject();
133
134 final KtModifierList modifierList = classLikeInfo.getModifierList();
135 if (syntaxKind.isSingleton()) {
136 this.modality = Modality.FINAL;
137 }
138 else {
139 Modality defaultModality = syntaxKind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL;
140 this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
141 }
142
143 boolean isLocal = classOrObject != null && KtPsiUtil.isLocal(classOrObject);
144 Visibility defaultVisibility;
145 if (syntaxKind == ClassKind.ENUM_ENTRY || (syntaxKind == ClassKind.OBJECT && isCompanionObject)) {
146 defaultVisibility = Visibilities.PUBLIC;
147 }
148 else {
149 defaultVisibility = Visibilities.DEFAULT_VISIBILITY;
150 }
151 this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, defaultVisibility);
152
153 StorageManager storageManager = c.getStorageManager();
154 final ClassDescriptor descriptor = this;
155
156 this.isInner = storageManager.createLazyValue(new Function0<Boolean>() {
157 @Override
158 public Boolean invoke() {
159 return isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(descriptor);
160 }
161 });
162
163 this.isData = storageManager.createLazyValue(new Function0<Boolean>() {
164 @Override
165 public Boolean invoke() {
166 return modifierList != null && modifierList.hasModifier(KtTokens.DATA_KEYWORD);
167 }
168 });
169
170 this.kind = storageManager.createLazyValue(new Function0<ClassKind>() {
171 @Override
172 public ClassKind invoke() {
173 return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
174 }
175 });
176 // Annotation entries are taken from both own annotations (if any) and object literal annotations (if any)
177 List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
178 if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
179 // TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
180 annotationEntries.addAll(KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
181 }
182 if (modifierList != null) {
183 annotationEntries.addAll(modifierList.getAnnotationEntries());
184 }
185 if (!annotationEntries.isEmpty()) {
186 this.annotations = new LazyAnnotations(
187 new LazyAnnotationsContext(
188 c.getAnnotationResolver(),
189 storageManager,
190 c.getTrace()
191 ) {
192 @NotNull
193 @Override
194 public LexicalScope getScope() {
195 return getOuterScope();
196 }
197 },
198 annotationEntries
199 );
200 }
201 else {
202 this.annotations = Annotations.Companion.getEMPTY();
203 }
204
205 List<KtAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations();
206 if (jetDanglingAnnotations.isEmpty()) {
207 this.danglingAnnotations = Annotations.Companion.getEMPTY();
208 }
209 else {
210 this.danglingAnnotations = new LazyAnnotations(
211 new LazyAnnotationsContext(
212 c.getAnnotationResolver(),
213 storageManager,
214 c.getTrace()
215 ) {
216 @NotNull
217 @Override
218 public LexicalScope getScope() {
219 return getScopeForMemberDeclarationResolution();
220 }
221 },
222 jetDanglingAnnotations
223 );
224 }
225
226 this.companionObjectDescriptor = storageManager.createNullableLazyValue(new Function0<LazyClassDescriptor>() {
227 @Override
228 public LazyClassDescriptor invoke() {
229 return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed());
230 }
231 });
232 this.extraCompanionObjectDescriptors = storageManager.createMemoizedFunction(new Function1<KtObjectDeclaration, ClassDescriptor>() {
233 @Override
234 public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
235 return computeCompanionObjectDescriptor(companionObject);
236 }
237 });
238 this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0<Void>() {
239 @Override
240 public Void invoke() {
241 doForceResolveAllContents();
242 return null;
243 }
244 }, null);
245
246 this.resolutionScopesSupport = new ClassResolutionScopesSupport(this, storageManager, new Function0<LexicalScope>() {
247 @Override
248 public LexicalScope invoke() {
249 return getOuterScope();
250 }
251 });
252
253 this.parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
254 @Override
255 public List<TypeParameterDescriptor> invoke() {
256 KtClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
257 KtTypeParameterList typeParameterList = classInfo.getTypeParameterList();
258 if (typeParameterList == null) return Collections.emptyList();
259
260 if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) {
261 c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList));
262 }
263
264 List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
265
266 List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
267
268 for (int i = 0; i < typeParameters.size(); i++) {
269 parameters.add(new LazyTypeParameterDescriptor(c, LazyClassDescriptor.this, typeParameters.get(i), i));
270 }
271
272 return parameters;
273 }
274 });
275
276 this.scopeForInitializerResolution = storageManager.createLazyValue(new Function0<LexicalScope>() {
277 @Override
278 public LexicalScope invoke() {
279 return ClassResolutionScopesSupportKt.scopeForInitializerResolution(LazyClassDescriptor.this,
280 createInitializerScopeParent(),
281 classLikeInfo.getPrimaryConstructorParameters());
282 }
283 });
284 }
285
286 @NotNull
287 private DeclarationDescriptor createInitializerScopeParent() {
288 ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
289 if (primaryConstructor != null) return primaryConstructor;
290
291 return new FunctionDescriptorImpl(LazyClassDescriptor.this, null, Annotations.Companion.getEMPTY(),
292 Name.special("<init-blocks>"),
293 CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE) {
294 @NotNull
295 @Override
296 protected FunctionDescriptorImpl createSubstitutedCopy(
297 @NotNull DeclarationDescriptor newOwner,
298 @Nullable FunctionDescriptor original,
299 @NotNull Kind kind,
300 @Nullable Name newName,
301 boolean preserveSource
302 ) {
303 throw new UnsupportedOperationException();
304 }
305
306 @NotNull
307 @Override
308 public FunctionDescriptor copy(
309 DeclarationDescriptor newOwner,
310 Modality modality,
311 Visibility visibility,
312 Kind kind,
313 boolean copyOverrides
314 ) {
315 throw new UnsupportedOperationException();
316 }
317 };
318 }
319
320 // NOTE: Called from constructor!
321 @NotNull
322 protected LazyClassMemberScope createMemberScope(
323 @NotNull LazyClassContext c,
324 @NotNull ClassMemberDeclarationProvider declarationProvider
325 ) {
326 return new LazyClassMemberScope(c, declarationProvider, this, c.getTrace());
327 }
328
329 @NotNull
330 @Override
331 public MemberScope getUnsubstitutedMemberScope() {
332 return unsubstitutedMemberScope;
333 }
334
335 @NotNull
336 protected LexicalScope getOuterScope() {
337 return c.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declarationProvider.getOwnerInfo().getScopeAnchor());
338 }
339
340 @Override
341 @NotNull
342 public LexicalScope getScopeForClassHeaderResolution() {
343 return resolutionScopesSupport.getScopeForClassHeaderResolution().invoke();
344 }
345
346 @Override
347 @NotNull
348 public LexicalScope getScopeForConstructorHeaderResolution() {
349 return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke();
350 }
351
352 @Override
353 @NotNull
354 public LexicalScope getScopeForCompanionObjectHeaderResolution() {
355 return resolutionScopesSupport.getScopeForCompanionObjectHeaderResolution().invoke();
356 }
357
358 @Override
359 @NotNull
360 public LexicalScope getScopeForMemberDeclarationResolution() {
361 return resolutionScopesSupport.getScopeForMemberDeclarationResolution().invoke();
362 }
363
364 @Override
365 @NotNull
366 public LexicalScope getScopeForStaticMemberDeclarationResolution() {
367 return resolutionScopesSupport.getScopeForStaticMemberDeclarationResolution().invoke();
368 }
369
370 @Override
371 @NotNull
372 public LexicalScope getScopeForInitializerResolution() {
373 return scopeForInitializerResolution.invoke();
374 }
375
376 @NotNull
377 @Override
378 public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
379 //noinspection unchecked
380 return (Collection) CollectionsKt.filter(
381 DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope),
382 new Function1<DeclarationDescriptor, Boolean>() {
383 @Override
384 public Boolean invoke(DeclarationDescriptor descriptor) {
385 return descriptor instanceof CallableMemberDescriptor
386 && ((CallableMemberDescriptor) descriptor).getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
387 }
388 }
389 );
390 }
391
392 @NotNull
393 @Override
394 public MemberScope getStaticScope() {
395 return staticScope;
396 }
397
398 @NotNull
399 @Override
400 public Collection<ConstructorDescriptor> getConstructors() {
401 return unsubstitutedMemberScope.getConstructors();
402 }
403
404 @Override
405 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
406 return unsubstitutedMemberScope.getPrimaryConstructor();
407 }
408
409 @NotNull
410 @Override
411 public TypeConstructor getTypeConstructor() {
412 return typeConstructor;
413 }
414
415 @Override
416 public LazyClassDescriptor getCompanionObjectDescriptor() {
417 return companionObjectDescriptor.invoke();
418 }
419
420 @NotNull
421 @ReadOnly
422 public List<ClassDescriptor> getDescriptorsForExtraCompanionObjects() {
423 final KtObjectDeclaration allowedCompanionObject = getCompanionObjectIfAllowed();
424
425 return CollectionsKt.map(
426 CollectionsKt.filter(
427 declarationProvider.getOwnerInfo().getCompanionObjects(),
428 new Function1<KtObjectDeclaration, Boolean>() {
429 @Override
430 public Boolean invoke(KtObjectDeclaration companionObject) {
431 return companionObject != allowedCompanionObject;
432 }
433 }
434 ),
435 new Function1<KtObjectDeclaration, ClassDescriptor>() {
436 @Override
437 public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
438 return extraCompanionObjectDescriptors.invoke(companionObject);
439 }
440 }
441 );
442 }
443
444 @Nullable
445 private LazyClassDescriptor computeCompanionObjectDescriptor(@Nullable KtObjectDeclaration companionObject) {
446 KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
447 if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
448 return null;
449 }
450 Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName();
451 assert name != null;
452 getUnsubstitutedMemberScope().getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
453 ClassDescriptor companionObjectDescriptor = c.getTrace().get(BindingContext.CLASS, companionObject);
454 if (companionObjectDescriptor instanceof LazyClassDescriptor) {
455 assert DescriptorUtils.isCompanionObject(companionObjectDescriptor) : "Not a companion object: " + companionObjectDescriptor;
456 return (LazyClassDescriptor) companionObjectDescriptor;
457 }
458 else {
459 return null;
460 }
461 }
462
463 @Nullable
464 private static KtClassLikeInfo getCompanionObjectInfo(@Nullable KtObjectDeclaration companionObject) {
465 if (companionObject != null) {
466 return KtClassInfoUtil.createClassLikeInfo(companionObject);
467 }
468
469 return null;
470 }
471
472 @Nullable
473 private KtObjectDeclaration getCompanionObjectIfAllowed() {
474 KtObjectDeclaration companionObject = firstOrNull(declarationProvider.getOwnerInfo().getCompanionObjects());
475 return (companionObject != null && isCompanionObjectAllowed()) ? companionObject : null;
476 }
477
478 private boolean isCompanionObjectAllowed() {
479 return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this));
480 }
481
482 @NotNull
483 @Override
484 public ClassKind getKind() {
485 return kind.invoke();
486 }
487
488 @NotNull
489 @Override
490 public Modality getModality() {
491 return modality;
492 }
493
494 @NotNull
495 @Override
496 public Visibility getVisibility() {
497 return visibility;
498 }
499
500 @Override
501 public boolean isInner() {
502 return isInner.invoke();
503 }
504
505 @Override
506 public boolean isData() {
507 return isData.invoke();
508 }
509
510 @Override
511 public boolean isCompanionObject() {
512 return isCompanionObject;
513 }
514
515 @NotNull
516 @Override
517 public Annotations getAnnotations() {
518 return annotations;
519 }
520
521 @NotNull
522 public Annotations getDanglingAnnotations() {
523 return danglingAnnotations;
524 }
525
526 @Override
527 public String toString() {
528 // not using descriptor render to preserve laziness
529 return "lazy class " + getName().toString();
530 }
531
532 @Override
533 public void forceResolveAllContents() {
534 forceResolveAllContents.invoke();
535 }
536
537 private void doForceResolveAllContents() {
538 resolveMemberHeaders();
539 ClassDescriptor companionObjectDescriptor = getCompanionObjectDescriptor();
540 if (companionObjectDescriptor != null) {
541 ForceResolveUtil.forceResolveAllContents(companionObjectDescriptor);
542 }
543
544 ForceResolveUtil.forceResolveAllContents(getConstructors());
545 ForceResolveUtil.forceResolveAllContents(getDescriptorsForExtraCompanionObjects());
546 ForceResolveUtil.forceResolveAllContents(getUnsubstitutedMemberScope());
547 ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
548 }
549
550 // Note: headers of member classes' members are not resolved
551 public void resolveMemberHeaders() {
552 ForceResolveUtil.forceResolveAllContents(getAnnotations());
553 ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());
554
555 getCompanionObjectDescriptor();
556
557 getDescriptorsForExtraCompanionObjects();
558
559 getConstructors();
560 getContainingDeclaration();
561 getThisAsReceiverParameter();
562 getKind();
563 getModality();
564 getName();
565 getOriginal();
566 getScopeForClassHeaderResolution();
567 getScopeForMemberDeclarationResolution();
568 DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope());
569 getScopeForInitializerResolution();
570 getUnsubstitutedInnerClassesScope();
571 getTypeConstructor().getSupertypes();
572 for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
573 typeParameterDescriptor.getUpperBounds();
574 }
575 getUnsubstitutedPrimaryConstructor();
576 getVisibility();
577 }
578
579 @NotNull
580 @Override
581 public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
582 return parameters.invoke();
583 }
584
585 private static class Supertypes {
586 @Mutable
587 public final Collection<KotlinType> trueSupertypes;
588 @Mutable
589 public final Collection<KotlinType> allSuperTypes;
590
591 private Supertypes(@Mutable @NotNull Collection<KotlinType> allSuperTypes) {
592 this.trueSupertypes = allSuperTypes;
593 this.allSuperTypes = new ArrayList<KotlinType>(allSuperTypes);
594 }
595
596 @NotNull
597 public Collection<KotlinType> getAllSupertypes() {
598 return allSuperTypes;
599 }
600 }
601
602 private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity {
603 private final NotNullLazyValue<Supertypes> supertypes = c.getStorageManager().createLazyValueWithPostCompute(
604 new Function0<Supertypes>() {
605 @Override
606 public Supertypes invoke() {
607 if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
608 return new Supertypes(Collections.<KotlinType>emptyList());
609 }
610
611 KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
612 if (classOrObject == null) {
613 return new Supertypes(Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType()));
614 }
615
616 List<KotlinType> allSupertypes = c.getDescriptorResolver()
617 .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
618 c.getTrace());
619
620 return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)));
621 }
622 },
623 new Function1<Boolean, Supertypes>() {
624 @Override
625 public Supertypes invoke(Boolean firstTime) {
626 return new Supertypes(Collections.<KotlinType>emptyList());
627 }
628 },
629 new Function1<Supertypes, Unit>() {
630 @Override
631 public Unit invoke(@NotNull Supertypes supertypes) {
632 findAndDisconnectLoopsInTypeHierarchy(supertypes.trueSupertypes);
633 return Unit.INSTANCE;
634 }
635 }
636 );
637
638 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
639 @Override
640 public List<TypeParameterDescriptor> invoke() {
641 return TypeParameterUtilsKt.computeConstructorTypeParameters(LazyClassDescriptor.this);
642 }
643 });
644
645 private final NullableLazyValue<Void> forceResolveAllContents =
646 c.getStorageManager().createRecursionTolerantNullableLazyValue(new Function0<Void>() {
647 @Override
648 public Void invoke() {
649 doForceResolveAllContents();
650 return null;
651 }
652 }, null);
653
654 @NotNull
655 @Override
656 public List<TypeParameterDescriptor> getParameters() {
657 return parameters.invoke();
658 }
659
660 @NotNull
661 @Override
662 public Collection<KotlinType> getSupertypes() {
663 return supertypes.invoke().trueSupertypes;
664 }
665
666 private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection<KotlinType> supertypes) {
667 c.getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect(
668 typeConstructor, supertypes,
669 new Function1<TypeConstructor, Iterable<? extends KotlinType>>() {
670 @Override
671 public Iterable<? extends KotlinType> invoke(TypeConstructor typeConstructor) {
672 return getNeighbors(typeConstructor);
673 }
674 },
675 new Function1<KotlinType, Unit>() {
676 @Override
677 public Unit invoke(KotlinType type) {
678 ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor();
679 if (supertypeDescriptor instanceof ClassDescriptor) {
680 ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
681 reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass);
682 }
683
684 return Unit.INSTANCE;
685 }
686 }
687 );
688 }
689
690 private void reportCyclicInheritanceHierarchyError(
691 @NotNull BindingTrace trace,
692 @NotNull ClassDescriptor classDescriptor,
693 @NotNull ClassDescriptor superclass
694 ) {
695 PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);
696
697 PsiElement elementToMark = null;
698 if (psiElement instanceof KtClassOrObject) {
699 KtClassOrObject classOrObject = (KtClassOrObject) psiElement;
700 for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) {
701 KtTypeReference typeReference = delegationSpecifier.getTypeReference();
702 if (typeReference == null) continue;
703 KotlinType supertype = trace.get(TYPE, typeReference);
704 if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
705 elementToMark = typeReference;
706 }
707 }
708 }
709 if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
710 PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
711 PsiElement nameIdentifier = namedElement.getNameIdentifier();
712 if (nameIdentifier != null) {
713 elementToMark = nameIdentifier;
714 }
715 }
716 if (elementToMark != null) {
717 trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
718 }
719 }
720
721 private Collection<KotlinType> getNeighbors(TypeConstructor from) {
722 // Supertypes + type for container
723 Collection<KotlinType> neighbours = new ArrayList<KotlinType>(
724 from instanceof LazyClassTypeConstructor
725 ? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes()
726 : from.getSupertypes()
727 );
728
729 ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor();
730 if (fromDescriptor != null) {
731 DeclarationDescriptor container = fromDescriptor.getContainingDeclaration();
732 if (container instanceof ClassDescriptor) {
733 neighbours.add(((ClassDescriptor) container).getDefaultType());
734 }
735 }
736 return neighbours;
737 }
738
739 @Override
740 public boolean isFinal() {
741 return getModality() == Modality.FINAL;
742 }
743
744 @Override
745 public boolean isDenotable() {
746 return true;
747 }
748
749 @Override
750 @NotNull
751 public ClassifierDescriptor getDeclarationDescriptor() {
752 return LazyClassDescriptor.this;
753 }
754
755 @NotNull
756 @Override
757 public Annotations getAnnotations() {
758 return Annotations.Companion.getEMPTY(); // TODO
759 }
760
761 @Override
762 public String toString() {
763 return LazyClassDescriptor.this.getName().toString();
764 }
765
766 @Override
767 public void forceResolveAllContents() {
768 forceResolveAllContents.invoke();
769 }
770
771 private void doForceResolveAllContents() {
772 ForceResolveUtil.forceResolveAllContents(getAnnotations());
773 ForceResolveUtil.forceResolveAllContents(getSupertypes());
774 ForceResolveUtil.forceResolveAllContents(getParameters());
775 }
776 }
777 }