16
16
using System . ComponentModel . DataAnnotations ;
17
17
18
18
using static Microsoft . CodeAnalysis . CSharp . SyntaxFactory ;
19
+ using REFrameworkNET . Attributes ;
19
20
20
21
public class ClassGenerator {
21
22
public class PseudoProperty {
@@ -209,16 +210,24 @@ private void Generate() {
209
210
var refProxyFieldDecl = SyntaxFactory . FieldDeclaration ( refProxyVarDecl ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
210
211
211
212
213
+ // var typeIdExpr = GenericDictExpr((t) => t.Index);
214
+ var refTypeName = ( FieldDeclarationSyntax ) ParseMemberDeclaration ( $ "public static readonly string REFTypeName = { GenericTypeNameExpr ( ) } ;") ! ;
215
+ if ( baseTypes . Length > 0 )
216
+ refTypeName = refTypeName . AddModifiers ( Token ( SyntaxKind . NewKeyword ) ) ;
217
+ typeDeclaration = typeDeclaration . AddMembers ( refTypeName ) ;
218
+
212
219
// Add a static field to the class that holds the REFrameworkNET.TypeDefinition
213
220
var refTypeFieldDecl = ParseMemberDeclaration (
214
- $ "public static readonly global::REFrameworkNET.TypeDefinition REFType = global::REFrameworkNET.TDB.Get().FindType(\" { t . FullName } \" );"
221
+ $ "public static readonly global::REFrameworkNET.TypeDefinition REFType = global::REFrameworkNET.TDB.Get().FindType(REFTypeName );"
215
222
) ! ;
216
223
if ( baseTypes . Length > 0 ) {
217
224
refTypeFieldDecl = refTypeFieldDecl . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . NewKeyword ) ) ;
218
225
}
219
226
typeDeclaration = typeDeclaration . AddMembers ( refTypeFieldDecl ) ;
220
227
//typeDeclaration = typeDeclaration.AddMembers(refProxyFieldDecl);
221
228
229
+
230
+
222
231
GenerateMethods ( ) ;
223
232
GenerateFields ( ) ;
224
233
GenerateProperties ( ) ;
@@ -251,6 +260,38 @@ var t when t.IsEquivalentTo(TypeHandler.VoidType()) =>
251
260
return ParseStatement ( stmt ) ;
252
261
}
253
262
263
+ // This is a fun one
264
+ private string GenericTypeNameExpr ( ) {
265
+ if ( ! generic )
266
+ return $ "\" { t . FullName } \" ";
267
+ if ( t . FullName == "!0[]" )
268
+ return $ "(string)typeof(T).GetField(\" REFTypeName\" ).GetValue(null) + \" []\" ";
269
+ var hierarchy = TypeHandler . NameHierarchy ( t ) ;
270
+ int genericCount = 0 ;
271
+ var expr = "\" \" " ;
272
+ bool dot = false ;
273
+ foreach ( var elem in hierarchy ) {
274
+ if ( dot ) expr += "+ \" .\" " ;
275
+ dot = true ;
276
+
277
+ var ( name , count ) = TypeHandler . BaseTypeName ( elem ) ;
278
+ if ( count == 0 ) {
279
+ expr += $ " + \" { name } \" ";
280
+ }
281
+
282
+ if ( count != 0 ) {
283
+ expr += $ "+ \" { elem } <\" ";
284
+ for ( int i = 0 ; i < count ; ++ i ) {
285
+ if ( i > 0 ) expr += "+ \" ,\" " ;
286
+ var genericParamName = GenericNames [ genericCount ++ ] ;
287
+ expr += $ "+ (string) typeof({ genericParamName } ).GetField(\" REFTypeName\" ).GetValue(null)";
288
+ }
289
+ expr += $ "+ \" >\" ";
290
+ }
291
+ }
292
+ return expr ;
293
+ }
294
+
254
295
private void GenerateProperties ( ) {
255
296
if ( pseudoProperties . Count == 0 ) {
256
297
return ;
@@ -285,10 +326,12 @@ private void GenerateProperties() {
285
326
SyntaxFactory . ParseName ( "global::REFrameworkNET.Attributes.Method" ) ,
286
327
SyntaxFactory . ParseAttributeArgumentList ( "(" + property . Value . getter . Index . ToString ( ) + ", global::REFrameworkNET.FieldFacadeType.None)" ) )
287
328
) ) ;
288
-
329
+
289
330
if ( property . Value . getter . IsStatic ( ) ) {
290
331
shouldAddStaticKeyword = true ;
332
+ }
291
333
334
+ if ( generic | property . Value . getter . IsStatic ( ) ) {
292
335
// Now we must add a body to it that actually calls the method
293
336
// We have our REFType field, so we can lookup the method and call it
294
337
// Make a private static field to hold the REFrameworkNET.Method
@@ -299,15 +342,9 @@ private void GenerateProperties() {
299
342
var methodFieldDeclaration = SyntaxFactory . FieldDeclaration ( methodVariableDeclaration ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
300
343
internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
301
344
302
- List < StatementSyntax > bodyStatements = [ ] ;
303
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( "return (" + propertyType . GetText ( ) . ToString ( ) + ")" + internalFieldName + ".InvokeBoxed(typeof(" + propertyType . GetText ( ) . ToString ( ) + "), null, null);" ) ) ;
304
-
305
- getter = getter . AddBodyStatements ( bodyStatements . ToArray ( ) ) ;
306
- } else if ( generic ) {
307
- var index = t . Methods . IndexOf ( property . Value . getter ) ;
308
- getter = getter
309
- . AddBodyStatements ( GenericStub ( propertyType , [ ] , index ) )
310
- . WithAttributeLists ( [ ] ) ;
345
+ var instance = property . Value . getter . IsStatic ( ) ? "null" : "this" ;
346
+ var stmt = $ "return ({ propertyType . ToFullString ( ) } ) { internalFieldName } .InvokeBoxed(typeof({ propertyType . ToFullString ( ) } ), { instance } , null);";
347
+ getter = getter . AddBodyStatements ( ParseStatement ( stmt ) ) ;
311
348
} else {
312
349
getter = getter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
313
350
}
@@ -327,9 +364,11 @@ private void GenerateProperties() {
327
364
SyntaxFactory . ParseName ( "global::REFrameworkNET.Attributes.Method" ) ,
328
365
SyntaxFactory . ParseAttributeArgumentList ( "(" + property . Value . setter . Index . ToString ( ) + ", global::REFrameworkNET.FieldFacadeType.None)" ) )
329
366
) ) ;
330
-
367
+
331
368
if ( property . Value . setter . IsStatic ( ) ) {
332
369
shouldAddStaticKeyword = true ;
370
+ }
371
+ if ( generic | property . Value . setter . IsStatic ( ) ) {
333
372
334
373
// Now we must add a body to it that actually calls the method
335
374
// We have our REFType field, so we can lookup the method and call it
@@ -341,15 +380,9 @@ private void GenerateProperties() {
341
380
var methodFieldDeclaration = SyntaxFactory . FieldDeclaration ( methodVariableDeclaration ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
342
381
internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
343
382
344
- List < StatementSyntax > bodyStatements = [ ] ;
345
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( internalFieldName + ".Invoke(null, new object[] {value});" ) ) ;
346
-
347
- setter = setter . AddBodyStatements ( bodyStatements . ToArray ( ) ) ;
348
- } else if ( generic ) {
349
- var index = t . Methods . IndexOf ( property . Value . setter ) ;
350
- setter = setter
351
- . AddBodyStatements ( GenericStub ( null , [ ] , index ) )
352
- . WithAttributeLists ( [ ] ) ;
383
+ var instance = property . Value . setter . IsStatic ( ) ? "null" : "this" ;
384
+ var stmt = $ "{ internalFieldName } .Invoke({ instance } , [value]);";
385
+ setter = setter . AddBodyStatements ( ParseStatement ( stmt ) ) ;
353
386
} else {
354
387
setter = setter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
355
388
}
@@ -455,8 +488,9 @@ private void GenerateFields() {
455
488
var propertyDeclaration = SyntaxFactory . PropertyDeclaration ( fieldType , fieldName )
456
489
. AddModifiers ( [ SyntaxFactory . Token ( SyntaxKind . PublicKeyword ) ] ) ;
457
490
458
- if ( field . IsStatic ( ) ) {
459
- propertyDeclaration = propertyDeclaration . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) ) ;
491
+ if ( field . IsStatic ( ) || generic ) {
492
+ if ( field . IsStatic ( ) )
493
+ propertyDeclaration = propertyDeclaration . AddModifiers ( Token ( SyntaxKind . StaticKeyword ) ) ;
460
494
461
495
// Now we must add a body to it that actually calls the method
462
496
// We have our REFType field, so we can lookup the method and call it
@@ -471,19 +505,15 @@ private void GenerateFields() {
471
505
List < StatementSyntax > bodyStatementsSetter = [ ] ;
472
506
List < StatementSyntax > bodyStatementsGetter = [ ] ;
473
507
508
+ var instance = field . IsStatic ( )
509
+ ? "0"
510
+ : "(this as REFrameworkNET.IObject).GetAddress()" ;
474
511
475
- bodyStatementsGetter . Add ( SyntaxFactory . ParseStatement ( " return (" + fieldType . GetText ( ) . ToString ( ) + ")" + internalFieldName + " .GetDataBoxed(typeof(" + fieldType . GetText ( ) . ToString ( ) + "), 0 , false);") ) ;
476
- bodyStatementsSetter . Add ( SyntaxFactory . ParseStatement ( internalFieldName + " .SetDataBoxed(0 , new object[] {value}, false);") ) ;
512
+ var getterStatement = ParseStatement ( @$ " return ({ fieldType . ToFullString ( ) } ) { internalFieldName } .GetDataBoxed(typeof({ fieldType . ToFullString ( ) } ), { instance } , false);") ;
513
+ var setterStatement = ParseStatement ( $ " { internalFieldName } .SetDataBoxed({ instance } , new object[] {{ value}} , false);") ;
477
514
478
- getter = getter . AddBodyStatements ( bodyStatementsGetter . ToArray ( ) ) ;
479
- setter = setter . AddBodyStatements ( bodyStatementsSetter . ToArray ( ) ) ;
480
- } else if ( generic ) {
481
- getter = getter
482
- . AddBodyStatements ( ParseStatement ( "throw new System.NotImplementedException();" ) )
483
- . WithAttributeLists ( [ ] ) ;
484
- setter = setter
485
- . AddBodyStatements ( ParseStatement ( "throw new System.NotImplementedException();" ) )
486
- . WithAttributeLists ( [ ] ) ;
515
+ getter = getter . AddBodyStatements ( getterStatement ) ;
516
+ setter = setter . AddBodyStatements ( setterStatement ) ;
487
517
} else {
488
518
getter = getter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
489
519
setter = setter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
@@ -609,7 +639,7 @@ private void GenerateMethods() {
609
639
) ;
610
640
611
641
bool anyOutParams = false ;
612
- System . Collections . Generic . List < string > paramNames = [ ] ;
642
+ List < string > paramNames = [ ] ;
613
643
614
644
if ( method . Parameters . Count > 0 ) {
615
645
var runtimeMethod = method . GetRuntimeMethod ( ) ;
@@ -710,48 +740,46 @@ private void GenerateMethods() {
710
740
simpleMethodSignature += "()" ;
711
741
}
712
742
713
- if ( method . IsStatic ( ) ) {
743
+ if ( method . IsStatic ( ) || generic ) {
744
+
714
745
// lets see what happens if we just make it static
715
- methodDeclaration = methodDeclaration . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) ) ;
746
+ if ( method . IsStatic ( ) )
747
+ methodDeclaration = methodDeclaration . AddModifiers ( Token ( SyntaxKind . StaticKeyword ) ) ;
716
748
717
749
// Now we must add a body to it that actually calls the method
718
750
// We have our REFType field, so we can lookup the method and call it
719
751
// Make a private static field to hold the REFrameworkNET.Method
752
+ var index = t . Methods . IndexOf ( method ) ;
720
753
var internalFieldName = "INTERNAL_" + method . Name + method . GetIndex ( ) . ToString ( ) ;
721
- var methodVariableDeclaration = SyntaxFactory . VariableDeclaration ( SyntaxFactory . ParseTypeName ( "global::REFrameworkNET.Method" ) )
722
- . AddVariables ( SyntaxFactory . VariableDeclarator ( internalFieldName ) . WithInitializer ( SyntaxFactory . EqualsValueClause ( SyntaxFactory . ParseExpression ( "REFType.GetMethod(\" " + method . GetMethodSignature ( ) + "\" )" ) ) ) ) ;
723
-
724
- var methodFieldDeclaration = SyntaxFactory . FieldDeclaration ( methodVariableDeclaration ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
754
+ internalFieldName = internalFieldName . Replace ( "." , "_" ) ;
755
+ var methodVariableDeclaration = VariableDeclaration (
756
+ ParseTypeName ( "global::REFrameworkNET.Method" ) )
757
+ . AddVariables ( VariableDeclarator ( internalFieldName )
758
+ . WithInitializer (
759
+ EqualsValueClause ( ParseExpression ( $ "REFType.GetMethods()[{ index } ]") ) ) ) ;
760
+
761
+ var methodFieldDeclaration = FieldDeclaration ( methodVariableDeclaration )
762
+ . AddModifiers (
763
+ Token ( SyntaxKind . PrivateKeyword ) ,
764
+ Token ( SyntaxKind . StaticKeyword ) ,
765
+ Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
725
766
internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
726
767
727
768
List < StatementSyntax > bodyStatements = [ ] ;
728
769
729
- if ( method . ReturnType . FullName == "System.Void" ) {
730
- if ( method . Parameters . Count == 0 ) {
731
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( internalFieldName + ".Invoke(null, null);" ) ) ;
732
- } else if ( ! anyOutParams ) {
733
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( internalFieldName + ".Invoke(null, new object[] {" + string . Join ( ", " , paramNames ) + "});" ) ) ;
734
- } else {
735
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( "throw new System.NotImplementedException();" ) ) ; // TODO: Implement this
736
- }
737
- } else {
738
- if ( method . Parameters . Count == 0 ) {
739
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( "return (" + returnType . GetText ( ) . ToString ( ) + ")" + internalFieldName + ".InvokeBoxed(typeof(" + returnType . GetText ( ) . ToString ( ) + "), null, null);" ) ) ;
740
- } else if ( ! anyOutParams ) {
741
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( "return (" + returnType . GetText ( ) . ToString ( ) + ")" + internalFieldName + ".InvokeBoxed(typeof(" + returnType . GetText ( ) . ToString ( ) + "), null, new object[] {" + string . Join ( ", " , paramNames ) + "});" ) ) ;
742
- } else {
743
- bodyStatements . Add ( SyntaxFactory . ParseStatement ( "throw new System.NotImplementedException();" ) ) ; // TODO: Implement this
744
- }
770
+ var instance = "this" ;
771
+ if ( method . IsStatic ( ) ) {
772
+ instance = "null" ;
745
773
}
746
774
747
- methodDeclaration = methodDeclaration . AddBodyStatements (
748
- [ .. bodyStatements ]
749
- ) ;
750
- } else if ( generic ) {
751
- var index = t . Methods . IndexOf ( method ) ;
752
- methodDeclaration = methodDeclaration
753
- . AddBodyStatements ( GenericStub ( returnType , [ .. paramNames ] , index ) )
754
- . WithAttributeLists ( [ ] ) ;
775
+ var statement = ( method . ReturnType . FullName , method . Parameters ) switch {
776
+ _ when anyOutParams => "throw new System.NotImplementedException();" ,
777
+ ( "System.Void" , [ ] ) => $ " { internalFieldName } .Invoke( { instance } , null);" ,
778
+ ( "System.Void" , [ .. ] ) => $ " { internalFieldName } .Invoke( { instance } , [ { string . Join ( "," , paramNames ) } ]);" ,
779
+ ( _ , [ ] ) => $ "return ( { returnType . ToFullString ( ) } ) { internalFieldName } .InvokeBoxed(typeof( { returnType . ToFullString ( ) } ), { instance } , null);" ,
780
+ ( _ , [ .. ] ) => $ "return ( { returnType . ToFullString ( ) } ) { internalFieldName } .InvokeBoxed(typeof( { returnType . ToFullString ( ) } ), { instance } , [ { string . Join ( "," , paramNames ) } ]);"
781
+ } ;
782
+ methodDeclaration = methodDeclaration . AddBodyStatements ( ParseStatement ( statement ) ) ;
755
783
} else {
756
784
methodDeclaration = methodDeclaration . WithSemicolonToken ( Token ( SyntaxKind . SemicolonToken ) ) ;
757
785
}
@@ -863,6 +891,22 @@ public static TypeSyntax ProperType(TypeDefinition type) {
863
891
return ObjType ( ) ;
864
892
}
865
893
894
+ public static string [ ] NameHierarchy ( TypeDefinition type ) {
895
+ var typeList = new List < string > ( ) ;
896
+ while ( true ) {
897
+ typeList . Insert ( 0 , type . Name ) ;
898
+ if ( type . DeclaringType is null || type . DeclaringType == type )
899
+ break ;
900
+ type = type . DeclaringType ;
901
+ }
902
+ if ( type . Namespace is not null && type . Namespace . Any ( ) ) {
903
+ typeList . Insert ( 0 , type . Namespace ) ;
904
+ } else {
905
+ typeList . Insert ( 0 , "_" ) ;
906
+ }
907
+ return [ .. typeList ] ;
908
+ }
909
+
866
910
static TypeSyntax BuildProperType ( REFrameworkNET . TypeDefinition ? targetType ) {
867
911
868
912
if ( targetType is null ) return VoidType ( ) ;
@@ -886,22 +930,7 @@ static TypeSyntax BuildProperType(REFrameworkNET.TypeDefinition? targetType) {
886
930
}
887
931
Cache [ targetType . Index ] = ObjType ( ) ;
888
932
889
- var typeList = new List < string > ( ) ;
890
- {
891
- var type = targetType ! ;
892
- while ( true ) {
893
- typeList . Insert ( 0 , type . Name ?? "UNKN" ) ;
894
- if ( type . DeclaringType is null || type . DeclaringType == type )
895
- break ;
896
- type = type . DeclaringType ;
897
- }
898
- if ( type . Namespace is not null && type . Namespace . Any ( ) ) {
899
- typeList . Insert ( 0 , type . Namespace ) ;
900
- } else {
901
- typeList . Insert ( 0 , "_" ) ;
902
- }
903
- }
904
-
933
+ var typeList = NameHierarchy ( targetType ) ;
905
934
int genericIndex = 0 ;
906
935
var generics = targetType . GenericArguments ?? [ ] ;
907
936
var toParse = string . Join ( "." , typeList . Select ( tName => {
@@ -933,7 +962,7 @@ public static void BuildProperTypes() {
933
962
BuildProperType ( type ) ;
934
963
// Special case delegates again
935
964
if ( ! ( type . FullName . StartsWith ( "System.Action" ) || type . FullName . StartsWith ( "System.Func" ) ) ) {
936
- if ( type . IsGenericType ( ) ) BuildProperType ( type . GetGenericTypeDefinition ( ) ) ;
965
+ if ( type . IsGenericType ( ) ) BuildProperType ( type . GetGenericTypeDefinition ( ) ) ;
937
966
}
938
967
}
939
968
API . LogInfo ( "Built proper types" ) ;
@@ -965,4 +994,3 @@ public static MemberDeclarationSyntax[] GenerateNestedTypes(TypeDefinition t) {
965
994
. ToArray ( ) ?? [ ] ;
966
995
}
967
996
}
968
-
0 commit comments