Skip to content

Commit fd87d94

Browse files
committed
Pass an ILog instance to the AssemblySymbolLoader constructor.
1 parent e874a21 commit fd87d94

File tree

10 files changed

+88
-41
lines changed

10 files changed

+88
-41
lines changed

src/Compatibility/ApiCompat/Microsoft.DotNet.ApiCompat.Shared/ApiCompatServiceProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public ApiCompatServiceProvider(Func<ISuppressionEngine, ISuppressibleLog> logFa
4949
return new ApiCompatRunner(SuppressibleLog,
5050
SuppressionEngine,
5151
new ApiComparerFactory(ruleFactory(SuppressibleLog), apiComparerSettings),
52-
new AssemblySymbolLoaderFactory(respectInternals));
52+
new AssemblySymbolLoaderFactory(SuppressibleLog, respectInternals));
5353
});
5454
}
5555

src/Compatibility/GenAPI/Microsoft.DotNet.GenAPI/GenAPIApp.cs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static void Run(ILog logger,
3535
bool resolveAssemblyReferences = assemblyReferences?.Length > 0;
3636

3737
// Create, configure and execute the assembly loader.
38-
AssemblySymbolLoader loader = new(resolveAssemblyReferences, respectInternals);
38+
AssemblySymbolLoader loader = new(logger, resolveAssemblyReferences, respectInternals);
3939
if (assemblyReferences is not null)
4040
{
4141
loader.AddReferenceSearchPaths(assemblyReferences);
@@ -86,21 +86,8 @@ public static void Run(ILog logger,
8686
fileBuilder.WriteAssembly(assemblySymbol);
8787
}
8888

89-
if (loader.HasRoslynDiagnostics(out IReadOnlyList<Diagnostic> roslynDiagnostics))
90-
{
91-
foreach (Diagnostic warning in roslynDiagnostics)
92-
{
93-
logger.LogWarning(warning.Id, warning.ToString());
94-
}
95-
}
96-
97-
if (loader.HasLoadWarnings(out IReadOnlyList<AssemblyLoadWarning> loadWarnings))
98-
{
99-
foreach (AssemblyLoadWarning warning in loadWarnings)
100-
{
101-
logger.LogWarning(warning.DiagnosticId, warning.Message);
102-
}
103-
}
89+
loader.LogAllDiagnostics();
90+
loader.LogAllWarnings();
10491
}
10592

10693
// Creates a TextWriter capable of writing into Console or a cs file.

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

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Reflection.PortableExecutable;
88
using Microsoft.CodeAnalysis;
99
using Microsoft.CodeAnalysis.CSharp;
10+
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
1011

1112
namespace Microsoft.DotNet.ApiSymbolExtensions
1213
{
@@ -15,7 +16,8 @@ namespace Microsoft.DotNet.ApiSymbolExtensions
1516
/// </summary>
1617
public class AssemblySymbolLoader : IAssemblySymbolLoader
1718
{
18-
// Dictionary that holds the paths to help loading dependencies. Keys will be assembly name and
19+
private readonly ILog _logger;
20+
// Dictionary that holds the paths to help loading dependencies. Keys will be assembly name and
1921
// value are the containing folder.
2022
private readonly Dictionary<string, string> _referencePathFiles = new(StringComparer.OrdinalIgnoreCase);
2123
private readonly HashSet<string> _referencePathDirectories = new(StringComparer.OrdinalIgnoreCase);
@@ -37,10 +39,12 @@ public class AssemblySymbolLoader : IAssemblySymbolLoader
3739
/// <summary>
3840
/// Creates a new instance of the <see cref="AssemblySymbolLoader"/> class.
3941
/// </summary>
42+
/// <param name="logger">A logger instance for logging message.</param>
4043
/// <param name="resolveAssemblyReferences">True to attempt to load references for loaded assemblies from the locations specified with <see cref="AddReferenceSearchPaths(string[])"/>. Default is false.</param>
4144
/// <param name="includeInternalSymbols">True to include all internal metadata for assemblies loaded. Default is false which only includes public and some internal metadata. <seealso cref="MetadataImportOptions"/></param>
42-
public AssemblySymbolLoader(bool resolveAssemblyReferences = false, bool includeInternalSymbols = false)
45+
public AssemblySymbolLoader(ILog logger, bool resolveAssemblyReferences = false, bool includeInternalSymbols = false)
4346
{
47+
_logger = logger;
4448
_loadedAssemblies = [];
4549
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable,
4650
metadataImportOptions: includeInternalSymbols ? MetadataImportOptions.Internal : MetadataImportOptions.Public);
@@ -386,5 +390,39 @@ private void ResolveReferences(PEReader peReader, ImmutableHashSet<string>? refe
386390
}
387391
}
388392
}
393+
394+
/// <inheritdoc />
395+
public void LogAllDiagnostics(string? headerMessage = null)
396+
{
397+
if (HasRoslynDiagnostics(out IReadOnlyList<Diagnostic> roslynDiagnostics))
398+
{
399+
if (!string.IsNullOrEmpty(headerMessage))
400+
{
401+
_logger.LogWarning(headerMessage!);
402+
}
403+
404+
foreach (Diagnostic warning in roslynDiagnostics)
405+
{
406+
_logger.LogWarning(warning.Id, warning.ToString());
407+
}
408+
}
409+
}
410+
411+
/// <inheritdoc />
412+
public void LogAllWarnings(string? headerMessage = null)
413+
{
414+
if (HasLoadWarnings(out IReadOnlyList<AssemblyLoadWarning> loadWarnings))
415+
{
416+
if (!string.IsNullOrEmpty(headerMessage))
417+
{
418+
_logger.LogWarning(headerMessage!);
419+
}
420+
421+
foreach (AssemblyLoadWarning warning in loadWarnings)
422+
{
423+
_logger.LogWarning(warning.DiagnosticId, warning.Message);
424+
}
425+
}
426+
}
389427
}
390428
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
5+
46
namespace Microsoft.DotNet.ApiSymbolExtensions
57
{
68
/// <summary>
79
/// Factory to create an AssemblySymbolLoader
810
/// </summary>
11+
/// <param name="logger">A logger instance used for logging messages.</param>
912
/// <param name="includeInternalSymbols">True to include internal API when reading assemblies from the <see cref="AssemblySymbolLoader"/> created.</param>
10-
public sealed class AssemblySymbolLoaderFactory(bool includeInternalSymbols = false) : IAssemblySymbolLoaderFactory
13+
public sealed class AssemblySymbolLoaderFactory(ILog logger, bool includeInternalSymbols = false) : IAssemblySymbolLoaderFactory
1114
{
1215
/// <inheritdoc />
1316
public IAssemblySymbolLoader Create(bool shouldResolveReferences) =>
14-
new AssemblySymbolLoader(shouldResolveReferences, includeInternalSymbols);
17+
new AssemblySymbolLoader(logger, shouldResolveReferences, includeInternalSymbols);
1518
}
1619
}

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public interface IAssemblySymbolLoader
6060
/// </summary>
6161
/// <param name="name">The name to use to resolve the assembly.</param>
6262
/// <param name="stream">The stream to read the metadata from.</param>
63-
/// <returns><see cref="IAssemblySymbol"/> representing the given <paramref name="stream"/>. If an
63+
/// <returns><see cref="IAssemblySymbol"/> representing the given <paramref name="stream"/>. If an
6464
/// assembly with the same <paramref name="name"/> was already loaded, the previously loaded assembly is returned.</returns>
6565
IAssemblySymbol? LoadAssembly(string name, Stream stream);
6666

@@ -83,6 +83,18 @@ public interface IAssemblySymbolLoader
8383
/// <returns>The list of matching assemblies represented as <see cref="IAssemblySymbol"/>.</returns>
8484
IEnumerable<IAssemblySymbol> LoadMatchingAssemblies(IEnumerable<IAssemblySymbol> fromAssemblies, IEnumerable<string> searchPaths, bool validateMatchingIdentity = true, bool warnOnMissingAssemblies = true);
8585

86+
/// <summary>
87+
/// Logs all diagnostics that were emitted during the loading of the assemblies.
88+
/// </summary>
89+
/// <param name="headerMessage">Optional custom message to prepend to the diagnostics.</param>
90+
public void LogAllDiagnostics(string? headerMessage = null);
91+
92+
/// <summary>
93+
/// Logs all warnings that were emitted during the loading of the assemblies.
94+
/// </summary>
95+
/// <param name="headerMessage">Optional custom message to prepend to the warnings.</param>
96+
public void LogAllWarnings(string? headerMessage = null);
97+
8698
/// <summary>
8799
/// The list of metadata references represented as <see cref="MetadataReference" />.
88100
/// </summary>

test/Microsoft.DotNet.ApiCompat.IntegrationTests/CompatibleFrameworkInPackageValidatorIntegrationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public CompatibleFrameworkInPackageValidatorIntegrationTests(ITestOutputHelper l
2727
new ApiCompatRunner(log,
2828
new SuppressionEngine(),
2929
new ApiComparerFactory(new RuleFactory(log)),
30-
new AssemblySymbolLoaderFactory()));
30+
new AssemblySymbolLoaderFactory(log)));
3131

3232
return (log, validator);
3333
}

test/Microsoft.DotNet.ApiCompat.IntegrationTests/Task/ValidatePackageTargetIntegrationTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public ValidatePackageTargetIntegrationTests(ITestOutputHelper log) : base(log)
2929
new ApiCompatRunner(log,
3030
new SuppressionEngine(),
3131
new ApiComparerFactory(new RuleFactory(log)),
32-
new AssemblySymbolLoaderFactory()));
32+
new AssemblySymbolLoaderFactory(log)));
3333

3434
return (log, validator);
3535
}

test/Microsoft.DotNet.ApiCompatibility.Tests/Rules/AssemblyIdentityMustMatchTests.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Microsoft.CodeAnalysis.CSharp;
88
using Microsoft.DotNet.ApiCompatibility.Tests;
99
using Microsoft.DotNet.ApiSymbolExtensions;
10+
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
1011
using Microsoft.DotNet.ApiSymbolExtensions.Tests;
1112

1213
namespace Microsoft.DotNet.ApiCompatibility.Rules.Tests
@@ -196,8 +197,10 @@ public void RetargetableFlagSet(bool strictMode)
196197
string leftAssembly = SymbolFactory.EmitAssemblyFromSyntax(syntax, publicKey: _publicKey);
197198
string rightAssembly = SymbolFactory.EmitAssemblyFromSyntax(syntax);
198199

199-
IAssemblySymbol leftSymbol = new AssemblySymbolLoader().LoadAssembly(leftAssembly);
200-
IAssemblySymbol rightSymbol = new AssemblySymbolLoader().LoadAssembly(rightAssembly);
200+
ILog logger = new ConsoleLog(MessageImportance.High);
201+
202+
IAssemblySymbol leftSymbol = new AssemblySymbolLoader(logger).LoadAssembly(leftAssembly);
203+
IAssemblySymbol rightSymbol = new AssemblySymbolLoader(logger).LoadAssembly(rightAssembly);
201204

202205
Assert.True(leftSymbol.Identity.IsRetargetable);
203206
Assert.True(rightSymbol.Identity.IsRetargetable);
@@ -210,4 +213,3 @@ public void RetargetableFlagSet(bool strictMode)
210213
}
211214
}
212215
}
213-

test/Microsoft.DotNet.ApiSymbolExtensions.Tests/AssemblySymbolLoaderTests.cs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66
using System.Collections.Concurrent;
77
using System.Reflection;
88
using Microsoft.CodeAnalysis;
9+
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
910
using Microsoft.DotNet.Cli.Utils;
1011

1112
namespace Microsoft.DotNet.ApiSymbolExtensions.Tests
1213
{
1314
public class AssemblySymbolLoaderTests : SdkTest
1415
{
16+
private readonly ILog _logger = new ConsoleLog(MessageImportance.High);
17+
1518
public AssemblySymbolLoaderTests(ITestOutputHelper log) : base(log) { }
1619

1720
private const string SimpleAssemblySourceContents = @"
@@ -89,14 +92,14 @@ private TestAssetInfo GetAsset(TestAssetsManager manager)
8992
[Fact]
9093
public void LoadAssembly_Throws()
9194
{
92-
AssemblySymbolLoader loader = new();
95+
AssemblySymbolLoader loader = new(_logger);
9396
Assert.Throws<FileNotFoundException>(() => loader.LoadAssembly(Guid.NewGuid().ToString("N").Substring(0, 8)));
9497
}
9598

9699
[Fact]
97100
public void LoadAssemblyFromSourceFiles_Throws()
98101
{
99-
AssemblySymbolLoader loader = new();
102+
AssemblySymbolLoader loader = new(_logger);
100103
IEnumerable<string> paths = new[] { Guid.NewGuid().ToString("N") };
101104
Assert.Throws<FileNotFoundException>(() => loader.LoadAssemblyFromSourceFiles(paths, "assembly1", Array.Empty<string>()));
102105
Assert.Throws<ArgumentNullException>("filePaths", () => loader.LoadAssemblyFromSourceFiles(Array.Empty<string>(), "assembly1", Array.Empty<string>()));
@@ -106,7 +109,7 @@ public void LoadAssemblyFromSourceFiles_Throws()
106109
[Fact]
107110
public void LoadMatchingAssemblies_Throws()
108111
{
109-
AssemblySymbolLoader loader = new();
112+
AssemblySymbolLoader loader = new(_logger);
110113
IEnumerable<string> paths = new[] { Guid.NewGuid().ToString("N") };
111114
IAssemblySymbol assembly = SymbolFactory.GetAssemblyFromSyntax("namespace MyNamespace { class Foo { } }");
112115

@@ -119,7 +122,7 @@ public void LoadMatchingAssembliesWarns()
119122
IAssemblySymbol assembly = SymbolFactory.GetAssemblyFromSyntax("namespace MyNamespace { class Foo { } }");
120123
IEnumerable<string> paths = new[] { AppContext.BaseDirectory };
121124

122-
AssemblySymbolLoader loader = new();
125+
AssemblySymbolLoader loader = new(_logger);
123126
IEnumerable<IAssemblySymbol> symbols = loader.LoadMatchingAssemblies(new[] { assembly }, paths);
124127
Assert.Empty(symbols);
125128
Assert.True(loader.HasLoadWarnings(out IReadOnlyList<AssemblyLoadWarning> warnings));
@@ -152,7 +155,7 @@ public void LoadMatchingAssembliesSameIdentitySucceeds()
152155
.Should()
153156
.Pass();
154157

155-
AssemblySymbolLoader loader = new();
158+
AssemblySymbolLoader loader = new(_logger);
156159
IEnumerable<IAssemblySymbol> matchingAssemblies = loader.LoadMatchingAssemblies(new[] { fromAssembly }, new[] { outputDirectory });
157160

158161
Assert.Single(matchingAssemblies);
@@ -167,7 +170,7 @@ public void LoadMatchingAssemblies_DifferentIdentity(bool validateIdentities)
167170
var assetInfo = GetSimpleTestAsset();
168171
IAssemblySymbol fromAssembly = SymbolFactory.GetAssemblyFromSyntax(SimpleAssemblySourceContents, assemblyName: assetInfo.TestAsset.TestProject.Name);
169172

170-
AssemblySymbolLoader loader = new();
173+
AssemblySymbolLoader loader = new(_logger);
171174
IEnumerable<IAssemblySymbol> matchingAssemblies = loader.LoadMatchingAssemblies(new[] { fromAssembly }, new[] { assetInfo.OutputDirectory }, validateMatchingIdentity: validateIdentities);
172175

173176
if (validateIdentities)
@@ -194,7 +197,7 @@ public void LoadMatchingAssemblies_DifferentIdentity(bool validateIdentities)
194197
public void LoadsSimpleAssemblyFromDirectory()
195198
{
196199
var assetInfo = GetSimpleTestAsset();
197-
AssemblySymbolLoader loader = new();
200+
AssemblySymbolLoader loader = new(_logger);
198201
IEnumerable<IAssemblySymbol> symbols = loader.LoadAssemblies(assetInfo.OutputDirectory);
199202
Assert.Single(symbols);
200203

@@ -212,7 +215,7 @@ public void LoadsSimpleAssemblyFromDirectory()
212215
public void LoadSimpleAssemblyFullPath()
213216
{
214217
var assetInfo = GetSimpleTestAsset();
215-
AssemblySymbolLoader loader = new();
218+
AssemblySymbolLoader loader = new(_logger);
216219
IAssemblySymbol symbol = loader.LoadAssembly(Path.Combine(assetInfo.OutputDirectory, assetInfo.TestAsset.TestProject.Name + ".dll"));
217220

218221
IEnumerable<ITypeSymbol> types = symbol.GlobalNamespace
@@ -246,7 +249,7 @@ public void LoadsMultipleAssembliesFromDirectory()
246249
.Should()
247250
.Pass();
248251

249-
AssemblySymbolLoader loader = new();
252+
AssemblySymbolLoader loader = new(_logger);
250253
IEnumerable<IAssemblySymbol> symbols = loader.LoadAssemblies(outputDirectory);
251254

252255
Assert.Equal(2, symbols.Count());
@@ -263,7 +266,7 @@ public void LoadsMultipleAssembliesFromDirectory()
263266
public void LoadAssemblyResolveReferences_WarnsWhenEnabled(bool resolveReferences)
264267
{
265268
var assetInfo = GetSimpleTestAsset();
266-
AssemblySymbolLoader loader = new(resolveAssemblyReferences: resolveReferences);
269+
AssemblySymbolLoader loader = new(_logger, resolveAssemblyReferences: resolveReferences);
267270
loader.LoadAssembly(Path.Combine(assetInfo.OutputDirectory, assetInfo.TestAsset.TestProject.Name + ".dll"));
268271

269272
if (resolveReferences)
@@ -295,7 +298,7 @@ public void LoadAssemblyResolveReferences_WarnsWhenEnabled(bool resolveReference
295298
public void LoadAssembliesShouldResolveReferencesNoWarnings()
296299
{
297300
var assetInfo = GetSimpleTestAsset();
298-
AssemblySymbolLoader loader = new(resolveAssemblyReferences: true);
301+
AssemblySymbolLoader loader = new(_logger, resolveAssemblyReferences: true);
299302
// AddReferenceSearchDirectories should be able to handle directories as well as full path to assemblies.
300303
loader.AddReferenceSearchPaths(Path.GetDirectoryName(typeof(string).Assembly.Location));
301304
loader.AddReferenceSearchPaths(Path.GetFullPath(typeof(string).Assembly.Location));
@@ -314,7 +317,7 @@ public void LoadAssemblyFromStreamNoWarns()
314317
{
315318
var assetInfo = GetSimpleTestAsset();
316319
TestProject testProject = assetInfo.TestAsset.TestProject;
317-
AssemblySymbolLoader loader = new();
320+
AssemblySymbolLoader loader = new(_logger);
318321
using FileStream stream = File.OpenRead(Path.Combine(assetInfo.OutputDirectory, testProject.Name + ".dll"));
319322
IAssemblySymbol symbol = loader.LoadAssembly(testProject.Name, stream);
320323

test/Microsoft.DotNet.GenAPI.Tests/CSharpFileBuilderTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ private void RunTest(string original,
5454
}
5555
attributeDataSymbolFilter.Add(accessibilitySymbolFilter);
5656

57+
ILog logger = new ConsoleLog(MessageImportance.Low);
58+
5759
IAssemblySymbolWriter csharpFileBuilder = new CSharpFileBuilder(
58-
new ConsoleLog(MessageImportance.Low),
60+
logger,
5961
symbolFilter,
6062
attributeDataSymbolFilter,
6163
stringWriter,
@@ -64,7 +66,7 @@ private void RunTest(string original,
6466
MetadataReferences);
6567

6668
using Stream assemblyStream = SymbolFactory.EmitAssemblyStreamFromSyntax(original, enableNullable: true, allowUnsafe: allowUnsafe, assemblyName: assemblyName);
67-
AssemblySymbolLoader assemblySymbolLoader = new(resolveAssemblyReferences: true, includeInternalSymbols: includeInternalSymbols);
69+
AssemblySymbolLoader assemblySymbolLoader = new(logger, resolveAssemblyReferences: true, includeInternalSymbols: includeInternalSymbols);
6870
assemblySymbolLoader.AddReferenceSearchPaths(typeof(object).Assembly!.Location!);
6971
assemblySymbolLoader.AddReferenceSearchPaths(typeof(DynamicAttribute).Assembly!.Location!);
7072
IAssemblySymbol assemblySymbol = assemblySymbolLoader.LoadAssembly(assemblyName, assemblyStream);

0 commit comments

Comments
 (0)