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