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(); }
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(); }
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(); }