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(); } }
// 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; }