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 > > ( NonAliasCommands , Aliases ) ) ;
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,94 @@ 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+ if ( moduleVersion . Value . Aliases == null )
111137 {
112- foreach ( KeyValuePair < string , CommandData > alias in module . Aliases )
113- {
114- if ( ! commandTable . ContainsKey ( alias . Key ) )
115- {
116- commandTable . Add ( alias . Key , new List < CommandData > ( ) ) ;
117- }
138+ continue ;
139+ }
118140
119- ( ( List < CommandData > ) commandTable [ alias . Key ] ) . Add ( alias . Value ) ;
141+ foreach ( KeyValuePair < string , string > alias in moduleVersion . Value . Aliases )
142+ {
143+ if ( commands . TryGetValue ( alias . Value , out IReadOnlyList < CommandData > aliasedCommands ) )
144+ {
145+ aliasTable [ alias . Key ] = aliasedCommands ;
120146 }
121147 }
122148 }
123149 }
150+ return aliasTable ;
151+ }
124152
125- return commandTable ;
153+ private class DualLookupTable < K , V > : IReadOnlyDictionary < K , V >
154+ {
155+ private readonly IReadOnlyDictionary < K , V > _firstTable ;
156+
157+ private readonly IReadOnlyDictionary < K , V > _secondTable ;
158+
159+ public DualLookupTable ( IReadOnlyDictionary < K , V > firstTable , IReadOnlyDictionary < K , V > secondTable )
160+ {
161+ _firstTable = firstTable ;
162+ _secondTable = secondTable ;
163+ }
164+
165+ public V this [ K key ]
166+ {
167+ get
168+ {
169+ if ( _firstTable . TryGetValue ( key , out V firstValue ) )
170+ {
171+ return firstValue ;
172+ }
173+
174+ if ( _secondTable . TryGetValue ( key , out V secondValue ) )
175+ {
176+ return secondValue ;
177+ }
178+
179+ throw new KeyNotFoundException ( ) ;
180+ }
181+ }
182+
183+ public IEnumerable < K > Keys => _firstTable . Keys . Concat ( _secondTable . Keys ) ;
184+
185+ public IEnumerable < V > Values => _firstTable . Values . Concat ( _secondTable . Values ) ;
186+
187+ public int Count => _firstTable . Count + _secondTable . Count ;
188+
189+ public bool ContainsKey ( K key )
190+ {
191+ return _firstTable . ContainsKey ( key ) || _secondTable . ContainsKey ( key ) ;
192+ }
193+
194+ public IEnumerator < KeyValuePair < K , V > > GetEnumerator ( )
195+ {
196+ return _firstTable . Concat ( _secondTable ) . GetEnumerator ( ) ;
197+ }
198+
199+ public bool TryGetValue ( K key , out V value )
200+ {
201+ return _firstTable . TryGetValue ( key , out value )
202+ || _secondTable . TryGetValue ( key , out value ) ;
203+ }
204+
205+ IEnumerator IEnumerable . GetEnumerator ( )
206+ {
207+ return GetEnumerator ( ) ;
208+ }
126209 }
127210 }
128211}
0 commit comments