private void detectAndDisconnectLoops(@NotNull TopDownAnalysisContext c) { // Loop detection and disconnection List<Runnable> tasks = new ArrayList<Runnable>(); for (final MutableClassDescriptorLite klass : c.getClassesTopologicalOrder()) { for (final JetType supertype : klass.getSupertypes()) { ClassifierDescriptor supertypeDescriptor = supertype.getConstructor().getDeclarationDescriptor(); if (supertypeDescriptor instanceof MutableClassDescriptorLite) { MutableClassDescriptorLite superclass = (MutableClassDescriptorLite) supertypeDescriptor; if (isReachable(superclass, klass, new HashSet<ClassDescriptor>())) { tasks.add( new Runnable() { @Override public void run() { klass.getSupertypes().remove(supertype); } }); reportCyclicInheritanceHierarchyError(trace, klass, superclass); } } } } for (Runnable task : tasks) { task.run(); } }
private void createTypeConstructors(@NotNull TopDownAnalysisContext c) { for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) { JetClassOrObject classOrObject = entry.getKey(); MutableClassDescriptor descriptor = (MutableClassDescriptor) entry.getValue(); if (classOrObject instanceof JetClass) { descriptorResolver.resolveMutableClassDescriptor( (JetClass) classOrObject, descriptor, trace); } else if (classOrObject instanceof JetObjectDeclaration) { descriptor.setModality(Modality.FINAL); descriptor.setVisibility( resolveVisibilityFromModifiers(classOrObject, getDefaultClassVisibility(descriptor))); descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList()); } descriptor.createTypeConstructor(); ClassKind kind = descriptor.getKind(); if (kind == ClassKind.ENUM_ENTRY || kind == ClassKind.OBJECT || kind == ClassKind.ENUM_CLASS) { MutableClassDescriptorLite classObject = descriptor.getClassObjectDescriptor(); assert classObject != null : "Enum entries and named objects should have class objects: " + classOrObject.getText(); JetType supertype; if (kind == ClassKind.ENUM_CLASS) { supertype = KotlinBuiltIns.getInstance().getAnyType(); } else { // This is a clever hack: each enum entry and object declaration (i.e. singleton) has a // synthetic class object. // We make this class object inherit from the singleton here, thus allowing to use the // singleton's class object where // the instance of the singleton is applicable. Effectively all members of the singleton // would be present in its class // object as fake overrides, so you can access them via standard class object notation: // ObjectName.memberName() supertype = descriptor.getDefaultType(); } classObject.setSupertypes(Collections.singleton(supertype)); classObject.createTypeConstructor(); } } }
// Temporary. Duplicates logic from LazyClassTypeConstructor.isReachable private static boolean isReachable( MutableClassDescriptorLite from, MutableClassDescriptorLite to, Set<ClassDescriptor> visited) { if (!visited.add(from)) return false; for (JetType supertype : from.getSupertypes()) { TypeConstructor supertypeConstructor = supertype.getConstructor(); if (supertypeConstructor.getDeclarationDescriptor() == to) { return true; } ClassifierDescriptor superclass = supertypeConstructor.getDeclarationDescriptor(); if (superclass instanceof MutableClassDescriptorLite && isReachable((MutableClassDescriptorLite) superclass, to, visited)) { return true; } } return false; }