Skip to content

Commit 982a3c4

Browse files
authored
Improve AssemblySymbolLoader logging (#46102)
1 parent ca81e9c commit 982a3c4

File tree

16 files changed

+618
-51
lines changed

16 files changed

+618
-51
lines changed

src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/AssemblySymbolLoader.cs

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ public void AddReferenceSearchPaths(params string[] paths)
9595
/// <inheritdoc />
9696
public IReadOnlyList<IAssemblySymbol?> LoadAssemblies(params string[] paths)
9797
{
98+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssemblies, string.Join(", ", paths)));
99+
98100
// First resolve all assemblies that are passed in and create metadata references out of them.
99101
// Reference assemblies of the passed in assemblies that themselves are passed in, will be skipped to be resolved,
100102
// as they are resolved as part of the loop below.
@@ -119,6 +121,8 @@ public void AddReferenceSearchPaths(params string[] paths)
119121
/// <inheritdoc />
120122
public IReadOnlyList<IAssemblySymbol?> LoadAssembliesFromArchive(string archivePath, IReadOnlyList<string> relativePaths)
121123
{
124+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssembliesFromArchive, string.Join(", ", relativePaths), archivePath));
125+
122126
using FileStream stream = File.OpenRead(archivePath);
123127
using ZipArchive zipFile = new(stream);
124128

@@ -144,7 +148,8 @@ public void AddReferenceSearchPaths(params string[] paths)
144148
string name = Path.GetFileName(relativePaths[i]);
145149
if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference))
146150
{
147-
metadataReference = CreateAndAddReferenceToCompilation(name, memoryStream, fileNames);
151+
string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyFromPackageDisplayString, relativePaths[i], archivePath);
152+
metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, memoryStream, fileNames);
148153
}
149154

150155
metadataReferences[i] = metadataReference;
@@ -170,6 +175,8 @@ public void AddReferenceSearchPaths(params string[] paths)
170175
/// <inheritdoc />
171176
public IAssemblySymbol? LoadAssembly(string path)
172177
{
178+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssembly, path));
179+
173180
MetadataReference metadataReference = CreateOrGetMetadataReferenceFromPath(path);
174181
IAssemblySymbol? assemblySymbol = _cSharpCompilation.GetAssemblyOrModuleSymbol(metadataReference) as IAssemblySymbol;
175182
LogCompilationDiagnostics();
@@ -180,14 +187,17 @@ public void AddReferenceSearchPaths(params string[] paths)
180187
/// <inheritdoc />
181188
public IAssemblySymbol? LoadAssembly(string name, Stream stream)
182189
{
190+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.LoadingAssemblyFromStream, name));
191+
183192
if (stream.Position >= stream.Length)
184193
{
185194
throw new ArgumentException(Resources.StreamPositionGreaterThanLength, nameof(stream));
186195
}
187196

188197
if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference))
189198
{
190-
metadataReference = CreateAndAddReferenceToCompilation(name, stream);
199+
string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyDisplayString, name);
200+
metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, stream);
191201
}
192202

193203
IAssemblySymbol? assemblySymbol = _cSharpCompilation.GetAssemblyOrModuleSymbol(metadataReference) as IAssemblySymbol;
@@ -318,13 +328,14 @@ private MetadataReference CreateOrGetMetadataReferenceFromPath(string path, Immu
318328
if (!_loadedAssemblies.TryGetValue(name, out MetadataReference? metadataReference))
319329
{
320330
using FileStream stream = File.OpenRead(path);
321-
metadataReference = CreateAndAddReferenceToCompilation(name, stream, referenceAssemblyNamesToIgnore);
331+
string rootAssemblyDisplayString = string.Format(Resources.RootAssemblyDisplayString, path);
332+
metadataReference = CreateAndAddReferenceToCompilation(name, rootAssemblyDisplayString, stream, referenceAssemblyNamesToIgnore);
322333
}
323334

324335
return metadataReference;
325336
}
326337

327-
private MetadataReference CreateAndAddReferenceToCompilation(string name, Stream fileStream, ImmutableHashSet<string>? referenceAssemblyNamesToIgnore = null)
338+
private MetadataReference CreateAndAddReferenceToCompilation(string assemblyName, string rootAssemblyDisplayString, Stream fileStream, ImmutableHashSet<string>? referenceAssemblyNamesToIgnore = null, string? referenceeAssemblyName = null)
328339
{
329340
// If we need to resolve references we can't reuse the same stream after creating the metadata
330341
// reference from it as Roslyn closes it. So instead we use PEReader and get the bytes
@@ -333,51 +344,60 @@ private MetadataReference CreateAndAddReferenceToCompilation(string name, Stream
333344

334345
if (!reader.HasMetadata)
335346
{
336-
throw new ArgumentException(string.Format(Resources.ProvidedStreamDoesNotHaveMetadata, name));
347+
throw new ArgumentException(string.Format(Resources.ProvidedStreamDoesNotHaveMetadata, assemblyName));
337348
}
338349

339350
PEMemoryBlock image = reader.GetEntireImage();
340351
MetadataReference metadataReference = MetadataReference.CreateFromImage(image.GetContent());
341-
_loadedAssemblies.Add(name, metadataReference);
352+
_loadedAssemblies.Add(assemblyName, metadataReference);
342353
_cSharpCompilation = _cSharpCompilation.AddReferences([ metadataReference ]);
343354

355+
if (referenceeAssemblyName is null)
356+
{
357+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.AssemblyLoaded, assemblyName));
358+
}
359+
else
360+
{
361+
_log.LogMessage(MessageImportance.Low, string.Format(Resources.AssemblyReferenceLoaded, assemblyName, referenceeAssemblyName));
362+
}
363+
344364
if (_resolveReferences)
345365
{
346-
ResolveReferences(reader, referenceAssemblyNamesToIgnore);
366+
ResolveReferences(reader, assemblyName, rootAssemblyDisplayString, referenceAssemblyNamesToIgnore);
347367
}
348368

349369
return metadataReference;
350370
}
351371

352-
private void ResolveReferences(PEReader peReader, ImmutableHashSet<string>? referenceAssemblyNamesToIgnore = null)
372+
private void ResolveReferences(PEReader peReader, string assemblyName, string rootAssemblyDisplayString, ImmutableHashSet<string>? referenceAssemblyNamesToIgnore = null)
353373
{
354374
MetadataReader reader = peReader.GetMetadataReader();
355-
foreach (AssemblyReferenceHandle handle in reader.AssemblyReferences)
375+
foreach (AssemblyReferenceHandle assemblyReferenceHandle in reader.AssemblyReferences)
356376
{
357-
AssemblyReference reference = reader.GetAssemblyReference(handle);
358-
string nameWithoutExtension = reader.GetString(reference.Name);
377+
AssemblyReference assemblyReference = reader.GetAssemblyReference(assemblyReferenceHandle);
378+
string assemblyReferenceNameWithoutExtension = reader.GetString(assemblyReference.Name);
359379

360380
// Skip assemblies that should never get loaded because they are purely internal
361-
if (s_assembliesToIgnore.Contains(nameWithoutExtension))
381+
if (s_assembliesToIgnore.Contains(assemblyReferenceNameWithoutExtension))
362382
continue;
363383

364-
string name = nameWithoutExtension + ".dll";
384+
string assemblyReferenceName = assemblyReferenceNameWithoutExtension + ".dll";
365385

366386
// Skip reference assemblies that are loaded later.
367-
if (referenceAssemblyNamesToIgnore != null && referenceAssemblyNamesToIgnore.Contains(name))
387+
if (referenceAssemblyNamesToIgnore != null && referenceAssemblyNamesToIgnore.Contains(assemblyReferenceName))
368388
continue;
369389

370390
// If the assembly reference is already loaded, don't do anything.
371-
if (_loadedAssemblies.ContainsKey(name))
391+
if (_loadedAssemblies.ContainsKey(assemblyReferenceName))
372392
continue;
373393

374394
// First we try to see if a reference path for this specific assembly was passed in directly, and if so
375395
// we use that.
376-
if (_referencePathFiles.TryGetValue(name, out string? fullReferencePath))
396+
if (_referencePathFiles.TryGetValue(assemblyReferenceName, out string? fullReferencePath))
377397
{
378398
// TODO: add version check and add a warning if it doesn't match?
379-
using FileStream resolvedStream = File.OpenRead(Path.Combine(fullReferencePath, name));
380-
CreateAndAddReferenceToCompilation(name, resolvedStream, referenceAssemblyNamesToIgnore);
399+
using FileStream resolvedStream = File.OpenRead(Path.Combine(fullReferencePath, assemblyReferenceName));
400+
CreateAndAddReferenceToCompilation(assemblyReferenceName, rootAssemblyDisplayString, resolvedStream, referenceAssemblyNamesToIgnore, assemblyName);
381401
}
382402
// If we can't find a specific reference path for the dependency, then we look in the folders where the
383403
// rest of the reference paths are located to see if we can find the dependency there.
@@ -387,20 +407,21 @@ private void ResolveReferences(PEReader peReader, ImmutableHashSet<string>? refe
387407

388408
foreach (string referencePathDirectory in _referencePathDirectories)
389409
{
390-
string potentialPath = Path.Combine(referencePathDirectory, name);
410+
string potentialPath = Path.Combine(referencePathDirectory, assemblyReferenceName);
391411
if (File.Exists(potentialPath))
392412
{
393413
// TODO: add version check and add a warning if it doesn't match?
394414
using FileStream resolvedStream = File.OpenRead(potentialPath);
395-
CreateAndAddReferenceToCompilation(name, resolvedStream, referenceAssemblyNamesToIgnore);
415+
CreateAndAddReferenceToCompilation(assemblyReferenceName, rootAssemblyDisplayString, resolvedStream, referenceAssemblyNamesToIgnore, assemblyName);
396416
found = true;
397417
break;
398418
}
399419
}
400420

401421
if (!found)
402422
{
403-
_log.LogWarning(AssemblyReferenceNotFoundErrorCode, string.Format(Resources.CouldNotResolveReference, name));
423+
_log.LogWarning(AssemblyReferenceNotFoundErrorCode,
424+
string.Format(Resources.CouldNotResolveReference, assemblyReferenceName, rootAssemblyDisplayString));
404425
}
405426
}
406427
}

src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/Resources.resx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,26 @@
117117
<resheader name="writer">
118118
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
119119
</resheader>
120+
<data name="AssemblyLoaded" xml:space="preserve">
121+
<value>Assembly '{0}' loaded.</value>
122+
</data>
123+
<data name="AssemblyReferenceLoaded" xml:space="preserve">
124+
<value>Assembly '{0}' referenced by '{1}' loaded.</value>
125+
</data>
120126
<data name="CouldNotResolveReference" xml:space="preserve">
121-
<value>Could not resolve reference '{0}' in any of the provided search directories.</value>
127+
<value>Could not resolve reference '{0}' directly or transitively referenced by {1} in any of the provided search directories.</value>
128+
</data>
129+
<data name="LoadingAssemblies" xml:space="preserve">
130+
<value>Loading assemblies '{0}'.</value>
131+
</data>
132+
<data name="LoadingAssembliesFromArchive" xml:space="preserve">
133+
<value>Loading assemblies '{0}' ({1}).</value>
134+
</data>
135+
<data name="LoadingAssembly" xml:space="preserve">
136+
<value>Loading assembly '{0}'.</value>
137+
</data>
138+
<data name="LoadingAssemblyFromStream" xml:space="preserve">
139+
<value>Loading assembly '{0}' from stream.</value>
122140
</data>
123141
<data name="MatchingAssemblyNotFound" xml:space="preserve">
124142
<value>Could not find matching assembly: '{0}' in any of the search directories.</value>
@@ -129,6 +147,12 @@
129147
<data name="ProvidedStreamDoesNotHaveMetadata" xml:space="preserve">
130148
<value>Provided stream for assembly '{0}' doesn't have any metadata to read. from.</value>
131149
</data>
150+
<data name="RootAssemblyDisplayString" xml:space="preserve">
151+
<value>'{0}'</value>
152+
</data>
153+
<data name="RootAssemblyFromPackageDisplayString" xml:space="preserve">
154+
<value>'{0}' ({1})</value>
155+
</data>
132156
<data name="ShouldNotBeNullAndContainAtLeastOneElement" xml:space="preserve">
133157
<value>Should not be null and contain at least one element.</value>
134158
</data>

src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.cs.xlf

Lines changed: 42 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Compatibility/Microsoft.DotNet.ApiSymbolExtensions/xlf/Resources.de.xlf

Lines changed: 42 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)