private bool CheckForItselfOrAnyChildIsConditional(
            ref HashSet <IBindingContainer> used,
            BindingExtenderBox bindingContainerBox,
            IBindingContainer bindingContainer
            )
        {
            if (bindingContainer is null)
            {
                throw new ArgumentNullException(nameof(bindingContainer));
            }

            if (used is null)
            {
                throw new ArgumentNullException(nameof(used));
            }

            if (bindingContainerBox is null)
            {
                throw new ArgumentNullException(nameof(bindingContainerBox));
            }

            if (used.Contains(bindingContainer))
            {
                //found cycle, skip this subtree as circular
                return(false);
            }
            used.Add(bindingContainer);

            if (bindingContainer.IsConditional)
            {
                return(true);
            }

            if (bindingContainerBox.TryGetChildren(bindingContainer, true, out var pairs))
            {
                foreach (var pair in pairs)
                {
                    var used2 = new HashSet <IBindingContainer>(used);
                    if (CheckForItselfOrAnyChildIsConditional(
                            ref used2,
                            bindingContainerBox,
                            pair.BindingExtender.BindingContainer
                            ))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public ClusterBindings(
            ITypeSymbol clusterType,
            IReadOnlyList <IBindingContainer> bindingContainers
            )
        {
            if (clusterType is null)
            {
                throw new ArgumentNullException(nameof(clusterType));
            }

            if (bindingContainers is null)
            {
                throw new ArgumentNullException(nameof(bindingContainers));
            }

            ClusterType       = clusterType;
            BindingContainers = bindingContainers;

            BindingExtenders = bindingContainers.ConvertAll(c => new BindingContainerExtender(c));

            _bindsFrom = new HashSet <ITypeSymbol>(
                new TypeSymbolEqualityComparer()
                );
            NotBindParents = new Dictionary <ITypeSymbol, List <BindingContainerExtender> >(
                new TypeSymbolEqualityComparer()
                );

            foreach (var extender in BindingExtenders)
            {
                foreach (var bindFromType in extender.BindingContainer.BindFromTypes)
                {
                    _bindsFrom.Add(bindFromType);
                }

                foreach (var cat in extender.BindingContainer.NotBindConstructorArgumentTypes)
                {
                    if (!NotBindParents.ContainsKey(cat))
                    {
                        NotBindParents[cat] = new List <BindingContainerExtender>();
                    }

                    NotBindParents[cat].Add(extender);
                }
            }

            Box = new BindingExtenderBox(
                BindingExtenders
                );
        }
        private bool CheckForHasUnresolvedChildren(
            ref HashSet <IBindingContainer> used,
            BindingExtenderBox box,
            IBindingContainer bindingContainer
            )
        {
            if (bindingContainer is null)
            {
                throw new ArgumentNullException(nameof(bindingContainer));
            }

            if (used is null)
            {
                throw new ArgumentNullException(nameof(used));
            }

            if (box is null)
            {
                throw new ArgumentNullException(nameof(box));
            }

            if (used.Contains(bindingContainer))
            {
                //found cycle, skip this subtree as circular
                return(false);
            }
            used.Add(bindingContainer);

            if (!box.TryGetChildren(bindingContainer, false, out var pairs))
            {
                //at least one child does not found
                return(true);
            }

            foreach (var pair in pairs)
            {
                var used2 = new HashSet <IBindingContainer>(used);
                if (CheckForHasUnresolvedChildren(
                        ref used2,
                        box,
                        pair.BindingExtender.BindingContainer
                        ))
                {
                    return(true);
                }
            }

            return(false);
        }