-
Notifications
You must be signed in to change notification settings - Fork 116
Add 'CsWinRTMergeReferencedActivationFactories' option #1637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Sergio0694
merged 17 commits into
staging/AOT
from
user/sergiopedri/merged-activation-factories
Jun 28, 2024
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
3ac90b4
Add 'WinRTAssemblyExportsTypeAttribute' type
Sergio0694 7203787
Generate [WinRTAssemblyExportsType] types
Sergio0694 88cf020
Add new symbol extensions
Sergio0694 84ea663
Add 'MergeReferencedActivationFactoriesGenerator'
Sergio0694 b6bfcd3
Set default value of new MSBuild option
Sergio0694 ba8fbc7
Update readme.md
Sergio0694 69f859e
Update MatchingRefApiCompatBaseline.txt
Sergio0694 a60d4e7
Invoke 'fullyQualifiedTypeName' in AOT export
Sergio0694 f6570c1
Fix check for metadata reference types
Sergio0694 3d77666
Add missing 'CompilerVisibleProperty'
Sergio0694 7157e38
Simplify 'MergeReferencedActivationFactoriesGenerator'
Sergio0694 030dd60
Add missing 'unsafe' modifier
Sergio0694 8c3d14a
Fix reading type from assembly attributes
Sergio0694 9d9f7b9
Escape invalid characters in assembly names
Sergio0694 e18cfb5
Fix issues with multiple assemblies, minor tweaks
Sergio0694 8e20655
Enable unsafe blocks in diagnostic tests
Sergio0694 1c735f3
Remove unnecessary 'unsafe' modifier
Sergio0694 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
175 changes: 175 additions & 0 deletions
175
src/Authoring/WinRT.SourceGenerator/MergeReferencedActivationFactoriesGenerator.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
using System.Collections.Immutable; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis; | ||
using WinRT.SourceGenerator; | ||
|
||
#nullable enable | ||
|
||
namespace Generator; | ||
|
||
[Generator] | ||
public sealed class MergeReferencedActivationFactoriesGenerator : IIncrementalGenerator | ||
{ | ||
/// <inheritdoc/> | ||
public void Initialize(IncrementalGeneratorInitializationContext context) | ||
{ | ||
// Get whether the generator is enabled | ||
IncrementalValueProvider<bool> isGeneratorEnabled = context.AnalyzerConfigOptionsProvider.Select(static (options, token) => | ||
{ | ||
return options.GetCsWinRTMergeReferencedActivationFactories(); | ||
}); | ||
|
||
// Get the fully qualified type names of all assembly exports types to merge | ||
IncrementalValueProvider<EquatableArray<string>> assemblyExportsTypeNames = | ||
context.CompilationProvider | ||
.Combine(isGeneratorEnabled) | ||
.Select(static (item, token) => | ||
{ | ||
// Immediately bail if the generator is disabled | ||
if (!item.Right) | ||
{ | ||
return new EquatableArray<string>(ImmutableArray<string>.Empty); | ||
} | ||
|
||
ImmutableArray<string>.Builder builder = ImmutableArray.CreateBuilder<string>(); | ||
|
||
foreach (MetadataReference metadataReference in item.Left.References) | ||
{ | ||
token.ThrowIfCancellationRequested(); | ||
|
||
if (item.Left.GetAssemblyOrModuleSymbol(metadataReference) is not IAssemblySymbol assemblySymbol) | ||
{ | ||
continue; | ||
} | ||
|
||
token.ThrowIfCancellationRequested(); | ||
|
||
// Add the type name if the assembly is a WinRT component | ||
if (TryGetDependentAssemblyExportsTypeName( | ||
assemblySymbol, | ||
item.Left, | ||
token, | ||
out string? name)) | ||
{ | ||
builder.Add(name); | ||
} | ||
} | ||
|
||
token.ThrowIfCancellationRequested(); | ||
|
||
return new EquatableArray<string>(builder.ToImmutable()); | ||
}); | ||
|
||
// Generate the chaining helper | ||
context.RegisterImplementationSourceOutput(assemblyExportsTypeNames, static (context, assemblyExportsTypeNames) => | ||
{ | ||
StringBuilder builder = new(); | ||
|
||
builder.AppendLine(""" | ||
// <auto-generated/> | ||
#pragma warning disable | ||
|
||
namespace WinRT | ||
{ | ||
using global::System; | ||
|
||
/// <inheritdoc cref="Module"/> | ||
partial class Module | ||
{ | ||
/// <summary> | ||
/// Tries to retrieve the activation factory from all dependent WinRT components. | ||
/// </summary> | ||
/// <param name="fullyQualifiedTypeName">The marshalled fully qualified type name of the activation factory to retrieve.</param> | ||
/// <returns>The pointer to the activation factory that corresponds with the class specified by <paramref name="fullyQualifiedTypeName"/>.</returns> | ||
internal static unsafe IntPtr TryGetDependentActivationFactory(ReadOnlySpan<char> fullyQualifiedTypeName) | ||
{ | ||
"""); | ||
|
||
if (!assemblyExportsTypeNames.IsEmpty) | ||
{ | ||
builder.AppendLine(" IntPtr obj;"); | ||
builder.AppendLine(); | ||
} | ||
|
||
foreach (string assemblyExportsTypeName in assemblyExportsTypeNames) | ||
{ | ||
builder.AppendLine($$""" | ||
obj = global::{{assemblyExportsTypeName}}.GetActivationFactory(fullyQualifiedTypeName); | ||
|
||
if ((void*)obj is not null) | ||
{ | ||
return obj; | ||
} | ||
|
||
"""); | ||
} | ||
|
||
builder.AppendLine(""" | ||
return default; | ||
} | ||
} | ||
} | ||
"""); | ||
|
||
context.AddSource("ChainedExports.g.cs", builder.ToString()); | ||
}); | ||
} | ||
|
||
/// <summary> | ||
/// Tries to get the name of a dependent WinRT component from a given assembly. | ||
/// </summary> | ||
/// <param name="assemblySymbol">The assembly symbol to analyze.</param> | ||
/// <param name="compilation">The <see cref="Compilation"/> instance to use.</param> | ||
/// <param name="token">The <see cref="CancellationToken"/> instance to use.</param> | ||
/// <param name="name">The resulting type name, if found.</param> | ||
/// <returns>Whether a type name was found.</returns> | ||
private static bool TryGetDependentAssemblyExportsTypeName( | ||
IAssemblySymbol assemblySymbol, | ||
Compilation compilation, | ||
CancellationToken token, | ||
[NotNullWhen(true)] out string? name) | ||
{ | ||
// Get the attribute to lookup to find the target type to use | ||
INamedTypeSymbol winRTAssemblyExportsTypeAttributeSymbol = compilation.GetTypeByMetadataName("WinRT.WinRTAssemblyExportsTypeAttribute")!; | ||
|
||
// Make sure the assembly does have the attribute on it | ||
if (!assemblySymbol.TryGetAttributeWithType(winRTAssemblyExportsTypeAttributeSymbol, out AttributeData? attributeData)) | ||
{ | ||
name = null; | ||
|
||
return false; | ||
} | ||
|
||
token.ThrowIfCancellationRequested(); | ||
|
||
// Sanity check: we should have a valid type in the annotation | ||
if (attributeData.ConstructorArguments is not [{ Kind: TypedConstantKind.Type, Value: INamedTypeSymbol assemblyExportsTypeSymbol }]) | ||
{ | ||
name = null; | ||
|
||
return false; | ||
} | ||
|
||
token.ThrowIfCancellationRequested(); | ||
|
||
// Other sanity check: this type should be accessible from this compilation | ||
if (!assemblyExportsTypeSymbol.IsAccessibleFromCompilationAssembly(compilation)) | ||
{ | ||
name = null; | ||
|
||
return false; | ||
} | ||
|
||
token.ThrowIfCancellationRequested(); | ||
|
||
name = assemblyExportsTypeSymbol.ToDisplayString(); | ||
|
||
return true; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.