|
15 | 15 | using Microsoft.CodeAnalysis.PooledObjects; |
16 | 16 | using Microsoft.CodeAnalysis.Collections; |
17 | 17 | using Microsoft.CodeAnalysis.Shared.Collections; |
| 18 | +using Roslyn.Utilities; |
18 | 19 |
|
19 | 20 | #if DEBUG |
20 | 21 | using System.Linq; |
@@ -907,107 +908,87 @@ internal static void AddToMultiValueDictionaryBuilder<K, T>(Dictionary<K, object |
907 | 908 |
|
908 | 909 | internal static void CreateNameToMembersMap |
909 | 910 | <TNamespaceOrTypeSymbol, TNamedTypeSymbol, TNamespaceSymbol> |
910 | | - (Dictionary<string, object> dictionary, Dictionary<String, ImmutableArray<TNamespaceOrTypeSymbol>> result) |
| 911 | + (Dictionary<string, object> dictionary, Dictionary<string, ImmutableArray<TNamespaceOrTypeSymbol>> result) |
911 | 912 | where TNamespaceOrTypeSymbol : class |
912 | 913 | where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol |
913 | 914 | where TNamespaceSymbol : class, TNamespaceOrTypeSymbol |
914 | 915 | { |
915 | | - foreach (var kvp in dictionary) |
916 | | - { |
917 | | - object value = kvp.Value; |
918 | | - ImmutableArray<TNamespaceOrTypeSymbol> members; |
| 916 | + foreach (var (name, value) in dictionary) |
| 917 | + result.Add(name, createMembers(value)); |
| 918 | + |
| 919 | + return; |
919 | 920 |
|
920 | | - var builder = value as ArrayBuilder<TNamespaceOrTypeSymbol>; |
921 | | - if (builder != null) |
| 921 | + static ImmutableArray<TNamespaceOrTypeSymbol> createMembers(object value) |
| 922 | + { |
| 923 | + if (value is ArrayBuilder<TNamespaceOrTypeSymbol> builder) |
922 | 924 | { |
923 | 925 | Debug.Assert(builder.Count > 1); |
924 | | - bool hasNamespaces = false; |
925 | | - for (int i = 0; i < builder.Count; i++) |
| 926 | + foreach (var item in builder) |
926 | 927 | { |
927 | | - if (builder[i] is TNamespaceSymbol) |
928 | | - { |
929 | | - hasNamespaces = true; |
930 | | - break; |
931 | | - } |
| 928 | + if (item is TNamespaceSymbol) |
| 929 | + return builder.ToImmutableAndFree(); |
932 | 930 | } |
933 | 931 |
|
934 | | - members = hasNamespaces |
935 | | - ? builder.ToImmutable() |
936 | | - : ImmutableArray<TNamespaceOrTypeSymbol>.CastUp(builder.ToDowncastedImmutable<TNamedTypeSymbol>()); |
937 | | - |
938 | | - builder.Free(); |
| 932 | + return ImmutableArray<TNamespaceOrTypeSymbol>.CastUp(builder.ToDowncastedImmutableAndFree<TNamedTypeSymbol>()); |
939 | 933 | } |
940 | 934 | else |
941 | 935 | { |
942 | 936 | TNamespaceOrTypeSymbol symbol = (TNamespaceOrTypeSymbol)value; |
943 | | - members = symbol is TNamespaceSymbol |
944 | | - ? ImmutableArray.Create<TNamespaceOrTypeSymbol>(symbol) |
945 | | - : ImmutableArray<TNamespaceOrTypeSymbol>.CastUp(ImmutableArray.Create<TNamedTypeSymbol>((TNamedTypeSymbol)symbol)); |
| 937 | + return symbol is TNamespaceSymbol |
| 938 | + ? ImmutableArray.Create(symbol) |
| 939 | + : ImmutableArray<TNamespaceOrTypeSymbol>.CastUp(ImmutableArray.Create((TNamedTypeSymbol)symbol)); |
946 | 940 | } |
947 | | - |
948 | | - result.Add(kvp.Key, members); |
949 | 941 | } |
950 | 942 | } |
951 | 943 |
|
952 | | - internal static Dictionary<string, ImmutableArray<TNamedTypeSymbol>> GetTypesFromMemberMap |
953 | | - <TNamespaceOrTypeSymbol, TNamedTypeSymbol |
954 | | -#if DEBUG |
955 | | - , TNamespaceSymbol |
956 | | -#endif |
957 | | - > |
| 944 | + internal static Dictionary<string, ImmutableArray<TNamedTypeSymbol>> GetTypesFromMemberMap<TNamespaceOrTypeSymbol, TNamedTypeSymbol> |
958 | 945 | (Dictionary<string, ImmutableArray<TNamespaceOrTypeSymbol>> map, IEqualityComparer<string> comparer) |
959 | 946 | where TNamespaceOrTypeSymbol : class |
960 | 947 | where TNamedTypeSymbol : class, TNamespaceOrTypeSymbol |
961 | | -#if DEBUG |
962 | | - where TNamespaceSymbol : class, TNamespaceOrTypeSymbol |
963 | | -#endif |
964 | 948 | { |
965 | 949 | var dictionary = new Dictionary<string, ImmutableArray<TNamedTypeSymbol>>(comparer); |
966 | 950 |
|
967 | | - foreach (var kvp in map) |
| 951 | + foreach (var (name, members) in map) |
968 | 952 | { |
969 | | - ImmutableArray<TNamespaceOrTypeSymbol> members = kvp.Value; |
| 953 | + var namedTypes = getOrCreateNamedTypes(members); |
| 954 | + if (namedTypes.Length > 0) |
| 955 | + dictionary.Add(name, namedTypes); |
| 956 | + } |
970 | 957 |
|
971 | | - bool hasType = false; |
972 | | - bool hasNamespace = false; |
| 958 | + return dictionary; |
973 | 959 |
|
974 | | - foreach (var symbol in members) |
975 | | - { |
976 | | - if (symbol is TNamedTypeSymbol) |
977 | | - { |
978 | | - hasType = true; |
979 | | - if (hasNamespace) |
980 | | - { |
981 | | - break; |
982 | | - } |
983 | | - } |
984 | | - else |
985 | | - { |
986 | | -#if DEBUG |
987 | | - Debug.Assert(symbol is TNamespaceSymbol); |
988 | | -#endif |
989 | | - hasNamespace = true; |
990 | | - if (hasType) |
991 | | - { |
992 | | - break; |
993 | | - } |
994 | | - } |
995 | | - } |
| 960 | + static ImmutableArray<TNamedTypeSymbol> getOrCreateNamedTypes(ImmutableArray<TNamespaceOrTypeSymbol> members) |
| 961 | + { |
| 962 | + Debug.Assert(members.Length > 0); |
| 963 | + |
| 964 | + // See if creator 'map' put a downcasted ImmutableArray<TNamedTypeSymbol> in it. If so, we can just directly |
| 965 | + // downcast to that and trivially reuse it. If not, that means the array must have contained at least one |
| 966 | + // TNamespaceSymbol and we'll need to filter that out. |
| 967 | + var membersAsNamedTypes = members.As<TNamedTypeSymbol>(); |
| 968 | + |
| 969 | + if (!membersAsNamedTypes.IsDefault) |
| 970 | + return membersAsNamedTypes; |
| 971 | + |
| 972 | + // Preallocate the right amount so we can avoid garbage reallocs. |
| 973 | + var count = members.Count(static s => s is TNamedTypeSymbol); |
996 | 974 |
|
997 | | - if (hasType) |
| 975 | + // Must have less items than in the original array. Otherwise, the .As<TNamedTypeSymbol>() cast would |
| 976 | + // have succeeded. |
| 977 | + Debug.Assert(count < members.Length); |
| 978 | + |
| 979 | + if (count == 0) |
| 980 | + return ImmutableArray<TNamedTypeSymbol>.Empty; |
| 981 | + |
| 982 | + var builder = ArrayBuilder<TNamedTypeSymbol>.GetInstance(count); |
| 983 | + foreach (var member in members) |
998 | 984 | { |
999 | | - if (hasNamespace) |
1000 | | - { |
1001 | | - dictionary.Add(kvp.Key, members.OfType<TNamedTypeSymbol>().AsImmutable()); |
1002 | | - } |
1003 | | - else |
1004 | | - { |
1005 | | - dictionary.Add(kvp.Key, members.As<TNamedTypeSymbol>()); |
1006 | | - } |
| 985 | + if (member is TNamedTypeSymbol namedType) |
| 986 | + builder.Add(namedType); |
1007 | 987 | } |
1008 | | - } |
1009 | 988 |
|
1010 | | - return dictionary; |
| 989 | + Debug.Assert(builder.Count == count); |
| 990 | + return builder.ToImmutableAndFree(); |
| 991 | + } |
1011 | 992 | } |
1012 | 993 |
|
1013 | 994 | internal static bool SequenceEqual<TElement, TArg>(this ImmutableArray<TElement> array1, ImmutableArray<TElement> array2, TArg arg, Func<TElement, TElement, TArg, bool> predicate) |
|
0 commit comments