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