22// Licensed under the MIT License.
33
44using System ;
5+ using System . Collections ;
56using System . Collections . Generic ;
7+ using System . Linq ;
68using Data = Microsoft . PowerShell . CrossCompatibility . Data ;
79
810namespace Microsoft . PowerShell . CrossCompatibility . Query
@@ -14,6 +16,10 @@ public class RuntimeData
1416 {
1517 private readonly Lazy < IReadOnlyDictionary < string , IReadOnlyDictionary < Version , ModuleData > > > _modules ;
1618
19+ private readonly Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > _nonAliasCommands ;
20+
21+ private readonly Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > _aliases ;
22+
1723 private readonly Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > _commands ;
1824
1925 private readonly Lazy < NativeCommandLookupTable > _nativeCommands ;
@@ -28,7 +34,9 @@ public RuntimeData(Data.RuntimeData runtimeData)
2834 Common = new CommonPowerShellData ( runtimeData . Common ) ;
2935
3036 _modules = new Lazy < IReadOnlyDictionary < string , IReadOnlyDictionary < Version , ModuleData > > > ( ( ) => CreateModuleTable ( runtimeData . Modules ) ) ;
31- _commands = new Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > ( ( ) => CreateCommandLookupTable ( Modules ) ) ;
37+ _nonAliasCommands = new Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > ( ( ) => CreateNonAliasCommandLookupTable ( Modules ) ) ;
38+ _aliases = new Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > ( ( ) => CreateAliasLookupTable ( runtimeData . Modules , NonAliasCommands ) ) ;
39+ _commands = new Lazy < IReadOnlyDictionary < string , IReadOnlyList < CommandData > > > ( ( ) => new DualLookupTable < string , IReadOnlyList < CommandData > > ( Aliases , NonAliasCommands ) ) ;
3240 _nativeCommands = new Lazy < NativeCommandLookupTable > ( ( ) => NativeCommandLookupTable . Create ( runtimeData . NativeCommands ) ) ;
3341 }
3442
@@ -58,22 +66,26 @@ public RuntimeData(Data.RuntimeData runtimeData)
5866 /// </summary>
5967 public CommonPowerShellData Common { get ; }
6068
61- private static IReadOnlyDictionary < string , IReadOnlyDictionary < Version , ModuleData > > CreateModuleTable ( IDictionary < string , JsonDictionary < Version , Data . ModuleData > > modules )
69+ internal IReadOnlyDictionary < string , IReadOnlyList < CommandData > > NonAliasCommands => _nonAliasCommands . Value ;
70+
71+ internal IReadOnlyDictionary < string , IReadOnlyList < CommandData > > Aliases => _aliases . Value ;
72+
73+ private IReadOnlyDictionary < string , IReadOnlyDictionary < Version , ModuleData > > CreateModuleTable ( IDictionary < string , JsonDictionary < Version , Data . ModuleData > > modules )
6274 {
6375 var moduleDict = new Dictionary < string , IReadOnlyDictionary < Version , ModuleData > > ( modules . Count , StringComparer . OrdinalIgnoreCase ) ;
6476 foreach ( KeyValuePair < string , JsonDictionary < Version , Data . ModuleData > > moduleVersions in modules )
6577 {
6678 var moduleVersionDict = new Dictionary < Version , ModuleData > ( moduleVersions . Value . Count ) ;
6779 foreach ( KeyValuePair < Version , Data . ModuleData > module in moduleVersions . Value )
6880 {
69- moduleVersionDict [ module . Key ] = new ModuleData ( name : moduleVersions . Key , version : module . Key , moduleData : module . Value ) ;
81+ moduleVersionDict [ module . Key ] = new ModuleData ( name : moduleVersions . Key , version : module . Key , parent : this , moduleData : module . Value ) ;
7082 }
7183 moduleDict [ moduleVersions . Key ] = moduleVersionDict ;
7284 }
7385 return moduleDict ;
7486 }
7587
76- private static IReadOnlyDictionary < string , IReadOnlyList < CommandData > > CreateCommandLookupTable (
88+ private static IReadOnlyDictionary < string , IReadOnlyList < CommandData > > CreateNonAliasCommandLookupTable (
7789 IReadOnlyDictionary < string , IReadOnlyDictionary < Version , ModuleData > > modules )
7890 {
7991 var commandTable = new Dictionary < string , IReadOnlyList < CommandData > > ( StringComparer . OrdinalIgnoreCase ) ;
@@ -106,23 +118,89 @@ private static IReadOnlyDictionary<string, IReadOnlyList<CommandData>> CreateCom
106118 ( ( List < CommandData > ) commandTable [ function . Key ] ) . Add ( function . Value ) ;
107119 }
108120 }
121+ }
122+ }
109123
110- if ( module . Aliases != null )
124+ return commandTable ;
125+ }
126+
127+ private static IReadOnlyDictionary < string , IReadOnlyList < CommandData > > CreateAliasLookupTable (
128+ IReadOnlyDictionary < string , JsonDictionary < Version , Data . ModuleData > > modules ,
129+ IReadOnlyDictionary < string , IReadOnlyList < CommandData > > commands )
130+ {
131+ var aliasTable = new Dictionary < string , IReadOnlyList < CommandData > > ( ) ;
132+ foreach ( KeyValuePair < string , JsonDictionary < Version , Data . ModuleData > > module in modules )
133+ {
134+ foreach ( KeyValuePair < Version , Data . ModuleData > moduleVersion in module . Value )
135+ {
136+ foreach ( KeyValuePair < string , string > alias in moduleVersion . Value . Aliases )
111137 {
112- foreach ( KeyValuePair < string , CommandData > alias in module . Aliases )
138+ if ( commands . TryGetValue ( alias . Value , out IReadOnlyList < CommandData > aliasedCommands ) )
113139 {
114- if ( ! commandTable . ContainsKey ( alias . Key ) )
115- {
116- commandTable . Add ( alias . Key , new List < CommandData > ( ) ) ;
117- }
118-
119- ( ( List < CommandData > ) commandTable [ alias . Key ] ) . Add ( alias . Value ) ;
140+ aliasTable [ alias . Key ] = aliasedCommands ;
120141 }
121142 }
122143 }
123144 }
145+ return aliasTable ;
146+ }
124147
125- return commandTable ;
148+ private class DualLookupTable < K , V > : IReadOnlyDictionary < K , V >
149+ {
150+ private readonly IReadOnlyDictionary < K , V > _firstTable ;
151+
152+ private readonly IReadOnlyDictionary < K , V > _secondTable ;
153+
154+ public DualLookupTable ( IReadOnlyDictionary < K , V > firstTable , IReadOnlyDictionary < K , V > secondTable )
155+ {
156+ _firstTable = firstTable ;
157+ _secondTable = secondTable ;
158+ }
159+
160+ public V this [ K key ]
161+ {
162+ get
163+ {
164+ if ( _firstTable . TryGetValue ( key , out V firstValue ) )
165+ {
166+ return firstValue ;
167+ }
168+
169+ if ( _secondTable . TryGetValue ( key , out V secondValue ) )
170+ {
171+ return secondValue ;
172+ }
173+
174+ throw new KeyNotFoundException ( ) ;
175+ }
176+ }
177+
178+ public IEnumerable < K > Keys => _firstTable . Keys . Concat ( _secondTable . Keys ) ;
179+
180+ public IEnumerable < V > Values => _firstTable . Values . Concat ( _secondTable . Values ) ;
181+
182+ public int Count => _firstTable . Count + _secondTable . Count ;
183+
184+ public bool ContainsKey ( K key )
185+ {
186+ return _firstTable . ContainsKey ( key ) || _secondTable . ContainsKey ( key ) ;
187+ }
188+
189+ public IEnumerator < KeyValuePair < K , V > > GetEnumerator ( )
190+ {
191+ return _firstTable . Concat ( _secondTable ) . GetEnumerator ( ) ;
192+ }
193+
194+ public bool TryGetValue ( K key , out V value )
195+ {
196+ return _firstTable . TryGetValue ( key , out value )
197+ || _secondTable . TryGetValue ( key , out value ) ;
198+ }
199+
200+ IEnumerator IEnumerable . GetEnumerator ( )
201+ {
202+ return GetEnumerator ( ) ;
203+ }
126204 }
127205 }
128206}
0 commit comments