@@ -33,16 +33,12 @@ public AssemblyCache(IEnumerable<string> dirs, IProgressMonitor progress)
3333 /// (Indexing is performed at a later stage by IndexReferences()).
3434 /// </summary>
3535 /// <param name="dir">The directory to index.</param>
36- /// <returns>The number of DLLs within this directory.</returns>
37- int AddReferenceDirectory ( string dir )
36+ void AddReferenceDirectory ( string dir )
3837 {
39- int count = 0 ;
4038 foreach ( var dll in new DirectoryInfo ( dir ) . EnumerateFiles ( "*.dll" , SearchOption . AllDirectories ) )
4139 {
42- dlls . Add ( dll . FullName ) ;
43- ++ count ;
40+ pendingDllsToIndex . Enqueue ( dll . FullName ) ;
4441 }
45- return count ;
4642 }
4743
4844 /// <summary>
@@ -52,38 +48,42 @@ int AddReferenceDirectory(string dir)
5248 void IndexReferences ( )
5349 {
5450 // Read all of the files
55- foreach ( var filename in dlls )
51+ foreach ( var filename in pendingDllsToIndex )
5652 {
57- var info = AssemblyInfo . ReadFromFile ( filename ) ;
58-
59- if ( info . Valid )
60- {
61- assemblyInfo [ filename ] = info ;
62- }
63- else
64- {
65- failedDlls . Add ( filename ) ;
66- }
53+ IndexReference ( filename ) ;
6754 }
6855
6956 // Index "assemblyInfo" by version string
7057 // The OrderBy is used to ensure that we by default select the highest version number.
71- foreach ( var info in assemblyInfo . Values . OrderBy ( info => info . Id ) )
58+ foreach ( var info in assemblyInfoByFileName . Values . OrderBy ( info => info . Id ) )
7259 {
7360 foreach ( var index in info . IndexStrings )
74- references [ index ] = info ;
61+ assemblyInfoById [ index ] = info ;
62+ }
63+ }
64+
65+ private void IndexReference ( string filename )
66+ {
67+ try
68+ {
69+ var info = AssemblyInfo . ReadFromFile ( filename ) ;
70+ assemblyInfoByFileName [ filename ] = info ;
71+ }
72+ catch ( AssemblyLoadException )
73+ {
74+ failedAssemblyInfoFileNames . Add ( filename ) ;
7575 }
7676 }
7777
7878 /// <summary>
7979 /// The number of DLLs which are assemblies.
8080 /// </summary>
81- public int AssemblyCount => assemblyInfo . Count ;
81+ public int AssemblyCount => assemblyInfoByFileName . Count ;
8282
8383 /// <summary>
8484 /// The number of DLLs which weren't assemblies. (E.g. C++).
8585 /// </summary>
86- public int NonAssemblyCount => failedDlls . Count ;
86+ public int NonAssemblyCount => failedAssemblyInfoFileNames . Count ;
8787
8888 /// <summary>
8989 /// Given an assembly id, determine its full info.
@@ -93,70 +93,67 @@ void IndexReferences()
9393 public AssemblyInfo ResolveReference ( string id )
9494 {
9595 // Fast path if we've already seen this before.
96- if ( failedReferences . Contains ( id ) )
97- return AssemblyInfo . Invalid ;
96+ if ( failedAssemblyInfoIds . Contains ( id ) )
97+ throw new AssemblyLoadException ( ) ;
9898
99- var query = AssemblyInfo . MakeFromId ( id ) ;
100- id = query . Id ; // Sanitise the id.
99+ string assemblyName ;
100+ ( id , assemblyName ) = AssemblyInfo . ComputeSanitizedAssemblyInfo ( id ) ;
101101
102102 // Look up the id in our references map.
103- AssemblyInfo result ;
104- if ( references . TryGetValue ( id , out result ) )
103+ if ( assemblyInfoById . TryGetValue ( id , out AssemblyInfo ? result ) )
105104 {
106105 // The string is in the references map.
107106 return result ;
108107 }
109- else
110- {
111- // Attempt to load the reference from the GAC.
112- try
113- {
114- var loadedAssembly = System . Reflection . Assembly . ReflectionOnlyLoad ( id ) ;
115-
116- if ( loadedAssembly != null )
117- {
118- // The assembly was somewhere we haven't indexed before.
119- // Add this assembly to our index so that subsequent lookups are faster.
120-
121- result = AssemblyInfo . MakeFromAssembly ( loadedAssembly ) ;
122- references [ id ] = result ;
123- assemblyInfo [ loadedAssembly . Location ] = result ;
124- return result ;
125- }
126- }
127- catch ( FileNotFoundException )
128- {
129- // A suitable assembly could not be found
130- }
131- catch ( FileLoadException )
132- {
133- // The assembly cannot be loaded for some reason
134- // e.g. The name is malformed.
135- }
136- catch ( PlatformNotSupportedException )
137- {
138- // .NET Core does not have a GAC.
139- }
140108
141- // Fallback position - locate the assembly by its lower-case name only.
142- var asmName = query . Name . ToLowerInvariant ( ) ;
109+ // Attempt to load the reference from the GAC.
110+ try
111+ {
112+ var loadedAssembly = System . Reflection . Assembly . ReflectionOnlyLoad ( id ) ;
143113
144- if ( references . TryGetValue ( asmName , out result ) )
114+ if ( loadedAssembly != null )
145115 {
146- references [ asmName ] = result ; // Speed up the next time the same string is resolved
116+ // The assembly was somewhere we haven't indexed before.
117+ // Add this assembly to our index so that subsequent lookups are faster.
118+
119+ result = AssemblyInfo . MakeFromAssembly ( loadedAssembly ) ;
120+ assemblyInfoById [ id ] = result ;
121+ assemblyInfoByFileName [ loadedAssembly . Location ] = result ;
147122 return result ;
148123 }
124+ }
125+ catch ( FileNotFoundException )
126+ {
127+ // A suitable assembly could not be found
128+ }
129+ catch ( FileLoadException )
130+ {
131+ // The assembly cannot be loaded for some reason
132+ // e.g. The name is malformed.
133+ }
134+ catch ( PlatformNotSupportedException )
135+ {
136+ // .NET Core does not have a GAC.
137+ }
149138
150- failedReferences . Add ( id ) ; // Fail early next time
139+ // Fallback position - locate the assembly by its lower-case name only.
140+ var asmName = assemblyName . ToLowerInvariant ( ) ;
151141
152- return AssemblyInfo . Invalid ;
142+ if ( assemblyInfoById . TryGetValue ( asmName , out result ) )
143+ {
144+ assemblyInfoById [ asmName ] = result ; // Speed up the next time the same string is resolved
145+ return result ;
153146 }
147+
148+ failedAssemblyInfoIds . Add ( id ) ; // Fail early next time
149+
150+ throw new AssemblyLoadException ( ) ;
154151 }
155152
156153 /// <summary>
157154 /// All the assemblies we have indexed.
158155 /// </summary>
159- public IEnumerable < AssemblyInfo > AllAssemblies => assemblyInfo . Select ( a => a . Value ) ;
156+ public IEnumerable < AssemblyInfo > AllAssemblies => assemblyInfoByFileName . Select ( a => a . Value ) ;
160157
161158 /// <summary>
162159 /// Retrieve the assembly info of a pre-cached assembly.
@@ -165,32 +162,32 @@ public AssemblyInfo ResolveReference(string id)
165162 /// <returns>The assembly info.</returns>
166163 public AssemblyInfo GetAssemblyInfo ( string filepath )
167164 {
168- if ( assemblyInfo . TryGetValue ( filepath , out var info ) )
165+ if ( assemblyInfoByFileName . TryGetValue ( filepath , out var info ) )
169166 {
170167 return info ;
171168 }
172- else
169+
170+ IndexReference ( filepath ) ;
171+
172+ if ( assemblyInfoByFileName . TryGetValue ( filepath , out info ) )
173173 {
174- info = AssemblyInfo . ReadFromFile ( filepath ) ;
175- assemblyInfo . Add ( filepath , info ) ;
176174 return info ;
177175 }
176+
177+ throw new AssemblyLoadException ( ) ;
178178 }
179179
180- // List of pending DLLs to index.
181- readonly List < string > dlls = new List < string > ( ) ;
180+ readonly Queue < string > pendingDllsToIndex = new Queue < string > ( ) ;
182181
183- // Map from filename to assembly info.
184- readonly Dictionary < string , AssemblyInfo > assemblyInfo = new Dictionary < string , AssemblyInfo > ( ) ;
182+ readonly Dictionary < string , AssemblyInfo > assemblyInfoByFileName = new Dictionary < string , AssemblyInfo > ( ) ;
185183
186184 // List of DLLs which are not assemblies.
187185 // We probably don't need to keep this
188- readonly List < string > failedDlls = new List < string > ( ) ;
186+ readonly List < string > failedAssemblyInfoFileNames = new List < string > ( ) ;
189187
190188 // Map from assembly id (in various formats) to the full info.
191- readonly Dictionary < string , AssemblyInfo > references = new Dictionary < string , AssemblyInfo > ( ) ;
189+ readonly Dictionary < string , AssemblyInfo > assemblyInfoById = new Dictionary < string , AssemblyInfo > ( ) ;
192190
193- // Set of failed assembly ids.
194- readonly HashSet < string > failedReferences = new HashSet < string > ( ) ;
191+ readonly HashSet < string > failedAssemblyInfoIds = new HashSet < string > ( ) ;
195192 }
196193}
0 commit comments