1616using System . ComponentModel . DataAnnotations ;
1717
1818using static Microsoft . CodeAnalysis . CSharp . SyntaxFactory ;
19+ using REFrameworkNET . Attributes ;
1920
2021public class ClassGenerator {
2122 public class PseudoProperty {
@@ -209,16 +210,24 @@ private void Generate() {
209210 var refProxyFieldDecl = SyntaxFactory . FieldDeclaration ( refProxyVarDecl ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
210211
211212
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+
212219 // Add a static field to the class that holds the REFrameworkNET.TypeDefinition
213220 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 );"
215222 ) ! ;
216223 if ( baseTypes . Length > 0 ) {
217224 refTypeFieldDecl = refTypeFieldDecl . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . NewKeyword ) ) ;
218225 }
219226 typeDeclaration = typeDeclaration . AddMembers ( refTypeFieldDecl ) ;
220227 //typeDeclaration = typeDeclaration.AddMembers(refProxyFieldDecl);
221228
229+
230+
222231 GenerateMethods ( ) ;
223232 GenerateFields ( ) ;
224233 GenerateProperties ( ) ;
@@ -251,6 +260,38 @@ var t when t.IsEquivalentTo(TypeHandler.VoidType()) =>
251260 return ParseStatement ( stmt ) ;
252261 }
253262
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+
254295 private void GenerateProperties ( ) {
255296 if ( pseudoProperties . Count == 0 ) {
256297 return ;
@@ -285,10 +326,12 @@ private void GenerateProperties() {
285326 SyntaxFactory . ParseName ( "global::REFrameworkNET.Attributes.Method" ) ,
286327 SyntaxFactory . ParseAttributeArgumentList ( "(" + property . Value . getter . Index . ToString ( ) + ", global::REFrameworkNET.FieldFacadeType.None)" ) )
287328 ) ) ;
288-
329+
289330 if ( property . Value . getter . IsStatic ( ) ) {
290331 shouldAddStaticKeyword = true ;
332+ }
291333
334+ if ( generic | property . Value . getter . IsStatic ( ) ) {
292335 // Now we must add a body to it that actually calls the method
293336 // We have our REFType field, so we can lookup the method and call it
294337 // Make a private static field to hold the REFrameworkNET.Method
@@ -299,15 +342,9 @@ private void GenerateProperties() {
299342 var methodFieldDeclaration = SyntaxFactory . FieldDeclaration ( methodVariableDeclaration ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
300343 internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
301344
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 ) ) ;
311348 } else {
312349 getter = getter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
313350 }
@@ -327,9 +364,11 @@ private void GenerateProperties() {
327364 SyntaxFactory . ParseName ( "global::REFrameworkNET.Attributes.Method" ) ,
328365 SyntaxFactory . ParseAttributeArgumentList ( "(" + property . Value . setter . Index . ToString ( ) + ", global::REFrameworkNET.FieldFacadeType.None)" ) )
329366 ) ) ;
330-
367+
331368 if ( property . Value . setter . IsStatic ( ) ) {
332369 shouldAddStaticKeyword = true ;
370+ }
371+ if ( generic | property . Value . setter . IsStatic ( ) ) {
333372
334373 // Now we must add a body to it that actually calls the method
335374 // We have our REFType field, so we can lookup the method and call it
@@ -341,15 +380,9 @@ private void GenerateProperties() {
341380 var methodFieldDeclaration = SyntaxFactory . FieldDeclaration ( methodVariableDeclaration ) . AddModifiers ( SyntaxFactory . Token ( SyntaxKind . PrivateKeyword ) , SyntaxFactory . Token ( SyntaxKind . StaticKeyword ) , SyntaxFactory . Token ( SyntaxKind . ReadOnlyKeyword ) ) ;
342381 internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
343382
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 ) ) ;
353386 } else {
354387 setter = setter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
355388 }
@@ -455,8 +488,9 @@ private void GenerateFields() {
455488 var propertyDeclaration = SyntaxFactory . PropertyDeclaration ( fieldType , fieldName )
456489 . AddModifiers ( [ SyntaxFactory . Token ( SyntaxKind . PublicKeyword ) ] ) ;
457490
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 ) ) ;
460494
461495 // Now we must add a body to it that actually calls the method
462496 // We have our REFType field, so we can lookup the method and call it
@@ -471,19 +505,15 @@ private void GenerateFields() {
471505 List < StatementSyntax > bodyStatementsSetter = [ ] ;
472506 List < StatementSyntax > bodyStatementsGetter = [ ] ;
473507
508+ var instance = field . IsStatic ( )
509+ ? "0"
510+ : "(this as REFrameworkNET.IObject).GetAddress()" ;
474511
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);") ;
477514
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 ) ;
487517 } else {
488518 getter = getter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
489519 setter = setter . WithSemicolonToken ( SyntaxFactory . Token ( SyntaxKind . SemicolonToken ) ) ;
@@ -609,7 +639,7 @@ private void GenerateMethods() {
609639 ) ;
610640
611641 bool anyOutParams = false ;
612- System . Collections . Generic . List < string > paramNames = [ ] ;
642+ List < string > paramNames = [ ] ;
613643
614644 if ( method . Parameters . Count > 0 ) {
615645 var runtimeMethod = method . GetRuntimeMethod ( ) ;
@@ -710,48 +740,46 @@ private void GenerateMethods() {
710740 simpleMethodSignature += "()" ;
711741 }
712742
713- if ( method . IsStatic ( ) ) {
743+ if ( method . IsStatic ( ) || generic ) {
744+
714745 // 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 ) ) ;
716748
717749 // Now we must add a body to it that actually calls the method
718750 // We have our REFType field, so we can lookup the method and call it
719751 // Make a private static field to hold the REFrameworkNET.Method
752+ var index = t . Methods . IndexOf ( method ) ;
720753 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 ) ) ;
725766 internalFieldDeclarations . Add ( methodFieldDeclaration ) ;
726767
727768 List < StatementSyntax > bodyStatements = [ ] ;
728769
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" ;
745773 }
746774
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 ) ) ;
755783 } else {
756784 methodDeclaration = methodDeclaration . WithSemicolonToken ( Token ( SyntaxKind . SemicolonToken ) ) ;
757785 }
@@ -863,6 +891,22 @@ public static TypeSyntax ProperType(TypeDefinition type) {
863891 return ObjType ( ) ;
864892 }
865893
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+
866910 static TypeSyntax BuildProperType ( REFrameworkNET . TypeDefinition ? targetType ) {
867911
868912 if ( targetType is null ) return VoidType ( ) ;
@@ -886,22 +930,7 @@ static TypeSyntax BuildProperType(REFrameworkNET.TypeDefinition? targetType) {
886930 }
887931 Cache [ targetType . Index ] = ObjType ( ) ;
888932
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 ) ;
905934 int genericIndex = 0 ;
906935 var generics = targetType . GenericArguments ?? [ ] ;
907936 var toParse = string . Join ( "." , typeList . Select ( tName => {
@@ -933,7 +962,7 @@ public static void BuildProperTypes() {
933962 BuildProperType ( type ) ;
934963 // Special case delegates again
935964 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 ( ) ) ;
937966 }
938967 }
939968 API . LogInfo ( "Built proper types" ) ;
@@ -965,4 +994,3 @@ public static MemberDeclarationSyntax[] GenerateNestedTypes(TypeDefinition t) {
965994 . ToArray ( ) ?? [ ] ;
966995 }
967996}
968-
0 commit comments