Skip to content

Commit bfe8634

Browse files
authored
Merge branch 'main' into dev/rolf/avfoundation
2 parents ff0afdf + b472b63 commit bfe8634

File tree

72 files changed

+8007
-976
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+8007
-976
lines changed

src/ObjCRuntime/RegistrarHelper.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,25 @@ static MapInfo GetMapEntry (string assemblyName)
102102
{
103103
if (TryGetMapEntry (assemblyName, out var rv))
104104
return rv;
105+
106+
#if TRACE
107+
Runtime.NSLog ($"RegistrarHelper.GetMapEntry ({assemblyName}) => failed to find entry, will ensure module constructors are called for all loaded assemblies.");
108+
#endif
109+
// An assembly is only registered if we've (tried to) execute code from it, which is not guaranteed to
110+
// happen before we get here (in particular for app extensions, which don't have a managed Main method).
111+
// So here we loop over all the assemblies in the current domain, make sure the module constructor
112+
// has been called for all of them, and then we try again.
113+
var assemblies = AppDomain.CurrentDomain.GetAssemblies ();
114+
foreach (var asm in assemblies)
115+
RuntimeHelpers.RunModuleConstructor (asm.ManifestModule.ModuleHandle);
116+
117+
if (TryGetMapEntry (assemblyName, out rv))
118+
return rv;
119+
120+
#if TRACE
121+
Runtime.NSLog ($"RegistrarHelper.GetMapEntry ({assemblyName}) => failed to find entry for the second time.");
122+
#endif
123+
105124
throw ErrorHelper.CreateError (8055, Errors.MX8055 /* Could not find the type 'ObjCRuntime.__Registrar__' in the assembly '{0}' */, assemblyName);
106125
}
107126

src/rgen/Microsoft.Macios.Generator/AttributesNames.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ static class AttributesNames {
2020
public const string UnsupportedOSPlatformAttribute = "System.Runtime.Versioning.UnsupportedOSPlatformAttribute";
2121
public const string ObsoletedOSPlatformAttribute = "System.Runtime.Versioning.ObsoletedOSPlatformAttribute";
2222

23+
public static readonly string [] BindingTypes = [
24+
BindingAttribute,
25+
BindingCategoryAttribute,
26+
BindingClassAttribute,
27+
BindingProtocolAttribute
28+
];
29+
2330

2431
public static string? GetBindingTypeAttributeName<T> () where T : Enum
2532
{

src/rgen/Microsoft.Macios.Generator/BindingSourceGeneratorGenerator.cs

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace Microsoft.Macios.Generator;
2222
/// </summary>
2323
[Generator]
2424
public class BindingSourceGeneratorGenerator : IIncrementalGenerator {
25-
static readonly DeclarationCodeChangesEqualityComparer equalityComparer = new ();
25+
static readonly CodeChangesEqualityComparer equalityComparer = new ();
2626

2727
/// <inheritdoc cref="IIncrementalGenerator"/>
2828
public void Initialize (IncrementalGeneratorInitializationContext context)
@@ -34,15 +34,15 @@ public void Initialize (IncrementalGeneratorInitializationContext context)
3434
fileName, SourceText.From (content, Encoding.UTF8)));
3535
}
3636

37-
// our bindings are special. Due to the fact that we write shared code in the Library.g.cs and the Trampolines.g.cs
37+
// our bindings are special. Since we write shared code in the Library.g.cs and the Trampolines.g.cs
3838
// we need to listen to all the BaseTypeDeclarationSyntax changes. We do so, generate a data model with the
39-
// changes we are interested and later we transform them. This allows use to be able to use a RootBindingContext
39+
// changes we are interested, and later we transform them. This allows use to be able to use a RootBindingContext
4040
// as a bag in which we can add information about libraries and trampolines needed by the bindings.
4141
var provider = context.SyntaxProvider
4242
.CreateSyntaxProvider (static (node, _) => IsValidNode (node),
4343
static (ctx, _) => GetChangesForSourceGen (ctx))
4444
.Where (tuple => tuple.BindingAttributeFound)
45-
.Select (static (tuple, _) => (tuple.Declaration, tuple.Changes))
45+
.Select (static (tuple, _) => tuple.Changes)
4646
.WithComparer (equalityComparer);
4747

4848
context.RegisterSourceOutput (context.CompilationProvider.Combine (provider.Collect ()),
@@ -59,29 +59,28 @@ public void Initialize (IncrementalGeneratorInitializationContext context)
5959
_ => false,
6060
};
6161

62-
static (BaseTypeDeclarationSyntax Declaration, CodeChanges Changes, bool BindingAttributeFound)
63-
GetChangesForSourceGen (GeneratorSyntaxContext context)
62+
static (CodeChanges Changes, bool BindingAttributeFound) GetChangesForSourceGen (GeneratorSyntaxContext context)
6463
{
6564
// we do know that the context node has to be one of the base type declarations
6665
var declarationSyntax = Unsafe.As<BaseTypeDeclarationSyntax> (context.Node);
6766

6867
// check if we do have the binding attr, else there nothing to retrieve
69-
bool isBindingType = declarationSyntax.HasAttribute (context.SemanticModel, AttributesNames.BindingAttribute);
68+
bool isBindingType = declarationSyntax.HasAtLeastOneAttribute (context.SemanticModel, AttributesNames.BindingTypes);
7069

7170
if (!isBindingType) {
7271
// return empty data + false
73-
return (declarationSyntax, default, false);
72+
return (default, false);
7473
}
7574

7675
var codeChanges = CodeChanges.FromDeclaration (declarationSyntax, context.SemanticModel);
7776
// if code changes are null, return the default value and a false to later ignore the change
7877
return codeChanges is not null
79-
? (declarationSyntax, codeChanges.Value, isBindingType)
80-
: (declarationSyntax, default, false);
78+
? (codeChanges.Value, isBindingType)
79+
: (default, false);
8180
}
8281

8382
static void GenerateCode (SourceProductionContext context, Compilation compilation,
84-
in ImmutableArray<(BaseTypeDeclarationSyntax Declaration, CodeChanges Changes)> changesList)
83+
in ImmutableArray<CodeChanges> changesList)
8584
{
8685
// The process is as follows, get all the changes we have received from the incremental generator,
8786
// loop over them, and based on the CodeChange.BindingType we are going to build the symbol context
@@ -90,15 +89,17 @@ static void GenerateCode (SourceProductionContext context, Compilation compilati
9089
// Once all the enums, classes and interfaces have been processed, we will use the data collected
9190
// in the RootBindingContext to generate the library and trampoline code.
9291
var rootContext = new RootBindingContext (compilation);
93-
foreach (var (declaration, change) in changesList) {
92+
var sb = new TabbedStringBuilder (new ());
93+
foreach (var change in changesList) {
9494
// init sb and add the header
95-
var sb = new TabbedStringBuilder (new ());
95+
sb.Clear ();
9696
sb.WriteHeader ();
97-
if (EmitterFactory.TryCreate (change, rootContext, sb, out var emitter)) {
97+
if (EmitterFactory.TryCreate (change, out var emitter)) {
9898
// write the using statements
99-
CollectUsingStatements (declaration.SyntaxTree, sb, emitter);
99+
CollectUsingStatements (change, sb, emitter);
100100

101-
if (emitter.TryEmit (change, out var diagnostics)) {
101+
var bindingContext = new BindingContext (rootContext, sb, change);
102+
if (emitter.TryEmit (bindingContext, out var diagnostics)) {
102103
// only add a file when we do generate code
103104
var code = sb.ToString ();
104105
var namespacePath = Path.Combine (change.Namespace.ToArray ());
@@ -115,7 +116,7 @@ static void GenerateCode (SourceProductionContext context, Compilation compilati
115116
context.ReportDiagnostic (Diagnostic.Create (
116117
Diagnostics
117118
.RBI0000, // An unexpected error ocurred while processing '{0}'. Please fill a bug report at https://github.com/xamarin/xamarin-macios/issues/new.
118-
declaration.GetLocation (),
119+
null,
119120
change.FullyQualifiedSymbol));
120121
}
121122
}
@@ -149,22 +150,18 @@ static void GenerateLibraryCode (SourceProductionContext context, RootBindingCon
149150
}
150151

151152
/// <summary>
152-
/// Collect the using statements from the class declaration root syntaxt tree and add them to the string builder
153+
/// Collect the using statements from the named ype code changes and add them to the string builder
153154
/// that will be used to generate the code. This way we ensure that we have all the namespaces needed by the
154155
/// generated code.
155156
/// </summary>
156-
/// <param name="tree">Root syntax tree of the base type declaration.</param>
157+
/// <param name="codeChanges">The code changes for a given named type.</param>
157158
/// <param name="sb">String builder that will be used for the generated code.</param>
158159
/// <param name="emitter">The emitter that will generate the code. Provides any extra needed namespace.</param>
159-
static void CollectUsingStatements (SyntaxTree tree, TabbedStringBuilder sb, ICodeEmitter emitter)
160+
static void CollectUsingStatements (in CodeChanges codeChanges, TabbedStringBuilder sb, ICodeEmitter emitter)
160161
{
161162
// collect all using from the syntax tree, add them to a hash to make sure that we don't have duplicates
162163
// and add those usings that we do know we need for bindings.
163-
var usingDirectives = tree.GetRoot ()
164-
.DescendantNodes ()
165-
.OfType<UsingDirectiveSyntax> ()
166-
.Select (d => d.Name!.ToString ()).ToArray ();
167-
var usingDirectivesToKeep = new HashSet<string> (usingDirectives) {
164+
var usingDirectivesToKeep = new SortedSet<string> (codeChanges.UsingDirectives) {
168165
// add the using statements that we know we need and print them to the sb
169166
};
170167

@@ -174,7 +171,7 @@ static void CollectUsingStatements (SyntaxTree tree, TabbedStringBuilder sb, ICo
174171
}
175172

176173
// add them sorted so that we have testeable generated code
177-
foreach (var ns in usingDirectivesToKeep.OrderBy (s => s)) {
174+
foreach (var ns in usingDirectivesToKeep) {
178175
if (string.IsNullOrEmpty (ns))
179176
continue;
180177
sb.AppendLine ($"using {ns};");

src/rgen/Microsoft.Macios.Generator/ListComparer.cs renamed to src/rgen/Microsoft.Macios.Generator/CollectionComparer.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44

55
namespace Microsoft.Macios.Generator;
66

7-
public class ListComparer<T> : EqualityComparer<IList<T>> {
7+
public class CollectionComparer<T> : EqualityComparer<IReadOnlyCollection<T>> {
88
readonly IComparer<T>? comparer;
99
readonly IEqualityComparer<T> valueComparer;
1010

11-
public ListComparer (IComparer<T>? sortComparer = null, IEqualityComparer<T>? equalityComparer = null)
11+
public CollectionComparer (IComparer<T>? sortComparer = null, IEqualityComparer<T>? equalityComparer = null)
1212
{
1313
comparer = sortComparer;
1414
valueComparer = equalityComparer ?? EqualityComparer<T>.Default;
1515
}
1616

1717
/// <inheritdoc/>
18-
public override bool Equals (IList<T>? x, IList<T>? y)
18+
public override bool Equals (IReadOnlyCollection<T>? x, IReadOnlyCollection<T>? y)
1919
{
2020
// bases cases for null or diff size
2121
if (x is null && y is null)
@@ -42,7 +42,7 @@ public override bool Equals (IList<T>? x, IList<T>? y)
4242
}
4343

4444
/// <inheritdoc/>
45-
public override int GetHashCode (IList<T> obj)
45+
public override int GetHashCode (IReadOnlyCollection<T> obj)
4646
{
4747
var hash = new HashCode ();
4848
foreach (var element in obj) {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.Macios.Generator.DataModel;
2+
3+
namespace Microsoft.Macios.Generator.Context;
4+
5+
readonly struct BindingContext {
6+
7+
/// <summary>
8+
/// The root context of the current binding operation.
9+
/// </summary>
10+
public RootBindingContext RootContext { get; }
11+
12+
/// <summary>
13+
/// Tabbed string builder that can be used to write the generated code.
14+
/// </summary>
15+
public TabbedStringBuilder Builder { get; }
16+
17+
/// <summary>
18+
/// Current code changes for the binding context.
19+
/// </summary>
20+
public CodeChanges Changes { get; }
21+
22+
public BindingContext (RootBindingContext rootContext, TabbedStringBuilder builder, CodeChanges changes)
23+
{
24+
RootContext = rootContext;
25+
Builder = builder;
26+
Changes = changes;
27+
}
28+
29+
}

src/rgen/Microsoft.Macios.Generator/DataModel/Accessor.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Text;
55
using Microsoft.CodeAnalysis;
6+
using Microsoft.Macios.Generator.Attributes;
67
using Microsoft.Macios.Generator.Availability;
78

89
namespace Microsoft.Macios.Generator.DataModel;
@@ -18,6 +19,11 @@ namespace Microsoft.Macios.Generator.DataModel;
1819
/// </summary>
1920
public SymbolAvailability SymbolAvailability { get; }
2021

22+
/// <summary>
23+
/// The data of the field attribute used to mark the value as a property binding.
24+
/// </summary>
25+
public ExportData<ObjCBindings.Property>? ExportPropertyData { get; init; }
26+
2127
/// <summary>
2228
/// List of attribute code changes of the accessor.
2329
/// </summary>
@@ -33,13 +39,18 @@ namespace Microsoft.Macios.Generator.DataModel;
3339
/// </summary>
3440
/// <param name="accessorKind">The kind of accessor.</param>
3541
/// <param name="symbolAvailability">The os availability of the symbol.</param>
42+
/// <param name="exportPropertyData">The data of the export attribute found in the accessor.</param>
3643
/// <param name="attributes">The list of attributes attached to the accessor.</param>
3744
/// <param name="modifiers">The list of visibility modifiers of the accessor.</param>
38-
public Accessor (AccessorKind accessorKind, SymbolAvailability symbolAvailability, ImmutableArray<AttributeCodeChange> attributes,
45+
public Accessor (AccessorKind accessorKind,
46+
SymbolAvailability symbolAvailability,
47+
ExportData<ObjCBindings.Property>? exportPropertyData,
48+
ImmutableArray<AttributeCodeChange> attributes,
3949
ImmutableArray<SyntaxToken> modifiers)
4050
{
4151
Kind = accessorKind;
4252
SymbolAvailability = symbolAvailability;
53+
ExportPropertyData = exportPropertyData;
4354
Attributes = attributes;
4455
Modifiers = modifiers;
4556
}
@@ -51,6 +62,8 @@ public bool Equals (Accessor other)
5162
return false;
5263
if (SymbolAvailability != other.SymbolAvailability)
5364
return false;
65+
if (ExportPropertyData != other.ExportPropertyData)
66+
return false;
5467

5568
var attrsComparer = new AttributesEqualityComparer ();
5669
if (!attrsComparer.Equals (Attributes, other.Attributes))
@@ -68,7 +81,7 @@ public override bool Equals (object? obj)
6881
/// <inheritdoc />
6982
public override int GetHashCode ()
7083
{
71-
return HashCode.Combine ((int) Kind, Attributes, Modifiers);
84+
return HashCode.Combine ((int) Kind, SymbolAvailability, ExportPropertyData, Attributes, Modifiers);
7285
}
7386

7487
public static bool operator == (Accessor left, Accessor right)
@@ -84,7 +97,7 @@ public override int GetHashCode ()
8497
/// <inheritdoc />
8598
public override string ToString ()
8699
{
87-
var sb = new StringBuilder ($"{{ Kind: {Kind}, Supported Platforms: {SymbolAvailability} Modifiers: [");
100+
var sb = new StringBuilder ($"{{ Kind: {Kind}, Supported Platforms: {SymbolAvailability}, ExportData: {ExportPropertyData?.ToString () ?? "null"} Modifiers: [");
88101
sb.AppendJoin (",", Modifiers.Select (x => x.Text));
89102
sb.Append ("], Attributes: [");
90103
sb.AppendJoin (", ", Attributes);

0 commit comments

Comments
 (0)