Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb11b39c

Browse files
mandel-macaqueGitHub Actions Autoformatter
and
GitHub Actions Autoformatter
authored
[RGen] Add support for the generation of constructors. (#23341)
This commit adds support to generate the constructors of a class. Thiscomes with some extra changes to take a look at:1. Constructor formatter: It now takes an extra parameter that can beused to state the addition of calling base (NSObjectFlag.Empty).2. Fixed the messsage send generation to use the this.SuperHandle. Wehad a bug and we were generating the super call with the this.Handle.3. Update all tests according to the changes for the super calls.4. Added the constructor generation in the class emitter.We still have to correctly add the Skip method for the constructors thatare not partial. This will need to be added in the net10.0 branch inwhich we will have partial constructors.---------Co-authored-by: GitHub Actions Autoformatter <github-actions-autoformatter@xamarin.com>
1 parent758a1d4 commitb11b39c

File tree

36 files changed

+1033
-302
lines changed

36 files changed

+1033
-302
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ static class AttributesNames {
2121
publicconststringFieldPropertyAttribute="ObjCBindings.FieldAttribute<ObjCBindings.Property>";
2222
publicconststringExportPropertyAttribute="ObjCBindings.ExportAttribute<ObjCBindings.Property>";
2323
publicconststringExportMethodAttribute="ObjCBindings.ExportAttribute<ObjCBindings.Method>";
24+
publicconststringExportConstructorAttribute="ObjCBindings.ExportAttribute<ObjCBindings.Constructor>";
2425
publicconststringSupportedOSPlatformAttribute="System.Runtime.Versioning.SupportedOSPlatformAttribute";
2526
publicconststringUnsupportedOSPlatformAttribute="System.Runtime.Versioning.UnsupportedOSPlatformAttribute";
2627
publicconststringObsoletedOSPlatformAttribute="System.Runtime.Versioning.ObsoletedOSPlatformAttribute";
@@ -84,6 +85,9 @@ static class AttributesNames {
8485
if(type==typeof(ObjCBindings.Method)){
8586
returnExportMethodAttribute;
8687
}
88+
if(type==typeof(ObjCBindings.Constructor)){
89+
returnExportConstructorAttribute;
90+
}
8791
returnnull;
8892
}
8993

‎src/rgen/Microsoft.Macios.Generator/DataModel/Constructor.Generator.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
usingMicrosoft.CodeAnalysis;
77
usingMicrosoft.CodeAnalysis.CSharp.Syntax;
88
usingMicrosoft.Macios.Generator.Attributes;
9+
usingMicrosoft.Macios.Generator.Availability;
910
usingMicrosoft.Macios.Generator.Context;
1011
usingMicrosoft.Macios.Generator.Extensions;
12+
usingObjCRuntime;
1113

1214
namespaceMicrosoft.Macios.Generator.DataModel;
1315

@@ -23,6 +25,21 @@ readonly partial struct Constructor {
2325
/// </summary>
2426
publicstring?Selector=>ExportMethodData.Selector;
2527

28+
publicConstructor(stringtype,
29+
SymbolAvailabilitysymbolAvailability,
30+
ExportData<ObjCBindings.Constructor>exportData,
31+
ImmutableArray<AttributeCodeChange>attributes,
32+
ImmutableArray<SyntaxToken>modifiers,
33+
ImmutableArray<Parameter>parameters)
34+
{
35+
Type=type;
36+
SymbolAvailability=symbolAvailability;
37+
ExportMethodData=exportData;
38+
Attributes=attributes;
39+
Modifiers=modifiers;
40+
Parameters=parameters;
41+
}
42+
2643
publicstaticboolTryCreate(ConstructorDeclarationSyntaxdeclaration,RootContextcontext,
2744
[NotNullWhen(true)]outConstructor?change)
2845
{
@@ -41,9 +58,13 @@ public static bool TryCreate (ConstructorDeclarationSyntax declaration, RootCont
4158
parametersBucket.Add(parameterChange.Value);
4259
}
4360

61+
varexportData=constructor.GetExportData<ObjCBindings.Constructor>()
62+
??new(null,ArgumentSemantic.None,ObjCBindings.Constructor.Default);
63+
4464
change=new(
4565
type:constructor.ContainingSymbol.Name,// we DO NOT want the full name
4666
symbolAvailability:constructor.GetSupportedPlatforms(),
67+
exportData:exportData,
4768
attributes:attributes,
4869
modifiers:[..declaration.Modifiers],
4970
parameters:parametersBucket.ToImmutable());

‎src/rgen/Microsoft.Macios.Generator/DataModel/TypeInfo.cs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,16 @@ namespace Microsoft.Macios.Generator.DataModel;
1919
[StructLayout(LayoutKind.Auto)]
2020
readonlypartialstructTypeInfo:IEquatable<TypeInfo>{
2121

22+
/// <summary>
23+
/// Represents the `void` type.
24+
/// </summary>
2225
publicstaticTypeInfoVoid=new("void",SpecialType.System_Void){Parents=["System.ValueType","object"],};
2326

27+
/// <summary>
28+
/// Represents a `System.NativeHandle` type.
29+
/// </summary>
30+
publicstaticTypeInfoNativeHandle=new("System.NativeHandle",SpecialType.System_IntPtr){Parents=["System.ValueType","object"],};
31+
2432
/// <summary>
2533
/// The fully qualified name of the type.
2634
/// </summary>
@@ -509,26 +517,26 @@ public override int GetHashCode ()
509517
return!left.Equals(right);
510518
}
511519

512-
conststringNativeHandle="NativeHandle";
513-
conststringIntPtr="IntPtr";
514-
conststringUIntPtr="UIntPtr";
520+
conststringNativeHandleString="NativeHandle";
521+
conststringIntPtrString="IntPtr";
522+
conststringUIntPtrString="UIntPtr";
515523

516524
publicstring?ToMarshallType()
517525
{
518526
#pragma warning disableformat
519527
vartype=thisswitch{
520528
// arrays
521-
{IsArray:true}=>NativeHandle,
529+
{IsArray:true}=>NativeHandleString,
522530

523531
// special cases based on name
524532
{Name:"nfloat" or"NFloat"}=>"nfloat",
525533
{Name:"nint" or"nuint"}=>MetadataName,
526534
// special string case
527-
{SpecialType:SpecialType.System_String}=>NativeHandle,// use a NSString when we get a string
535+
{SpecialType:SpecialType.System_String}=>NativeHandleString,// use a NSString when we get a string
528536

529537
// NSObject should use the native handle
530-
{IsNSObject:true}=>NativeHandle,
531-
{IsINativeObject:true}=>NativeHandle,
538+
{IsNSObject:true}=>NativeHandleString,
539+
{IsINativeObject:true}=>NativeHandleString,
532540

533541
// structs will use their name
534542
{IsStruct:true,SpecialType:SpecialType.System_Double}=>"Double",
@@ -539,9 +547,9 @@ public override int GetHashCode ()
539547
// IsNativeEnum: Depends on the enum backing field kind.
540548
// GeneralEnum: Depends on the EnumUnderlyingType
541549

542-
{IsNativeEnum:true,EnumUnderlyingType:SpecialType.System_Int64}=>IntPtr,
543-
{IsNativeEnum:true,EnumUnderlyingType:SpecialType.System_UInt64}=>UIntPtr,
544-
{IsSmartEnum:true}=>NativeHandle,
550+
{IsNativeEnum:true,EnumUnderlyingType:SpecialType.System_Int64}=>IntPtrString,
551+
{IsNativeEnum:true,EnumUnderlyingType:SpecialType.System_UInt64}=>UIntPtrString,
552+
{IsSmartEnum:true}=>NativeHandleString,
545553
{IsEnum:true,EnumUnderlyingType: notnull}=>EnumUnderlyingType.GetKeyword(),
546554

547555
// special type that is a keyword (none would be a ref type)
@@ -552,7 +560,7 @@ public override int GetHashCode ()
552560
{IsReferenceType:false}=>Name,
553561

554562
// delegates will use the native handle
555-
{IsDelegate:true}=>NativeHandle,
563+
{IsDelegate:true}=>NativeHandleString,
556564

557565
_=>null,
558566
};
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
usingSystem.Collections.Generic;
5+
usingSystem.Collections.Immutable;
6+
usingMicrosoft.CodeAnalysis;
7+
usingMicrosoft.CodeAnalysis.CSharp;
8+
usingMicrosoft.CodeAnalysis.CSharp.Syntax;
9+
usingMicrosoft.Macios.Generator.DataModel;
10+
usingMicrosoft.Macios.Generator.Extensions;
11+
usingstaticMicrosoft.CodeAnalysis.CSharp.SyntaxFactory;
12+
usingTypeInfo=Microsoft.Macios.Generator.DataModel.TypeInfo;
13+
14+
namespaceMicrosoft.Macios.Generator.Emitters;
15+
16+
staticpartialclassBindingSyntaxFactory{
17+
18+
/// <summary>
19+
/// Generates an invocation to the `InitializeHandle` method.
20+
/// </summary>
21+
/// <param name="arguments">The arguments to pass to the `InitializeHandle` method.</param>
22+
/// <returns>An invocation expression syntax.</returns>
23+
internalstaticExpressionSyntaxInitializeHandle(inImmutableArray<ArgumentSyntax>arguments)
24+
{
25+
varargumentList=ArgumentList(
26+
SeparatedList<ArgumentSyntax>(arguments.ToSyntaxNodeOrTokenArray()));
27+
returnInvocationExpression(
28+
IdentifierName("InitializeHandle").WithTrailingTrivia(Space)).WithArgumentList(argumentList);
29+
}
30+
31+
/// <summary>
32+
/// Generates the `objc_msgSend` invocation for a constructor.
33+
/// </summary>
34+
/// <param name="constructor">The constructor information.</param>
35+
/// <param name="arguments">The arguments to pass to the constructor.</param>
36+
/// <param name="isSuper">A value indicating whether to call the base implementation (`super`).</param>
37+
/// <returns>An expression syntax representing the `objc_msgSend` invocation.</returns>
38+
internalstaticExpressionSyntaxGetSendInvocation(inConstructorconstructor,
39+
inImmutableArray<ArgumentSyntax>arguments,boolisSuper)
40+
{
41+
varsend=GetObjCMessageSendMethodName(
42+
exportData:constructor.ExportMethodData,
43+
returnType:TypeInfo.NativeHandle,// constructors always return an native handle
44+
parameters:constructor.Parameters,
45+
isSuper:isSuper,
46+
isStret:false// we do not need to stret for constructors since we are always getting a handle
47+
);
48+
if(sendisnull||constructor.ExportMethodData.Selectorisnull){
49+
returnThrowNotImplementedException();
50+
}
51+
// return the call to the InitializeHandle method, which will take the execution of the send method and the
52+
// selector
53+
returnInitializeHandle(
54+
[
55+
Argument(MessagingInvocation(send,constructor.ExportMethodData.Selector,arguments,isSuper)),
56+
GetLiteralExpressionArgument(SyntaxKind.StringLiteralExpression,constructor.ExportMethodData.Selector)
57+
]
58+
);
59+
}
60+
61+
/// <summary>
62+
/// Generates the method invocations for a given constructor.
63+
/// </summary>
64+
/// <param name="constructor">The constructor for which to generate invocations.</param>
65+
/// <returns>A <see cref="MethodInvocations"/> object containing the generated syntax for the constructor.</returns>
66+
internalstaticMethodInvocationsGetInvocations(inConstructorconstructor)
67+
{
68+
varconversions=newPriorityQueue<ArgumentConversions,ArgumentInfo>(newArgumentInfoConversionComparer());
69+
varargumentSyntax=ImmutableArray.CreateBuilder<ArgumentSyntax>(constructor.Parameters.Length);
70+
foreach(varparaminconstructor.Parameters){
71+
vartrampolineSyntax=newArgumentConversions{
72+
Initializers=GetNativeInvokeArgumentInitializations(param),
73+
Validations=GetNativeInvokeArgumentValidations(param),
74+
PreCallConversion=GetPreNativeInvokeArgumentConversions(param),
75+
PostCallConversion=GetPostNativeInvokeArgumentConversions(param),
76+
};
77+
conversions.Enqueue(trampolineSyntax,param);
78+
argumentSyntax.Add(GetNativeInvokeArgument(param));
79+
}
80+
81+
// calculate the send expressions, we use the export data information to determine the selector
82+
varargs=argumentSyntax.ToImmutable();
83+
returnnewMethodInvocations(){
84+
Arguments=conversions.ToImmutable(),
85+
Send=GetSendInvocation(constructor,args,false),
86+
SendSuper=GetSendInvocation(constructor,args,true)
87+
};
88+
}
89+
}

‎src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Methods.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ internal static ExpressionSyntax GetSendInvocation (in Method method,
197197
if(sendisnull||method.ExportMethodData.Selectorisnull){
198198
returnThrowNotImplementedException();
199199
}
200-
varinvocation=MessagingInvocation(send,method.ExportMethodData.Selector,arguments);
200+
varinvocation=MessagingInvocation(send,method.ExportMethodData.Selector,arguments,isSuper);
201201
if(method.ReturnType.IsVoid)
202202
returninvocation;
203203
// we need to convert the return type to the managed type and assign it to the return variable

‎src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Property.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ internal static (ExpressionSyntax Send, ExpressionSyntax SendSuper) GetGetterInv
7171
return(ThrowNotImplementedException(),ThrowNotImplementedException());
7272
}
7373

74-
vargetterSend=ConvertToManaged(property,MessagingInvocation(sendMethod,selector,[]));
75-
vargetterSuperSend=ConvertToManaged(property,MessagingInvocation(superSendMethod,selector,[]));
74+
vargetterSend=ConvertToManaged(property,MessagingInvocation(sendMethod,selector,[],isSuper:false));
75+
vargetterSuperSend=ConvertToManaged(property,MessagingInvocation(superSendMethod,selector,[],isSuper:true));
7676
// if we cannot get the methods, throw a runtime exception
7777
if(getterSendisnull||getterSuperSendisnull){
7878
return(ThrowNotImplementedException(),ThrowNotImplementedException());
@@ -108,8 +108,8 @@ internal static (ArgumentConversions Argument, ExpressionSyntax Send, Expression
108108
return(argument,ThrowNotImplementedException(),ThrowNotImplementedException());
109109
}
110110

111-
varsetterSend=MessagingInvocation(sendMethod,selector,[syntax]);
112-
varsetterSuperSend=MessagingInvocation(superSendMethod,selector,[syntax]);
111+
varsetterSend=MessagingInvocation(sendMethod,selector,[syntax],isSuper:false);
112+
varsetterSuperSend=MessagingInvocation(superSendMethod,selector,[syntax],isSuper:true);
113113

114114
return(
115115
Argument:argument,

‎src/rgen/Microsoft.Macios.Generator/Emitters/BindingSyntaxFactory.Runtime.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,28 @@ public static MemberAccessExpressionSyntax ThisHandle ()
9999
IdentifierName("Handle"));
100100
}
101101

102+
/// <summary>
103+
/// Generates the "this.SuperHandle" expression.
104+
/// </summary>
105+
/// <returns></returns>
106+
publicstaticMemberAccessExpressionSyntaxThisSuperHandle()
107+
{
108+
returnMemberAccessExpression(
109+
SyntaxKind.SimpleMemberAccessExpression,
110+
ThisExpression(),
111+
IdentifierName("SuperHandle"));
112+
}
113+
102114
/// <summary>
103115
/// Generates the expression to call the objc_msgSend method.
104116
/// </summary>
105117
/// <param name="objcMsgSendMethod">The name of the method in the messaging namespace.</param>
106118
/// <param name="selector">The selector.</param>
107119
/// <param name="parameters">An optional argument list.</param>
120+
/// <param name="isSuper">A value indicating whether to call the base implementation (`super`).</param>
108121
/// <returns>The expression needed to call a specific messaging method.</returns>
109122
publicstaticInvocationExpressionSyntaxMessagingInvocation(stringobjcMsgSendMethod,stringselector,
110-
ImmutableArray<ArgumentSyntax>parameters)
123+
ImmutableArray<ArgumentSyntax>parameters,boolisSuper)
111124
{
112125
// the size of the arguments is 2 + the optional arguments
113126
// [0] = the handle
@@ -118,7 +131,7 @@ public static InvocationExpressionSyntax MessagingInvocation (string objcMsgSend
118131
varparametersCount=2+parameters.Length;
119132
varargs=newSyntaxNodeOrToken[(2*parametersCount)-1];
120133
// the first two arguments are the selector and the handle, we add those by hand
121-
args[0]=Argument(ThisHandle());
134+
args[0]=Argument(isSuper?ThisSuperHandle():ThisHandle());
122135
args[1]=Token(SyntaxKind.CommaToken).WithTrailingTrivia(Space);
123136
args[2]=Argument(SelectorGetHandle(selector));
124137

‎src/rgen/Microsoft.Macios.Generator/Emitters/ClassEmitter.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
usingObjCBindings;
1717
usingstaticMicrosoft.Macios.Generator.Emitters.BindingSyntaxFactory;
1818
usingstaticMicrosoft.CodeAnalysis.CSharp.SyntaxFactory;
19+
usingConstructor=ObjCBindings.Constructor;
1920
usingMethod=Microsoft.Macios.Generator.DataModel.Method;
2021
usingProperty=Microsoft.Macios.Generator.DataModel.Property;
2122

@@ -69,6 +70,47 @@ void EmitDefaultConstructors (in BindingContext bindingContext, TabbedWriter<Str
6970
classBlock.WriteLine($"protected internal{bindingContext.Changes.Name} ({NativeHandle} handle) : base (handle) {{}}");
7071
}
7172

73+
voidEmitConstructors(inBindingContextcontext,TabbedWriter<StringWriter>classBlock)
74+
{
75+
// When dealing with constructors we cannot sort them by name because the name is always the same as the class
76+
// instead we will sort them by the selector name so that we will always generate the constructors in the same order
77+
foreach(varconstructorincontext.Changes.Constructors.OrderBy(c=>c.ExportMethodData.Selector)){
78+
classBlock.WriteLine();
79+
classBlock.AppendMemberAvailability(constructor.SymbolAvailability);
80+
classBlock.AppendGeneratedCodeAttribute(optimizable:true);
81+
if(constructor.ExportMethodData.Flags.HasFlag(Constructor.DesignatedInitializer)){
82+
classBlock.AppendDesignatedInitializer();
83+
}
84+
85+
using(varconstructorBlock=classBlock.CreateBlock(constructor.ToDeclaration(withBaseNSFlag:true).ToString(),block:true)){
86+
// retrieve the method invocation via the factory, this will generate the necessary arguments
87+
// transformations and the invocation
88+
varinvocations=GetInvocations(constructor);
89+
90+
// init the needed temp variables
91+
foreach(varargumentininvocations.Arguments){
92+
constructorBlock.Write(argument.Validations,verifyTrivia:false);
93+
constructorBlock.Write(argument.Initializers,verifyTrivia:false);
94+
constructorBlock.Write(argument.PreCallConversion,verifyTrivia:false);
95+
}
96+
97+
// simply call the send or sendSuper accordingly
98+
constructorBlock.WriteRaw(
99+
$@"if (IsDirectBinding) {{
100+
{ExpressionStatement(invocations.Send)}
101+
}} else {{
102+
{ExpressionStatement(invocations.SendSuper)}
103+
}}
104+
");
105+
106+
// before we leave the methods, do any post operations
107+
foreach(varargumentininvocations.Arguments){
108+
constructorBlock.Write(argument.PostCallConversion,verifyTrivia:false);
109+
}
110+
}
111+
}
112+
}
113+
72114
/// <summary>
73115
/// Emit the code for all the field properties in the class. The code will add any necessary backing fields and
74116
/// will return all properties that are notifications.
@@ -554,6 +596,9 @@ public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out
554596
EmitDefaultConstructors(bindingContext:bindingContext,
555597
classBlock:classBlock,
556598
disableDefaultCtor:bindingData.Flags.HasFlag(ObjCBindings.Class.DisableDefaultCtor));
599+
600+
// emit any other constructor that is not the default one
601+
EmitConstructors(bindingContext,classBlock);
557602
}
558603

559604
EmitFields(bindingContext.Changes.Name,bindingContext.Changes.Properties,classBlock,
@@ -563,7 +608,6 @@ public bool TryEmit (in BindingContext bindingContext, [NotNullWhen (false)] out
563608

564609
// emit the notification helper classes, leave this for the very bottom of the class
565610
EmitNotifications(notificationProperties,classBlock);
566-
classBlock.WriteLine("// TODO: add binding code here");
567611
}
568612
returntrue;
569613
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp