5
5
using Microsoft . CodeAnalysis ;
6
6
using Microsoft . CodeAnalysis . CSharp ;
7
7
using Uno . UI . SourceGenerators . Helpers ;
8
+ using System . Diagnostics ;
8
9
9
10
#if NETFRAMEWORK
10
11
using Uno . SourceGeneration ;
@@ -40,7 +41,7 @@ private class SerializationMethodsGenerator : SymbolVisitor
40
41
private readonly INamedTypeSymbol ? _intPtrSymbol ;
41
42
private readonly INamedTypeSymbol ? _jniHandleOwnershipSymbol ;
42
43
private readonly INamedTypeSymbol ? [ ] ? _javaCtorParams ;
43
- private readonly INamedTypeSymbol ? _panelSymbol ;
44
+
44
45
private const string BaseClassFormat =
45
46
@"// <auto-generated>
46
47
// *************************************************************
@@ -99,7 +100,6 @@ public SerializationMethodsGenerator(GeneratorExecutionContext context)
99
100
_androidViewSymbol = context . Compilation . GetTypeByMetadataName ( "Android.Views.View" ) ;
100
101
_intPtrSymbol = context . Compilation . GetTypeByMetadataName ( "System.IntPtr" ) ;
101
102
_jniHandleOwnershipSymbol = context . Compilation . GetTypeByMetadataName ( "Android.Runtime.JniHandleOwnership" ) ;
102
- _panelSymbol = context . Compilation . GetTypeByMetadataName ( "Windows.UI.Xaml.Controls.Panel" ) ;
103
103
_javaCtorParams = new [ ] { _intPtrSymbol , _jniHandleOwnershipSymbol } ;
104
104
}
105
105
@@ -140,12 +140,10 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
140
140
141
141
if ( isiOSView || ismacOSView )
142
142
{
143
- var nativeCtor = typeSymbol
144
- . GetMethods ( )
145
- . Where ( m => m . MethodKind == MethodKind . Constructor && SymbolEqualityComparer . Default . Equals ( m . Parameters . FirstOrDefault ( ) ? . Type , _intPtrSymbol ) )
146
- . FirstOrDefault ( ) ;
143
+ Func < IMethodSymbol , bool > predicate = m => ! m . Parameters . IsDefaultOrEmpty && SymbolEqualityComparer . Default . Equals ( m . Parameters [ 0 ] . Type , _intPtrSymbol ) ;
144
+ var nativeCtor = GetNativeCtor ( typeSymbol , predicate , considerAllBaseTypes : false ) ;
147
145
148
- if ( nativeCtor == null )
146
+ if ( nativeCtor == null && GetNativeCtor ( typeSymbol . BaseType , predicate , considerAllBaseTypes : true ) != null )
149
147
{
150
148
_context . AddSource (
151
149
HashBuilder . BuildIDFromSymbol ( typeSymbol ) ,
@@ -162,15 +160,10 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
162
160
163
161
if ( isAndroidView )
164
162
{
163
+ Func < IMethodSymbol , bool > predicate = m => m . Parameters . Select ( p => p . Type ) . SequenceEqual ( _javaCtorParams ?? Array . Empty < ITypeSymbol ? > ( ) ) ;
164
+ var nativeCtor = GetNativeCtor ( typeSymbol , predicate , considerAllBaseTypes : false ) ;
165
165
166
- var nativeCtor = typeSymbol
167
- . GetMethods ( )
168
- . Where ( m =>
169
- m . MethodKind == MethodKind . Constructor
170
- && m . Parameters . Select ( p => p . Type ) . SequenceEqual ( _javaCtorParams ?? Array . Empty < ITypeSymbol ? > ( ) ) )
171
- . FirstOrDefault ( ) ;
172
-
173
- if ( nativeCtor == null )
166
+ if ( nativeCtor == null && GetNativeCtor ( typeSymbol . BaseType , predicate , considerAllBaseTypes : true ) != null )
174
167
{
175
168
_context . AddSource (
176
169
HashBuilder . BuildIDFromSymbol ( typeSymbol ) ,
@@ -184,6 +177,32 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
184
177
) ;
185
178
}
186
179
}
180
+
181
+ static IMethodSymbol ? GetNativeCtor ( INamedTypeSymbol ? type , Func < IMethodSymbol , bool > predicate , bool considerAllBaseTypes )
182
+ {
183
+ // Consider:
184
+ // Type A -> Type B -> Type C
185
+ // HasCtor NoCtor NoCtor
186
+ // We want to generate the ctor for both Type B and Type C
187
+ // But since the generator doesn't guarantee Type B is getting processed first,
188
+ // We need to check the inheritance hierarchy.
189
+ // However, assume Type B wasn't declared in source, we can't generate the ctor for it.
190
+ // Consequently, Type C shouldn't generate source as well.
191
+ if ( type is null )
192
+ {
193
+ return null ;
194
+ }
195
+
196
+ var ctor = type . GetMembers ( WellKnownMemberNames . InstanceConstructorName ) . Cast < IMethodSymbol > ( ) . FirstOrDefault ( predicate ) ;
197
+ if ( ctor != null || ! considerAllBaseTypes || ! type . Locations . Any ( l => l . IsInSource ) )
198
+ {
199
+ return ctor ;
200
+ }
201
+ else
202
+ {
203
+ return GetNativeCtor ( type . BaseType , predicate , true ) ;
204
+ }
205
+ }
187
206
}
188
207
189
208
private bool NeedsExplicitDefaultCtor ( INamedTypeSymbol typeSymbol )
0 commit comments