private static IEnumerable FindLoops()

in src/Microsoft.VisualStudio.Composition/CompositionConfiguration.cs [322:384]


        private static IEnumerable<ComposedPartDiagnostic> FindLoops(IEnumerable<ComposedPart> parts)
        {
            Requires.NotNull(parts, nameof(parts));

            var partByPartDefinition = parts.ToDictionary(p => p.Definition);
            var partByPartType = parts.ToDictionary(p => p.Definition.TypeRef);
            var partsAndDirectImports = new Dictionary<ComposedPart, IReadOnlyList<KeyValuePair<ImportDefinitionBinding, ComposedPart>>>();

            foreach (var part in parts)
            {
                var directlyImportedParts = (from importAndExports in part.SatisfyingExports
                                             from export in importAndExports.Value
                                             let exportingPart = partByPartDefinition[export.PartDefinition]
                                             select new KeyValuePair<ImportDefinitionBinding, ComposedPart>(importAndExports.Key, exportingPart)).ToList();
                partsAndDirectImports.Add(part, directlyImportedParts);
            }

            Func<Func<KeyValuePair<ImportDefinitionBinding, ComposedPart>, bool>, Func<ComposedPart, IEnumerable<ComposedPart>>> getDirectLinksWithFilter =
                filter => (part => partsAndDirectImports[part].Where(filter).Select(ip => ip.Value));
            var visited = new HashSet<ComposedPart>();

            // Find any loops of exclusively non-shared parts.
            var nonSharedPartsInLoops = new HashSet<ComposedPart>();
            foreach (var part in partsAndDirectImports.Keys)
            {
                if (nonSharedPartsInLoops.Contains(part))
                {
                    // Don't check and report parts already detected to be involved in a loop.
                    continue;
                }

                visited.Clear();
                var path = PathExistsBetween(part, part, getDirectLinksWithFilter(ip => !ip.Key.IsExportFactory && (!ip.Value.Definition.IsShared || PartCreationPolicyConstraint.IsNonSharedInstanceRequired(ip.Key.ImportDefinition))), visited);
                if (!path.IsEmpty)
                {
                    path = path.Push(part);
                    nonSharedPartsInLoops.UnionWith(path);
                    yield return new ComposedPartDiagnostic(path, Strings.LoopBetweenNonSharedParts);
                }
            }

            // Find loops even with shared parts where an importing constructor is involved.
            Func<KeyValuePair<ImportDefinitionBinding, ComposedPart>, bool> importingConstructorFilter = ip => !ip.Key.IsExportFactory && !ip.Key.IsLazy;
            foreach (var partAndImports in partsAndDirectImports)
            {
                var importingPart = partAndImports.Key;
                foreach (var import in partAndImports.Value)
                {
                    var importDefinitionBinding = import.Key;
                    var satisfyingPart = import.Value;
                    if (importDefinitionBinding.ImportingParameterRef != null && importingConstructorFilter(import))
                    {
                        visited.Clear();
                        var path = PathExistsBetween(satisfyingPart, importingPart, getDirectLinksWithFilter(importingConstructorFilter), visited);
                        if (!path.IsEmpty)
                        {
                            path = path.Push(satisfyingPart).Push(partByPartType[importDefinitionBinding.ComposablePartTypeRef]);
                            yield return new ComposedPartDiagnostic(path, Strings.LoopInvolvingImportingCtorArgumentAndAllNonLazyImports);
                        }
                    }
                }
            }
        }