Example #1
0
        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
                };
            }
        }
Example #2
0
 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);
         }
Example #3
0
        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()
                });
            }
        }
Example #4
0
        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];