예제 #1
0
        /// <summary>
        /// Returns a set containing all the types in <paramref name="ns" />
        /// after merging using the specified <see cref="UnionComparer" />. For
        /// large sets, this operation may require significant time and memory.
        /// The returned set is always a copy of the original.
        /// </summary>
        /// <param name="ns">The namespaces to contain in the set.</param>
        /// <param name="comparer">The comparer to use for the set.</param>
        internal static IAnalysisSet CreateUnion(IEnumerable <AnalysisProxy> ns, UnionComparer comparer)
        {
            bool dummy;

            // TODO: Replace Trim() call with more intelligent enumeration.
            return(new AnalysisSetDetails.AnalysisHashSet(ns.UnionIter(comparer, out dummy), comparer).Trim());
        }
예제 #2
0
        /// <summary>
        /// Returns <paramref name="set"/> with the specified comparer. If the
        /// comparer does not need to be changed, <paramref name="set"/> is
        /// returned unmodified.
        /// </summary>
        /// <param name="set">The set to convert to a union.</param>
        /// <param name="comparer">The comparer to use for the set.</param>
        /// <param name="wasChanged">Returns True if the contents of the
        /// returned set are different to <paramref name="set"/>.</param>
        internal static IAnalysisSet AsUnion(this IAnalysisSet set, UnionComparer comparer, out bool wasChanged)
        {
            if ((set is AnalysisSetDetails.AnalysisSetOneUnion ||
                 set is AnalysisSetDetails.AnalysisSetTwoUnion ||
                 set is AnalysisSetDetails.AnalysisSetEmptyUnion ||
                 set is AnalysisSetDetails.AnalysisHashSet) &&
                set.Comparer == comparer)
            {
                wasChanged = false;
                return(set);
            }

            wasChanged = true;

            var ns = set as AnalysisProxy;

            if (ns != null)
            {
                return(CreateUnion(ns, comparer));
            }
            var ns2 = set as AnalysisSetDetails.AnalysisSetTwoObject;

            if (ns2 != null)
            {
                if (ns2.Value1 == null)
                {
                    if (ns2.Value2 == null)
                    {
                        wasChanged = false;
                        return(AnalysisSetEmptyUnion.Instances[comparer.Strength]);
                    }
                    wasChanged = false;
                    return(new AnalysisSetOneUnion(ns2.Value2, comparer));
                }
                else if (ns2.Value2 == null)
                {
                    wasChanged = false;
                    return(new AnalysisSetOneUnion(ns2.Value1, comparer));
                }
                if (comparer.Equals(ns2.Value1, ns2.Value2))
                {
                    bool dummy;
                    return(new AnalysisSetDetails.AnalysisSetOneUnion(comparer.MergeTypes(ns2.Value1, ns2.Value2, out dummy), comparer));
                }
                else
                {
                    return(new AnalysisSetDetails.AnalysisSetTwoUnion(ns2.Value1, ns2.Value2, comparer));
                }
            }
            return(new AnalysisSetDetails.AnalysisHashSet(set, comparer));
        }
예제 #3
0
        internal static IEnumerable <AnalysisProxy> UnionIter(this IEnumerable <AnalysisProxy> items, UnionComparer comparer, out bool wasChanged)
        {
#endif
            wasChanged = false;

            var asSet = items as IAnalysisSet;
            if (asSet != null && asSet.Comparer == comparer)
            {
                return(items);
            }

            var newItems  = new List <AnalysisProxy>();
            var anyMerged = true;

            while (anyMerged)
            {
                anyMerged = false;
                var matches = new Dictionary <AnalysisProxy, List <AnalysisProxy> >(comparer);

                foreach (var ns in items)
                {
                    List <AnalysisProxy> list;
                    if (matches.TryGetValue(ns, out list))
                    {
                        if (list == null)
                        {
                            matches[ns] = list = new List <AnalysisProxy>();
                        }
                        list.Add(ns);
                    }
                    else
                    {
                        matches[ns] = null;
                    }
                }

                newItems.Clear();

                foreach (var keyValue in matches)
                {
                    var item = keyValue.Key;
                    if (keyValue.Value != null)
                    {
                        foreach (var other in keyValue.Value)
                        {
                            bool merged;
#if FULL_VALIDATION
                            Validation.Assert(comparer.Equals(item, other));
#endif
                            item = comparer.MergeTypes(item, other, out merged);
                            if (merged)
                            {
                                anyMerged  = true;
                                wasChanged = true;
                            }
                        }
                    }
                    newItems.Add(item);
                }
                items = newItems;
            }

            return(items);
        }
예제 #4
0
 private static IEnumerable <AnalysisWrapper> UnionIterInternal(IEnumerable <AnalysisWrapper> items, UnionComparer comparer, out bool wasChanged)
 {
예제 #5
0
        /// <summary>
        /// Merges the provided sequence using the specified <see
        /// cref="UnionComparer"/>.
        /// </summary>
#if FULL_VALIDATION
        internal static IEnumerable <AnalysisWrapper> UnionIter(this IEnumerable <AnalysisWrapper> items, UnionComparer comparer, out bool wasChanged)
        {
            var originalItems = items.ToList();
            var newItems      = UnionIterInternal(items, comparer, out wasChanged).ToList();

            Validation.Assert(newItems.Count <= originalItems.Count);
            if (wasChanged)
            {
                Validation.Assert(newItems.Count < originalItems.Count);
                foreach (var x in newItems)
                {
                    foreach (var y in newItems)
                    {
                        if (object.ReferenceEquals(x, y))
                        {
                            continue;
                        }

                        Validation.Assert(!comparer.Equals(x, y));
                        Validation.Assert(!comparer.Equals(y, x));
                    }
                }
            }

            return(newItems);
        }
예제 #6
0
 /// <summary>
 /// Returns a set containing only <paramref name="ns" /> that uses the
 /// specified <see cref="UnionComparer" />.
 ///
 /// This is different to casting from <see cref="AnalysisProxy" /> to <see
 /// cref="IAnalysisSet" />, because the implementation in <see
 /// cref="AnalysisProxy" /> always uses <see cref="ObjectComparer" />.
 /// </summary>
 /// <param name="ns">The namespace to contain in the set.</param>
 /// <param name="comparer">The comparer to use for the set.</param>
 internal static IAnalysisSet CreateUnion(AnalysisProxy ns, UnionComparer comparer)
 {
     return(new AnalysisSetDetails.AnalysisSetOneUnion(ns, comparer));
 }
예제 #7
0
 /// <summary>
 /// Returns an empty set that uses the specified <see
 /// cref="UnionComparer" />.
 /// </summary>
 /// <param name="comparer">The comparer to use for the set.</param>
 internal static IAnalysisSet CreateUnion(UnionComparer comparer)
 {
     return(AnalysisSetDetails.AnalysisSetEmptyUnion.Instances[comparer.Strength]);
 }