232 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			232 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using EpicGames.Core;
 | |
| using EpicGames.UHT.Types;
 | |
| using EpicGames.UHT.Utils;
 | |
| using UnrealSharpScriptGenerator.Utilities;
 | |
| 
 | |
| namespace UnrealSharpScriptGenerator;
 | |
| 
 | |
| public class GeneratorStringBuilder : IDisposable
 | |
| {
 | |
|     private int _indent;
 | |
|     private readonly List<string> _directives = new();
 | |
|     private BorrowStringBuilder _borrower = new(StringBuilderCache.Big);
 | |
|     private StringBuilder StringBuilder => _borrower.StringBuilder;
 | |
| 
 | |
|     public override string ToString()
 | |
|     {
 | |
|         return StringBuilder.ToString();
 | |
|     }
 | |
| 
 | |
|     public void Dispose()
 | |
|     {
 | |
|         _borrower.Dispose();
 | |
|     }
 | |
|     
 | |
|     public void OpenBrace()
 | |
|     {
 | |
|         AppendLine("{");
 | |
|         Indent();
 | |
|     }
 | |
|     
 | |
|     public void CloseBrace()
 | |
|     {
 | |
|         UnIndent();
 | |
|         AppendLine("}");
 | |
|     }
 | |
| 
 | |
|     public void Indent()
 | |
|     {
 | |
|        ++_indent;
 | |
|     }
 | |
|     
 | |
|     public void UnIndent()
 | |
|     {
 | |
|         --_indent;
 | |
|     }
 | |
|     
 | |
|     public void Append(string text)
 | |
|     {
 | |
|         StringBuilder.Append(text);
 | |
|     }
 | |
| 
 | |
|     public void AppendLine()
 | |
|     {
 | |
|         if (StringBuilder.Length > 0)
 | |
|         {
 | |
|             StringBuilder.AppendLine();
 | |
|         }
 | |
|         
 | |
|         for (int i = 0; i < _indent; i++)
 | |
|         {
 | |
|             StringBuilder.Append("    ");
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void AppendLine(string line)
 | |
|     {
 | |
|         AppendLine();
 | |
|         StringBuilder.Append(line);
 | |
|     }
 | |
|     
 | |
|     public void DeclareDirective(string directive)
 | |
|     {
 | |
|         if (_directives.Contains(directive) || string.IsNullOrEmpty(directive))
 | |
|         {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         _directives.Add(directive);
 | |
|         AppendLine($"using {directive};");
 | |
|     }
 | |
|     
 | |
|     public void DeclareDirectives(List<string> directives)
 | |
|     {
 | |
|         foreach (string directive in directives)
 | |
|         {
 | |
|             DeclareDirective(directive);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void BeginPreproccesorBlock(string condition)
 | |
|     {
 | |
|         AppendLine($"#if {condition}");
 | |
|     }
 | |
|     
 | |
|     public void EndPreproccesorBlock()
 | |
|     {
 | |
|         AppendLine("#endif");
 | |
|     }
 | |
|     
 | |
|     public void BeginWithEditorPreproccesorBlock()
 | |
|     {
 | |
|         BeginPreproccesorBlock("WITH_EDITOR");
 | |
|     }
 | |
|     
 | |
|     public void TryAddWithEditor(UhtProperty property)
 | |
|     {
 | |
|         if (property.HasAllFlags(EPropertyFlags.EditorOnly))
 | |
|         {
 | |
|             BeginWithEditorPreproccesorBlock();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void TryEndWithEditor(UhtProperty property)
 | |
|     {
 | |
|         if (property.HasAllFlags(EPropertyFlags.EditorOnly))
 | |
|         {
 | |
|             EndPreproccesorBlock();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void TryEndWithEditor(UhtFunction function)
 | |
|     {
 | |
|         if (function.FunctionFlags.HasAllFlags(EFunctionFlags.EditorOnly))
 | |
|         {
 | |
|             EndPreproccesorBlock();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void TryAddWithEditor(UhtFunction function)
 | |
|     {
 | |
|         if (function.FunctionFlags.HasAllFlags(EFunctionFlags.EditorOnly))
 | |
|         {
 | |
|             BeginWithEditorPreproccesorBlock();
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void BeginUnsafeBlock()
 | |
|     {
 | |
|         AppendLine("unsafe");
 | |
|         OpenBrace();
 | |
|     }
 | |
|     
 | |
|     public void EndUnsafeBlock()
 | |
|     {
 | |
|         CloseBrace();
 | |
|     }
 | |
|     
 | |
|     public void GenerateTypeSkeleton(string typeNameSpace, bool blittable = false, bool nullableEnabled = false)
 | |
|     {
 | |
|         if (nullableEnabled)
 | |
|         {
 | |
|             AppendLine("#nullable enable");
 | |
|         }
 | |
|         DeclareDirective(ScriptGeneratorUtilities.AttributeNamespace);
 | |
|         DeclareDirective(ScriptGeneratorUtilities.CoreAttributeNamespace);
 | |
|         DeclareDirective(ScriptGeneratorUtilities.InteropNamespace);
 | |
|         DeclareDirective(ScriptGeneratorUtilities.MarshallerNamespace);
 | |
|         
 | |
|         if (blittable)
 | |
|         {
 | |
|             DeclareDirective(ScriptGeneratorUtilities.InteropServicesNamespace);
 | |
|         }
 | |
| 
 | |
|         AppendLine();
 | |
|         AppendLine($"namespace {typeNameSpace};");
 | |
|         AppendLine();
 | |
|     }
 | |
|     
 | |
|     public void GenerateTypeSkeleton(UhtType type)
 | |
|     {
 | |
|         GenerateTypeSkeleton(type.GetNamespace());
 | |
|     }
 | |
|     
 | |
|     public void DeclareType(UhtType? type , string typeName, string declaredTypeName, string? baseType = null, bool isPartial = true, string? modifiers = "", List<UhtClass>? nativeInterfaces = default, List<string>? csInterfaces = default)
 | |
|     {
 | |
|         string partialSpecifier = isPartial ? "partial " : string.Empty;
 | |
|         List<string> inheritingFrom = new List<string>();
 | |
|         
 | |
|         if (!string.IsNullOrEmpty(baseType)) inheritingFrom.Add(baseType);
 | |
| 
 | |
|         if (nativeInterfaces != null)
 | |
|         {
 | |
|             foreach (UhtType @interface in nativeInterfaces)
 | |
|             {
 | |
|                 string fullInterfaceName = @interface.GetFullManagedName();
 | |
|                 inheritingFrom.Add(fullInterfaceName);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (csInterfaces != null)
 | |
|         {
 | |
|             foreach (string @interface in csInterfaces) inheritingFrom.Add(@interface);
 | |
|         }
 | |
| 
 | |
|         string accessSpecifier = "public";
 | |
|         if (type != null && type.HasMetadata("InternalType"))
 | |
|         {
 | |
|             accessSpecifier = "internal";
 | |
|         }
 | |
| 
 | |
|         string inheritanceSpecifier =
 | |
|             inheritingFrom.Count > 0 ? $" : {string.Join(", ", inheritingFrom)}" : string.Empty;
 | |
|         
 | |
|         AppendLine($"{accessSpecifier}{modifiers} {partialSpecifier}{typeName} {declaredTypeName}{inheritanceSpecifier}");
 | |
|         OpenBrace();
 | |
|     }
 | |
|     
 | |
|     public void AppendStackAlloc(string sizeVariableName)
 | |
|     {
 | |
|         AppendLine($"byte* paramsBufferAllocation = stackalloc byte[{sizeVariableName}];");
 | |
|         AppendLine("nint paramsBuffer = (nint) paramsBufferAllocation;");
 | |
|     }
 | |
| 
 | |
|     public void AppendStackAllocFunction(string sizeVariableName, string structName, bool appendInitializer = true)
 | |
|     {
 | |
|         AppendStackAlloc(sizeVariableName);
 | |
|         
 | |
|         if (appendInitializer)
 | |
|         {
 | |
|             AppendLine($"{ExporterCallbacks.UFunctionCallbacks}.CallInitializeFunctionParams({structName}, paramsBuffer);");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void AppendStackAllocProperty(string sizeVariableName, string sourcePropertyName)
 | |
|     {
 | |
|         AppendStackAlloc(sizeVariableName);
 | |
|         AppendLine($"{ExporterCallbacks.FPropertyCallbacks}.CallInitializeValue({sourcePropertyName}, paramsBuffer);");
 | |
|     }
 | |
| } |