private void WriteEnum(IREnum e, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, e.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}enum {1} {{", prefix, e.ShortName);

            if (ProtoHelper.HasEnumAlias(e))
            {
                w.WriteLine("{0}option allow_alias = true;", prefix + "\t");
            }

            // Write out all properties of the enum.
            foreach (IREnumProperty prop in e.Properties.OrderBy(prop => prop.Value))
            {
                // Enum property names are NOT converted to snake case!
                w.WriteLine("{0}{1} = {2};", prefix + "\t", prop.Name, prop.Value);
            }

            // End enum.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
        private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                string label = ProtoHelper.FieldLabelToString(opts.Label, false);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                string defaultValue = "";
                if (prop.Options.DefaultValue != null)
                {
                    string formattedValue = ProtoHelper.DefaultValueToString(prop.Options.DefaultValue,
                                                                             prop.ReferencedType);
                    defaultValue = String.Format("[default = {0}]", formattedValue);
                }

                // Proto2 has repeated fields NOT PACKED by default, if they are
                // we mark that explicitly.
                string packed = "";
                if (opts.IsPacked == true && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=true]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0 || defaultValue.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                if (packed.Length > 0)
                {
                    defaultValue = defaultValue.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5}{6};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, defaultValue, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
        public override void Compile()
        {
            Program.Log.OpenBlock("Proto2Compiler::Compile");
            Program.Log.Info("Writing proto files to folder `{0}`", _path);

            if (DumpMode == true)
            {
                // Dump all data into one file and return.
                Dump();

                Program.Log.CloseBlock();
                return;
            }

            // Process file names.
            // This already includes the proto extension!
            _NSLocationCache = ProtoHelper.NamespacesToFileNames(_program.Namespaces,
                                                                 PackageStructured);

            // Create/Open files for writing.
            foreach (var irNS in _NSLocationCache.Keys)
            {
                // Get filename of current namespace.
                var nsFileName = _NSLocationCache[irNS];
                // Make sure directory structure exists, before creating/writing file.
                var folderStruct = Path.Combine(_path, Path.GetDirectoryName(nsFileName));
                Directory.CreateDirectory(folderStruct);

                // Resolve all imports.
                var references = ProtoHelper.ResolveNSReferences(irNS);

                // Construct file for writing.
                var constructedFileName = Path.Combine(_path, nsFileName);
                var fileStream          = File.Create(constructedFileName);
                using (fileStream)
                {
                    var textStream = new StreamWriter(fileStream);
                    using (textStream)
                    {
                        // Print file header.
                        WriteHeaderToFile(irNS, constructedFileName, textStream);
                        // Print imports.
                        WriteImports(references, textStream);
                        // Write all enums..
                        WriteEnumsToFile(irNS, textStream, "");
                        // Followed by all messages.
                        WriteClassesToFile(irNS, textStream, "");
                    }
                }
            }

            // Finish up..
            Program.Log.CloseBlock();
        }
Example #4
0
        private void WriteEnum(IREnum e, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, e.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}enum {1} {{", prefix, e.ShortName);

            if (ProtoHelper.HasEnumAlias(e))
            {
                w.WriteLine("{0}option allow_alias = true;", prefix + "\t");
            }

            // Make a copy of all properties.
            var propList = e.Properties.ToList();
            // For enums, the default value is the first defined enum value, which must be 0.
            // Find or create that property with value 0
            IREnumProperty zeroProp;
            IEnumerable <IREnumProperty> zeroPropEnumeration = propList.Where(prop => prop.Value == 0);

            if (!zeroPropEnumeration.Any())
            {
                zeroProp = new IREnumProperty()
                {
                    // Enum values are all shared within the same namespace, so they must be
                    // unique within that namespace!
                    Name  = e.ShortName.ToUpper() + "_AUTO_INVALID",
                    Value = 0,
                };
            }
            else
            {
                zeroProp = zeroPropEnumeration.First();
                // And remove the property from the collection.
                propList.Remove(zeroProp);
            }

            // Write the zero property first - AS REQUIRED PER PROTO3!
            w.WriteLine("{0}{1} = {2};", prefix + "\t", zeroProp.Name, zeroProp.Value);

            // Write out the other properties of the enum next
            foreach (IREnumProperty prop in propList.OrderBy(prop => prop.Value))
            {
                // Enum property names are NOT converted to snake case!
                w.WriteLine("{0}{1} = {2};", prefix + "\t", prop.Name, prop.Value);
            }

            // End enum.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }
        private void WriteHeaderToFile(IRNamespace ns, string fileName, TextWriter w)
        {
            w.WriteLine("syntax = \"proto2\";");
            if (ns != null)
            {
                var nsPackage = ProtoHelper.ResolvePackageName(ns);
                w.WriteLine("package {0};", nsPackage);
                // Write all file scoped options
                WriteFileOptions(ns, fileName, w);
            }
            w.WriteLine();

            var firstComment = "Proto extractor compiled unit - https://github.com/HearthSim/proto-extractor";

            WriteComments(w, "", firstComment);

            w.WriteLine();
        }
Example #6
0
        private void WriteMessage(IRClass c, TextWriter w, string prefix)
        {
            string reference = String.Format(_Reference, c.OriginalName);

            WriteComments(w, prefix, reference);

            // Type names are kept in PascalCase!
            w.WriteLine("{0}message {1} {{", prefix, c.ShortName);
            // Write all private types first!
            WritePrivateTypesToFile(c, w, prefix + "\t");

            // Write all fields last!
            foreach (IRClassProperty prop in c.Properties.OrderBy(prop => prop.Options.PropertyOrder))
            {
                IRClassProperty.ILPropertyOptions opts = prop.Options;
                // Proto3 syntax has implicit default values!

                string label = ProtoHelper.FieldLabelToString(opts.Label, true);
                string type  = ProtoHelper.TypeTostring(prop.Type, c, prop.ReferencedType);
                string tag   = opts.PropertyOrder.ToString();

                // In proto3, the default for a repeated field is PACKED=TRUE.
                // Only if it's not packed.. we set it to false.
                string packed = "";
                if (opts.IsPacked == false && opts.Label == FieldLabel.REPEATED)
                {
                    packed = "[packed=false]";
                }

                string propName = prop.Name.PascalToSnake();
                if (packed.Length > 0)
                {
                    tag = tag.SuffixAlign();
                }

                w.WriteLine("{0}{1}{2}{3} = {4}{5};", prefix + "\t",
                            label.SuffixAlign(), type.SuffixAlign(), propName,
                            tag, packed);
            }

            // End message.
            w.WriteLine("{0}}}", prefix);
            w.WriteLine();
        }