Skip to content

Commit 1087712

Browse files
authored
[ApiDiff] Allow passing diagnostic options to all Compat places that use CSharpCompilationOptions (#46424)
1 parent 4f11aa7 commit 1087712

File tree

8 files changed

+36
-23
lines changed

8 files changed

+36
-23
lines changed

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public sealed class CSharpAssemblyDocumentGenerator
3535
private readonly IEnumerable<MetadataReference>? _metadataReferences;
3636
private readonly bool _addPartialModifier;
3737
private readonly bool _hideImplicitDefaultConstructors;
38+
private readonly CSharpCompilationOptions _compilationOptions;
3839

3940
/// <summary>
4041
/// Initializes a new instance of the <see cref="CSharpAssemblyDocumentGenerator"/> class.
@@ -46,6 +47,7 @@ public sealed class CSharpAssemblyDocumentGenerator
4647
/// <param name="exceptionMessage">The optional exception message to use.</param>
4748
/// <param name="includeAssemblyAttributes">Whether to include assembly attributes or not.</param>
4849
/// <param name="metadataReferences">The metadata references to use. The default value is <see langword="null"/>.</param>
50+
/// <param name="diagnosticOptions">The optional diagnostic options to use. The default value is <see langword="null"/>.</param>
4951
/// <param name="addPartialModifier">Whether to add the partial modifier or not. The default value is <see langword="true"/>.</param>
5052
/// <param name="hideImplicitDefaultConstructors">Whether to hide implicit default constructors or not. The default value is <see langword="true"/>.</param>
5153
public CSharpAssemblyDocumentGenerator(ILog log,
@@ -55,6 +57,7 @@ public CSharpAssemblyDocumentGenerator(ILog log,
5557
string? exceptionMessage,
5658
bool includeAssemblyAttributes,
5759
IEnumerable<MetadataReference>? metadataReferences = null,
60+
IEnumerable<KeyValuePair<string, ReportDiagnostic>>? diagnosticOptions = null,
5861
bool addPartialModifier = true,
5962
bool hideImplicitDefaultConstructors = true)
6063
{
@@ -69,6 +72,11 @@ public CSharpAssemblyDocumentGenerator(ILog log,
6972
_metadataReferences = metadataReferences;
7073
_addPartialModifier = addPartialModifier;
7174
_hideImplicitDefaultConstructors = hideImplicitDefaultConstructors;
75+
76+
_compilationOptions = new CSharpCompilationOptions(
77+
OutputKind.DynamicallyLinkedLibrary,
78+
nullableContextOptions: NullableContextOptions.Enable,
79+
specificDiagnosticOptions: diagnosticOptions);
7280
}
7381

7482
/// <summary>
@@ -78,11 +86,9 @@ public CSharpAssemblyDocumentGenerator(ILog log,
7886
/// <returns>The source code document instance of the specified assembly symbol.</returns>
7987
public Document GetDocumentForAssembly(IAssemblySymbol assemblySymbol)
8088
{
81-
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary,
82-
nullableContextOptions: NullableContextOptions.Enable);
8389
Project project = _adhocWorkspace.AddProject(ProjectInfo.Create(
8490
ProjectId.CreateNewId(), VersionStamp.Create(), assemblySymbol.Name, assemblySymbol.Name, LanguageNames.CSharp,
85-
compilationOptions: compilationOptions));
91+
compilationOptions: _compilationOptions));
8692
project = project.AddMetadataReferences(_metadataReferences ?? _loader.MetadataReferences);
8793

8894
IEnumerable<INamespaceSymbol> namespaceSymbols = EnumerateNamespaces(assemblySymbol).Where(_symbolFilter.Include);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public CSharpFileBuilder(ILog log,
3333
{
3434
_textWriter = textWriter;
3535
_header = header;
36-
_docGenerator = new CSharpAssemblyDocumentGenerator(log, loader, symbolFilter, attributeDataSymbolFilter, exceptionMessage, includeAssemblyAttributes, metadataReferences, addPartialModifier);
36+
_docGenerator = new CSharpAssemblyDocumentGenerator(log, loader, symbolFilter, attributeDataSymbolFilter, exceptionMessage, includeAssemblyAttributes, metadataReferences, addPartialModifier: addPartialModifier);
3737
}
3838

3939
/// <inheritdoc />

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static void Run(ILog log,
3535
log,
3636
assembliesPaths,
3737
assemblyReferencesPaths,
38-
respectInternals);
38+
respectInternals: respectInternals);
3939

4040
Run(log,
4141
loader,

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,19 @@ public class AssemblySymbolLoader : IAssemblySymbolLoader
5757
/// <param name="log">The logger instance to use for message logging.</param>
5858
/// <param name="assembliesPaths">A collection of paths where the assembly DLLs should be searched.</param>
5959
/// <param name="assemblyReferencesPaths">An optional collection of paths where the assembly references should be searched.</param>
60+
/// <param name="diagnosticOptions">An optional list of diagnostic options to use when compiling the loaded assemblies.</param>
6061
/// <param name="respectInternals">Whether to include internal symbols or not.</param>
6162
/// <returns>A tuple containing an assembly symbol loader and its corresponding dictionary of assembly symbols.</returns>
62-
public static (AssemblySymbolLoader, Dictionary<string, IAssemblySymbol>) CreateFromFiles(ILog log, string[] assembliesPaths, string[]? assemblyReferencesPaths, bool respectInternals = false)
63+
public static (AssemblySymbolLoader, Dictionary<string, IAssemblySymbol>) CreateFromFiles(ILog log, string[] assembliesPaths, string[]? assemblyReferencesPaths, IEnumerable<KeyValuePair<string, ReportDiagnostic>>? diagnosticOptions = null, bool respectInternals = false)
6364
{
6465
if (assembliesPaths.Length == 0)
6566
{
66-
return (new AssemblySymbolLoader(log, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals), new Dictionary<string, IAssemblySymbol>());
67+
return (new AssemblySymbolLoader(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals),
68+
new Dictionary<string, IAssemblySymbol>());
6769
}
6870

6971
bool atLeastOneReferencePath = assemblyReferencesPaths?.Count() > 0;
70-
AssemblySymbolLoader loader = new(log, resolveAssemblyReferences: atLeastOneReferencePath, respectInternals);
72+
AssemblySymbolLoader loader = new(log, diagnosticOptions, resolveAssemblyReferences: atLeastOneReferencePath, includeInternalSymbols: respectInternals);
7173
if (atLeastOneReferencePath)
7274
{
7375
loader.AddReferenceSearchPaths(assemblyReferencesPaths!);
@@ -97,14 +99,18 @@ public static (AssemblySymbolLoader, Dictionary<string, IAssemblySymbol>) Create
9799
/// Creates a new instance of the <see cref="AssemblySymbolLoader"/> class.
98100
/// </summary>
99101
/// <param name="log">A logger instance for logging message.</param>
102+
/// <param name="diagnosticOptions">An optional list of diagnostic options to use when compiling the loaded assemblies.</param>
100103
/// <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>
101104
/// <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>
102-
public AssemblySymbolLoader(ILog log, bool resolveAssemblyReferences = false, bool includeInternalSymbols = false)
105+
public AssemblySymbolLoader(ILog log, IEnumerable<KeyValuePair<string, ReportDiagnostic>>? diagnosticOptions = null, bool resolveAssemblyReferences = false, bool includeInternalSymbols = false)
103106
{
104107
_log = log;
105108
_loadedAssemblies = [];
106-
CSharpCompilationOptions compilationOptions = new(OutputKind.DynamicallyLinkedLibrary, nullableContextOptions: NullableContextOptions.Enable,
107-
metadataImportOptions: includeInternalSymbols ? MetadataImportOptions.Internal : MetadataImportOptions.Public);
109+
CSharpCompilationOptions compilationOptions = new(
110+
OutputKind.DynamicallyLinkedLibrary,
111+
nullableContextOptions: NullableContextOptions.Enable,
112+
metadataImportOptions: includeInternalSymbols ? MetadataImportOptions.Internal : MetadataImportOptions.Public,
113+
specificDiagnosticOptions: diagnosticOptions);
108114
_cSharpCompilation = CSharpCompilation.Create($"AssemblyLoader_{DateTime.Now:MM_dd_yy_HH_mm_ss_FFF}", options: compilationOptions);
109115
_resolveReferences = resolveAssemblyReferences;
110116
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ public sealed class AssemblySymbolLoaderFactory(ILog log, bool includeInternalSy
1414
{
1515
/// <inheritdoc />
1616
public IAssemblySymbolLoader Create(bool shouldResolveReferences) =>
17-
new AssemblySymbolLoader(log, shouldResolveReferences, includeInternalSymbols);
17+
new AssemblySymbolLoader(log, resolveAssemblyReferences: shouldResolveReferences, includeInternalSymbols: includeInternalSymbols);
1818
}
1919
}

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ public static string EmitAssemblyFromSyntax(string syntax,
3131
}
3232

3333
public static Stream EmitAssemblyStreamFromSyntax(string syntax,
34+
IEnumerable<KeyValuePair<string, ReportDiagnostic>> diagnosticOptions = null,
3435
bool enableNullable = false,
3536
byte[] publicKey = null,
3637
[CallerMemberName] string assemblyName = "",
3738
bool allowUnsafe = false)
3839
{
39-
CSharpCompilation compilation = CreateCSharpCompilationFromSyntax(syntax, assemblyName, enableNullable, publicKey, allowUnsafe);
40+
CSharpCompilation compilation = CreateCSharpCompilationFromSyntax(syntax, assemblyName, enableNullable, publicKey, allowUnsafe, diagnosticOptions);
4041

4142
Assert.Empty(compilation.GetDiagnostics());
4243

@@ -76,9 +77,9 @@ public static IAssemblySymbol GetAssemblyFromSyntaxWithReferences(string syntax,
7677
return compilation.Assembly;
7778
}
7879

79-
private static CSharpCompilation CreateCSharpCompilationFromSyntax(string syntax, string name, bool enableNullable, byte[] publicKey, bool allowUnsafe)
80+
private static CSharpCompilation CreateCSharpCompilationFromSyntax(string syntax, string name, bool enableNullable, byte[] publicKey, bool allowUnsafe, IEnumerable<KeyValuePair<string, ReportDiagnostic>> diagnosticOptions = null)
8081
{
81-
CSharpCompilation compilation = CreateCSharpCompilation(name, enableNullable, publicKey, allowUnsafe);
82+
CSharpCompilation compilation = CreateCSharpCompilation(name, enableNullable, publicKey, allowUnsafe, diagnosticOptions);
8283
return compilation.AddSyntaxTrees(GetSyntaxTree(syntax));
8384
}
8485

@@ -94,15 +95,15 @@ private static SyntaxTree GetSyntaxTree(string syntax)
9495
return CSharpSyntaxTree.ParseText(syntax, ParseOptions);
9596
}
9697

97-
private static CSharpCompilation CreateCSharpCompilation(string name, bool enableNullable, byte[] publicKey, bool allowUnsafe)
98+
private static CSharpCompilation CreateCSharpCompilation(string name, bool enableNullable, byte[] publicKey, bool allowUnsafe, IEnumerable<KeyValuePair<string, ReportDiagnostic>> diagnosticOptions = null)
9899
{
99100
bool publicSign = publicKey != null ? true : false;
100101
var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
101102
publicSign: publicSign,
102103
cryptoPublicKey: publicSign ? publicKey.ToImmutableArray() : default,
103104
nullableContextOptions: enableNullable ? NullableContextOptions.Enable : NullableContextOptions.Disable,
104105
allowUnsafe: allowUnsafe,
105-
specificDiagnosticOptions: DiagnosticOptions);
106+
specificDiagnosticOptions: diagnosticOptions ?? DiagnosticOptions);
106107

107108
return CSharpCompilation.Create(name, options: compilationOptions, references: DefaultReferences);
108109
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using Microsoft.DotNet.ApiSymbolExtensions;
1010
using Microsoft.DotNet.ApiSymbolExtensions.Filtering;
1111
using Microsoft.DotNet.ApiSymbolExtensions.Logging;
12-
using Microsoft.DotNet.ApiSymbolExtensions.Tests;
1312
using Moq;
1413

1514
namespace Microsoft.DotNet.GenAPI.Tests
@@ -40,7 +39,7 @@ private void RunTest(string original,
4039
Mock<ILog> log = new();
4140

4241
(IAssemblySymbolLoader loader, Dictionary<string, IAssemblySymbol> assemblySymbols) = TestAssemblyLoaderFactory
43-
.CreateFromTexts(log.Object, assemblyTexts: [(assemblyName, original)], respectInternals: includeInternalSymbols, allowUnsafe);
42+
.CreateFromTexts(log.Object, assemblyTexts: [(assemblyName, original)], respectInternals: includeInternalSymbols, allowUnsafe: allowUnsafe);
4443

4544
ISymbolFilter symbolFilter = SymbolFilterFactory.GetFilterFromList([], null, includeInternalSymbols, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols);
4645
ISymbolFilter attributeDataSymbolFilter = SymbolFilterFactory.GetFilterFromList(excludedAttributeList, null, includeInternalSymbols, includeEffectivelyPrivateSymbols, includeExplicitInterfaceImplementationSymbols);

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,22 @@ namespace Microsoft.DotNet.GenAPI.Tests;
1111

1212
public class TestAssemblyLoaderFactory
1313
{
14-
public static (IAssemblySymbolLoader, Dictionary<string, IAssemblySymbol>) CreateFromTexts(ILog log, (string, string)[] assemblyTexts, bool respectInternals = false, bool allowUnsafe = false)
14+
public static (IAssemblySymbolLoader, Dictionary<string, IAssemblySymbol>) CreateFromTexts(ILog log, (string, string)[] assemblyTexts, IEnumerable<KeyValuePair<string, ReportDiagnostic>>? diagnosticOptions = null, bool respectInternals = false, bool allowUnsafe = false)
1515
{
1616
if (assemblyTexts.Length == 0)
1717
{
18-
return (new AssemblySymbolLoader(log, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals), new Dictionary<string, IAssemblySymbol>());
18+
return (new AssemblySymbolLoader(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals),
19+
new Dictionary<string, IAssemblySymbol>());
1920
}
2021

21-
AssemblySymbolLoader loader = new(log, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals);
22+
AssemblySymbolLoader loader = new(log, diagnosticOptions, resolveAssemblyReferences: true, includeInternalSymbols: respectInternals);
2223
loader.AddReferenceSearchPaths(typeof(object).Assembly!.Location!);
2324
loader.AddReferenceSearchPaths(typeof(DynamicAttribute).Assembly!.Location!);
2425

2526
Dictionary<string, IAssemblySymbol> assemblySymbols = new();
2627
foreach ((string assemblyName, string assemblyText) in assemblyTexts)
2728
{
28-
using Stream assemblyStream = SymbolFactory.EmitAssemblyStreamFromSyntax(assemblyText, enableNullable: true, allowUnsafe: allowUnsafe, assemblyName: assemblyName);
29+
using Stream assemblyStream = SymbolFactory.EmitAssemblyStreamFromSyntax(assemblyText, diagnosticOptions, enableNullable: true, allowUnsafe: allowUnsafe, assemblyName: assemblyName);
2930
if (loader.LoadAssembly(assemblyName, assemblyStream) is IAssemblySymbol assemblySymbol)
3031
{
3132
assemblySymbols.Add(assemblyName, assemblySymbol);

0 commit comments

Comments
 (0)