public override void EnterTypeSpec(GoParser.TypeSpecContext context) { GoParser.Type_Context typeContext = context.type_(); string identifier = SanitizedIdentifier(context.IDENTIFIER().GetText()); string typeName = $"{PackageImport.Replace('/', '.')}.{identifier}"; string type = typeContext.GetText(); if (type.StartsWith("interface{")) { Types[typeContext] = new TypeInfo { Name = identifier, TypeName = typeName, FullTypeName = $"go.{typeName}", TypeClass = TypeClass.Interface }; } else if (type.StartsWith("struct{")) { Types[typeContext] = new TypeInfo { Name = identifier, TypeName = typeName, FullTypeName = $"go.{typeName}_package", TypeClass = TypeClass.Struct }; } }
private void RecurseInheritedInterfaces(GoParser.TypeSpecContext context, string identifier, InterfaceInfo interfaceInfo, List <FunctionSignature> functions, List <string> inheritedTypeNames = null, bool useFullTypeName = false) { foreach (string interfaceName in interfaceInfo.GetInheritedInterfaceNames()) { if (TryFindInheritedInterfaceInfo(interfaceName, out InterfaceInfo inheritedInferfaceInfo, out string shortTypeName, out string fullTypeName)) { inheritedTypeNames?.Add(useFullTypeName ? fullTypeName : shortTypeName); functions.AddRange(inheritedInferfaceInfo.GetLocalMethods()); RecurseInheritedInterfaces(context, identifier, inheritedInferfaceInfo, functions); }
public override void ExitTypeSpec(GoParser.TypeSpecContext context) { string identifier = context.IDENTIFIER().GetText(); if (m_interfaceMethods.TryGetValue(context.type_()?.typeLit()?.interfaceType(), out List <FunctionSignature> methods)) { m_interfaces.Add(GetUniqueIdentifier(m_interfaces, identifier), new InterfaceInfo { Name = identifier, Methods = methods.ToArray() }); } else if (m_structFields.TryGetValue(context.type_()?.typeLit()?.structType(), out List <FieldInfo> fields)) { m_structs.Add(GetUniqueIdentifier(m_structs, identifier), new StructInfo { Name = identifier, Fields = fields.ToArray() }); } }
public override void ExitTypeSpec(GoParser.TypeSpecContext context) { // typeSpec // : IDENTIFIER type string originalIdentifier = context.IDENTIFIER().GetText(); string scope = char.IsUpper(originalIdentifier[0]) ? "public" : "private"; string target = Path.GetFileNameWithoutExtension(TargetFileName); string identifier = SanitizedIdentifier(originalIdentifier); // TODO: Sub-function strategy, declare directly prior to function using PushBlock / PopBlock operations and a new replacement marker if (m_inFunction) { AddWarning(context, $"Type specification made from within function \"{m_currentFunctionName}\" - this is will not compile in C#"); } if (m_typeIdentifierCount == 0 && m_typeMultipleDeclaration) { m_targetFile.Append(RemoveFirstLineFeed(CheckForCommentsLeft(context))); } if (Metadata.Interfaces.TryGetValue(originalIdentifier, out InterfaceInfo interfaceInfo)) { // Handle interface type declaration string ancillaryInterfaceFileName = Path.Combine(TargetFilePath, $"{target}_{identifier}Interface.cs"); FunctionSignature[] localFunctions = interfaceInfo.GetLocalMethods().ToArray(); List <FunctionSignature> allFunctions = localFunctions.ToList(); RecurseInheritedInterfaces(context, originalIdentifier, interfaceInfo, allFunctions); using (StreamWriter writer = File.CreateText(ancillaryInterfaceFileName)) { writer.Write(new InterfaceTypeTemplate { NamespacePrefix = PackageNamespace, NamespaceHeader = m_namespaceHeader, NamespaceFooter = m_namespaceFooter, PackageName = Package, InterfaceName = identifier, Scope = scope, Interface = interfaceInfo, Functions = allFunctions, UsingStatements = m_usingStatements } .TransformText()); } // Track file name associated with package AddFileToPackage(Package, ancillaryInterfaceFileName, PackageNamespace); string inheritedInterfaces = interfaceInfo.GenerateInheritedInterfaceList(); if (inheritedInterfaces.Length > 0) { inheritedInterfaces = $" : {inheritedInterfaces}"; } m_targetFile.AppendLine($"{Spacing()}{scope} partial interface {identifier}{inheritedInterfaces}"); m_targetFile.AppendLine($"{Spacing()}{{"); foreach (FunctionSignature function in localFunctions) { m_targetFile.Append($"{Spacing(1)}{function.Signature.GenerateResultSignature()} {SanitizedIdentifier(function.Name)}({function.Signature.GenerateParametersSignature(false)});{(string.IsNullOrWhiteSpace(function.Comments) ? Environment.NewLine : $" {function.Comments.TrimStart()}")}"); } m_targetFile.Append($"{Spacing()}}}{CheckForCommentsRight(context)}"); } else if (Metadata.Structs.TryGetValue(originalIdentifier, out StructInfo structInfo)) { // Handle struct type declaration string ancillaryStructFileName = Path.Combine(TargetFilePath, $"{target}_{identifier}Struct.cs"); Dictionary <string, List <FunctionSignature> > promotedFunctions = new Dictionary <string, List <FunctionSignature> >(StringComparer.Ordinal); HashSet <string> inheritedTypeNames = new HashSet <string>(StringComparer.Ordinal); RecurseInheritedInterfaces(context, originalIdentifier, structInfo, promotedFunctions, inheritedTypeNames); Dictionary <string, List <FieldInfo> > promotedFields = new Dictionary <string, List <FieldInfo> >(StringComparer.Ordinal); HashSet <string> promotedStructs = new HashSet <string>(StringComparer.Ordinal); SearchPromotedStructFields(context, originalIdentifier, structInfo, inheritedTypeNames, promotedFields, promotedStructs); using (StreamWriter writer = File.CreateText(ancillaryStructFileName)) { writer.Write(new StructTypeTemplate { NamespacePrefix = PackageNamespace, NamespaceHeader = m_namespaceHeader, NamespaceFooter = m_namespaceFooter, PackageName = Package, StructName = identifier, Scope = scope, StructFields = structInfo.Fields, PromotedStructs = promotedStructs, PromotedFunctions = promotedFunctions, PromotedFields = promotedFields, UsingStatements = m_usingStatements } .TransformText()); } // Track file name associated with package AddFileToPackage(Package, ancillaryStructFileName, PackageNamespace); List <FieldInfo> fields = new List <FieldInfo>(); foreach (FieldInfo field in structInfo.Fields) { if (field.IsPromoted && !inheritedTypeNames.Contains(field.Name)) { FieldInfo promotedStruct = field.Clone(); promotedStruct.Type.TypeName = $"ref {promotedStruct.Type.Name}"; promotedStruct.Name = $"{promotedStruct.Name} => ref {promotedStruct.Name}_{(promotedStruct.Type.IsPointer ? "ptr" : "val")}"; fields.Add(promotedStruct); } else { fields.Add(field); } } m_targetFile.AppendLine($"{Spacing()}{scope} partial struct {identifier}{GetInheritedTypeList(inheritedTypeNames)}"); m_targetFile.AppendLine($"{Spacing()}{{"); foreach (FieldInfo field in fields) { StringBuilder fieldDecl = new StringBuilder(); if (!string.IsNullOrWhiteSpace(field.Description)) { string description = field.Description.Trim(); if (description.Length > 2) { RequiredUsings.Add("System.ComponentModel"); fieldDecl.AppendLine($"{Spacing(1)}[Description({description})]"); } } fieldDecl.Append($"{Spacing(1)}public {field.Type.TypeName} {field.Name};{(string.IsNullOrWhiteSpace(field.Comments) ? Environment.NewLine : $" {field.Comments.TrimStart()}")}"); m_targetFile.Append(fieldDecl); } m_targetFile.Append($"{Spacing()}}}{CheckForCommentsRight(context)}"); } else if (Types.TryGetValue(context.type_(), out TypeInfo typeInfo)) { if (typeInfo.TypeClass == TypeClass.Function) { RequiredUsings.Decrement("System"); // Handle delegate type declaration string signature = typeInfo.TypeName; if (signature.Equals("Action", StringComparison.Ordinal)) { m_targetFile.Append($"{Spacing()}public delegate void {identifier}();"); m_targetFile.Append(CheckForCommentsRight(context)); } else if (signature.StartsWith("Action<", StringComparison.Ordinal)) { signature = RemoveSurrounding(signature.Substring(6), "<", ">"); m_targetFile.Append($"{Spacing()}public delegate void {identifier}({signature});"); m_targetFile.Append(CheckForCommentsRight(context)); } else if (signature.StartsWith("Func<", StringComparison.Ordinal)) { signature = RemoveSurrounding(signature.Substring(4), "<", ">"); string[] parts = signature.Split(','); if (parts.Length > 0) { string result = parts[^ 1];