Skip to content

Commit 23435c2

Browse files
mandel-macaqueCopilotGitHub Actions Autoformatter
authored
[RGen] Implement the basic Wrapper implementation. (#23462)
Add the Protocol Wrapper class definition. Do not generate methods or properties yet, do that in follow up PRs because we need changes in the property and method emitters. --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com>
1 parent f4e2c1f commit 23435c2

File tree

8 files changed

+226
-6
lines changed

8 files changed

+226
-6
lines changed

src/rgen/Microsoft.Macios.Generator/Emitters/EmitterFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ static class EmitterFactory {
1414
static readonly Dictionary<BindingType, ICodeEmitter> emitters = new () {
1515
{ BindingType.Class, new ClassEmitter () },
1616
{ BindingType.SmartEnum, new EnumEmitter () },
17-
{ BindingType.Protocol, new ProtocolEmitter () },
17+
{ BindingType.Protocol, new ProtocolAndModelEmitter () },
1818
{ BindingType.Category, new CategoryEmitter () },
1919
{ BindingType.StrongDictionary, new StrongDictionaryEmitter () },
2020
{ BindingType.StrongDictionaryKeys, new StrongDictionaryKeysEmitter () }
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using System.Collections.Immutable;
6+
using System.Diagnostics.CodeAnalysis;
7+
using Microsoft.CodeAnalysis;
8+
using Microsoft.Macios.Generator.Context;
9+
using Microsoft.Macios.Generator.DataModel;
10+
11+
namespace Microsoft.Macios.Generator.Emitters;
12+
13+
/// <summary>
14+
/// An emitter that combines the functionality of <see cref="ProtocolEmitter"/> and <see cref="ProtocolWrapperEmitter"/>
15+
/// to emit both the protocol interface and its corresponding wrapper class.
16+
/// </summary>
17+
class ProtocolAndModelEmitter : ICodeEmitter {
18+
readonly ProtocolEmitter protocolEmitter = new ();
19+
readonly ProtocolWrapperEmitter protocolWrapperEmitter = new ();
20+
21+
/// <inheritdoc />
22+
public string GetSymbolName (in Binding binding) => protocolEmitter.GetSymbolName (binding);
23+
24+
/// <inheritdoc />
25+
public IEnumerable<string> UsingStatements {
26+
get {
27+
foreach (var ns in protocolEmitter.UsingStatements) {
28+
yield return ns;
29+
}
30+
foreach (var ns in protocolWrapperEmitter.UsingStatements) {
31+
yield return ns;
32+
}
33+
}
34+
}
35+
36+
/// <inheritdoc />
37+
public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out ImmutableArray<Diagnostic>? diagnostics)
38+
{
39+
// try to emit the protocol first
40+
if (!protocolEmitter.TryEmit (bindingContext, out diagnostics)) {
41+
return false;
42+
}
43+
44+
// add space and add the wrapper emitter
45+
bindingContext.Builder.WriteLine ();
46+
47+
if (!protocolWrapperEmitter.TryEmit (bindingContext, out diagnostics)) {
48+
return false;
49+
}
50+
51+
return true;
52+
}
53+
54+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System.Collections.Generic;
5+
using System.Collections.Immutable;
6+
using System.Diagnostics.CodeAnalysis;
7+
using System.IO;
8+
using System.Linq;
9+
using Microsoft.CodeAnalysis;
10+
using Microsoft.Macios.Generator.Attributes;
11+
using Microsoft.Macios.Generator.Context;
12+
using Microsoft.Macios.Generator.DataModel;
13+
using Microsoft.Macios.Generator.IO;
14+
using ObjCBindings;
15+
16+
namespace Microsoft.Macios.Generator.Emitters;
17+
18+
/// <summary>
19+
/// Emits the wrapper class for a protocol.
20+
/// </summary>
21+
class ProtocolWrapperEmitter : ICodeEmitter {
22+
/// <inheritdoc />
23+
public string GetSymbolName (in Binding binding) => Nomenclator.GetProtocolWrapperName (binding.Name);
24+
25+
/// <inheritdoc />
26+
public IEnumerable<string> UsingStatements { get; } = [];
27+
28+
/// <summary>
29+
/// Emits the default constructors for the protocol wrapper class.
30+
/// </summary>
31+
/// <param name="bindingContext">The binding context.</param>
32+
/// <param name="classBlock">The writer for the class block.</param>
33+
void EmitDefaultConstructors (in BindingContext bindingContext, TabbedWriter<StringWriter> classBlock)
34+
{
35+
classBlock.WriteLine ("// Implement default constructor");
36+
classBlock.WriteLine ();
37+
}
38+
39+
/// <summary>
40+
/// Emits the properties for the protocol wrapper class.
41+
/// </summary>
42+
/// <param name="context">The binding context.</param>
43+
/// <param name="classBlock">The writer for the class block.</param>
44+
void EmitProperties (in BindingContext context, TabbedWriter<StringWriter> classBlock)
45+
{
46+
var allProperties = context.Changes.Properties
47+
.Concat (context.Changes.ParentProtocolProperties)
48+
.OrderBy (p => p.Name);
49+
50+
foreach (var property in allProperties) {
51+
classBlock.WriteLine ($"// Implement property: {property.Name}");
52+
classBlock.WriteLine ();
53+
}
54+
}
55+
56+
/// <summary>
57+
/// Emits the methods for the protocol wrapper class.
58+
/// </summary>
59+
/// <param name="context">The binding context.</param>
60+
/// <param name="classBlock">The writer for the class block.</param>
61+
void EmitMethods (in BindingContext context, TabbedWriter<StringWriter> classBlock)
62+
{
63+
var allMethods = context.Changes.Methods
64+
.Concat (context.Changes.ParentProtocolMethods)
65+
.OrderBy (m => m.Name);
66+
67+
foreach (var method in allMethods) {
68+
classBlock.WriteLine ($"// Implement method: {method.Name}");
69+
classBlock.WriteLine ();
70+
}
71+
}
72+
73+
/// <inheritdoc />
74+
public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out ImmutableArray<Diagnostic>? diagnostics)
75+
{
76+
diagnostics = null;
77+
var bindingData = (BindingTypeData<Protocol>) bindingContext.Changes.BindingInfo;
78+
var protocolName = bindingData.Name ?? bindingContext.Changes.Name [1..];
79+
var wrapperName = Nomenclator.GetProtocolWrapperName (protocolName);
80+
81+
// we do not emit outer classes for protocol wrappers
82+
using (var classBlock = bindingContext.Builder.CreateBlock (
83+
$"internal unsafe sealed class {wrapperName} : BaseWrapper, {bindingContext.Changes.Name}",
84+
true)) {
85+
EmitDefaultConstructors (bindingContext, classBlock);
86+
EmitProperties (bindingContext, classBlock);
87+
EmitMethods (bindingContext, classBlock);
88+
}
89+
90+
return true;
91+
}
92+
93+
}

tests/rgen/Microsoft.Macios.Generator.Tests/Emitters/EmitterFactoryTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ public interface ITestInterface {
145145
";
146146
var changes = CreateSymbol<InterfaceDeclarationSyntax> (platform, inputText);
147147
Assert.True (EmitterFactory.TryCreate (changes, out var emitter));
148-
Assert.IsType<ProtocolEmitter> (emitter);
148+
Assert.IsType<ProtocolAndModelEmitter> (emitter);
149149
Assert.True (EmitterFactory.TryCreate (changes, out var secondEmitter));
150150
Assert.Same (emitter, secondEmitter);
151151
}

tests/rgen/Microsoft.Macios.Generator.Tests/Protocols/Data/ExpectedIAVAudio3DMixing.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,3 +346,23 @@ internal static void _SetSourceMode (this IAVAudio3DMixing self, global::AVFound
346346
set => _SetSourceMode (this, value);
347347
}
348348
}
349+
350+
internal unsafe sealed class AVAudio3DMixingWrapper : BaseWrapper, IAVAudio3DMixing
351+
{
352+
// Implement default constructor
353+
354+
// Implement property: Obstruction
355+
356+
// Implement property: Occlusion
357+
358+
// Implement property: PointSourceInHeadMode
359+
360+
// Implement property: Rate
361+
362+
// Implement property: RenderingAlgorithm
363+
364+
// Implement property: ReverbBlend
365+
366+
// Implement property: SourceMode
367+
368+
}

tests/rgen/Microsoft.Macios.Generator.Tests/Protocols/Data/ExpectedIAVAudioMixing.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,3 +97,27 @@ public virtual partial float Volume
9797
throw new global::Foundation.You_Should_Not_Call_base_In_This_Method ();
9898
}
9999
}
100+
101+
internal unsafe sealed class AVAudioMixingWrapper : BaseWrapper, IAVAudioMixing
102+
{
103+
// Implement default constructor
104+
105+
// Implement property: Obstruction
106+
107+
// Implement property: Occlusion
108+
109+
// Implement property: PointSourceInHeadMode
110+
111+
// Implement property: Rate
112+
113+
// Implement property: RenderingAlgorithm
114+
115+
// Implement property: ReverbBlend
116+
117+
// Implement property: SourceMode
118+
119+
// Implement property: Volume
120+
121+
// Implement method: DestinationForMixer
122+
123+
}

tests/rgen/Microsoft.Macios.Generator.Tests/Protocols/Data/IAVAudioMixing.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,36 @@ namespace Microsoft.Macios.Generator.Tests.Protocols.Data;
1313
[SupportedOSPlatform ("macos")]
1414
[SupportedOSPlatform ("maccatalyst13.1")]
1515
[BindingType<Protocol>]
16-
public partial interface IAVAudioMixing {
16+
public interface IAVAudio3DMixing {
17+
18+
[Export<Property> ("renderingAlgorithm")]
19+
public virtual partial AVAudio3DMixingRenderingAlgorithm RenderingAlgorithm { get; set; }
20+
21+
[Export<Property> ("rate")]
22+
public virtual partial float Rate { get; set; }
23+
24+
[Export<Property> ("reverbBlend")]
25+
public virtual partial float ReverbBlend { get; set; }
26+
27+
[Export<Property> ("obstruction")]
28+
public virtual partial float Obstruction { get; set; }
29+
30+
[Export<Property> ("occlusion")]
31+
public virtual partial float Occlusion { get; set; }
32+
33+
[Export<Property> ("sourceMode", ArgumentSemantic.Assign)]
34+
public virtual partial AVAudio3DMixingSourceMode SourceMode { get; set; }
35+
36+
[Export<Property> ("pointSourceInHeadMode", ArgumentSemantic.Assign)]
37+
public virtual partial AVAudio3DMixingPointSourceInHeadMode PointSourceInHeadMode { get; set; }
38+
}
39+
40+
[SupportedOSPlatform ("ios")]
41+
[SupportedOSPlatform ("tvos")]
42+
[SupportedOSPlatform ("macos")]
43+
[SupportedOSPlatform ("maccatalyst13.1")]
44+
[BindingType<Protocol>]
45+
public partial interface IAVAudioMixing : IAVAudio3DMixing {
1746

1847
[Export<Method> ("destinationForMixer:bus:")]
1948
public virtual partial AVAudioMixingDestination? DestinationForMixer (AVAudioNode mixer, nuint bus);

tests/rgen/Microsoft.Macios.Generator.Tests/Protocols/ProtocolGenerationTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ public class TestDataGenerator : BaseTestDataGenerator, IEnumerable<object []> {
1919
(ApplePlatform.MacOSX, "IAVAudio3DMixing", "IAVAudio3DMixing.cs", "ExpectedIAVAudio3DMixing.cs", null),
2020

2121
(ApplePlatform.iOS, "IAVAudioMixing", "IAVAudioMixing.cs", "ExpectedIAVAudioMixing.cs", null),
22-
(ApplePlatform.TVOS, "IAVAudio3DMixing", "IAVAudio3DMixing.cs", "ExpectedIAVAudio3DMixing.cs", null),
23-
(ApplePlatform.MacCatalyst, "IAVAudio3DMixing", "IAVAudio3DMixing.cs", "ExpectedIAVAudio3DMixing.cs", null),
24-
(ApplePlatform.MacOSX, "IAVAudio3DMixing", "IAVAudio3DMixing.cs", "ExpectedIAVAudio3DMixing.cs", null),
22+
(ApplePlatform.TVOS, "IAVAudioMixing", "IAVAudioMixing.cs", "ExpectedIAVAudioMixing.cs", null),
23+
(ApplePlatform.MacCatalyst, "IAVAudioMixing", "IAVAudioMixing.cs", "ExpectedIAVAudioMixing.cs", null),
24+
(ApplePlatform.MacOSX, "IAVAudioMixing", "IAVAudioMixing.cs", "ExpectedIAVAudioMixing.cs", null),
2525
};
2626

2727
public IEnumerator<object []> GetEnumerator ()

0 commit comments

Comments
 (0)