public ProtoCollection Import(IEnumerable<string> inputProto) { var collection = new ProtoCollection(); //Files from command line arguments, all import statements will be followed var basePath = Path.Combine(Path.GetFullPath(Directory.GetCurrentDirectory()), "dummy"); foreach (string rawPath in inputProto) { string protoPath = GetFullPath(basePath, rawPath); var proto = Import(protoPath); collection.Merge(proto); //Include non public imports for the first level foreach (var path in proto.Import) toImport.Add(GetFullPath(protoPath, path)); } //Read imported files, nested while (toImport.Count != 0) { var path = toImport[0]; toImport.RemoveAt(0); var c = Import(path); if (c != null) { //Mark imported c.MarkImported(); collection.Merge(c); } } return collection; }
public ProtoCollection Import(IEnumerable <string> inputProto) { var collection = new ProtoCollection(); //Files from command line arguments, all import statements will be followed var basePath = Path.Combine(Path.GetFullPath(Directory.GetCurrentDirectory()), "dummy"); foreach (string rawPath in inputProto) { string protoPath = GetFullPath(basePath, rawPath); var proto = Import(protoPath); collection.Merge(proto); //Include non public imports for the first level foreach (var path in proto.Import) { toImport.Add(GetFullPath(protoPath, path)); } } //Read imported files, nested while (toImport.Count != 0) { var path = toImport[0]; toImport.RemoveAt(0); var c = Import(path); if (c != null) { collection.Merge(c); } } return(collection); }
/// <summary> /// Parse a single .proto file. /// Return true if successful/no errors. /// </summary> public static void Parse(string path, ProtoCollection p) { //Preparation for parsing //Real parsing is done in ParseMessages lastComment.Clear(); //Read entire file and pass it into a TokenReader string t = ""; using (TextReader reader = new StreamReader(path, Encoding.UTF8)) { while (true) { string line = reader.ReadLine(); if (line == null) { break; } t += line + "\n"; } } TokenReader tr = new TokenReader(t, path); try { ParseMessages(tr, p); } catch (EndOfStreamException) { return; } }
ProtoCollection Import(string protoPath) { if (imported.ContainsKey(protoPath)) return null; //Already imported var proto = new ProtoCollection(); try { Console.WriteLine("Parsing " + protoPath); ProtoParser.Parse(protoPath, proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); throw; } foreach (var path in proto.ImportPublic) toImport.Add(GetFullPath(protoPath, path)); imported.Add(protoPath, proto); return proto; }
ProtoCollection Import(string protoPath) { if (imported.ContainsKey(protoPath)) { return(null); //Already imported } var proto = new ProtoCollection(); try { Console.WriteLine("Parsing " + protoPath); ProtoParser.Parse(protoPath, proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); throw; } foreach (var path in proto.ImportPublic) { toImport.Add(GetFullPath(protoPath, path)); } imported.Add(protoPath, proto); return(proto); }
/// <summary> /// Parse a single .proto file. /// Return true if successful/no errors. /// </summary> public static void Parse(string path, ProtoCollection p) { //Preparation for parsing //Real parsing is done in ParseMessages lastComment.Clear(); //Read entire file and pass it into a TokenReader string t = ""; using (TextReader reader = new StreamReader(path, Encoding.UTF8)) { while (true) { string line = reader.ReadLine(); if (line == null) break; t += line + "\n"; } } TokenReader tr = new TokenReader(t, path); try { ParseMessages(tr, p); } catch (EndOfStreamException) { return; } }
/// <summary> /// Parse a single .proto file. /// Return true if successful/no errors. /// </summary> public static void Parse(string path, ProtoCollection p, bool fixComments) { //Preparation for parsing //Real parsing is done in ParseMessages lastComment.Clear(); TextReader reader = null; if (fixComments) { var text = File.ReadAllLines(path).ToList(); for (int i = 0; i < text.Count; i++) { if (!text[i].TrimStart().StartsWith("//") && text[i].Contains("//")) { var splitted = text[i].Split(new [] { "//" }, StringSplitOptions.None); text[i] = splitted[0]; text.Insert(i, "//" + splitted[1]); if (splitted.Length > 2) { Console.WriteLine("More then 2 comments in line " + i); throw new Exception(); } i--; } reader = new StringReader(string.Join("\n", text)); } } else { reader = new StreamReader(path, Encoding.UTF8); } //Read entire file and pass it into a TokenReader string t = ""; while (true) { string line = reader.ReadLine(); if (line == null) { break; } t += line + "\n"; } reader.Close(); TokenReader tr = new TokenReader(t, path); try { ParseMessages(tr, p); } catch (EndOfStreamException) { return; } }
static void ParseMessages(TokenReader tr, ProtoCollection p) { string package = "Example"; while (true) { string token = tr.ReadNext(); if (ParseComment(token)) { continue; } try { switch (token) { case ";": lastComment.Clear(); continue; case "message": ParseMessage(tr, p, package); break; case "enum": ParseEnum(tr, p, package); break; case "option": //Save options ParseOption(tr, p); break; case "import": //Ignored tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "package": package = tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "extend": ParseExtend(tr, p, package); break; default: throw new ProtoFormatException("Unexpected/not implemented: " + token, tr); } } catch (EndOfStreamException) { throw new ProtoFormatException("Unexpected EOF", tr); } } }
static void ParseMessages(TokenReader tr, ProtoCollection p) { string package = "Example"; while (true) { string token = tr.ReadNextComment(); if (ParseComment(token)) continue; try { switch (token) { case ";": break; case "message": ParseMessage(tr, p, package); break; case "enum": ParseEnum(tr, p, package); break; case "option": //Save options ParseOption(tr, p); break; case "import": ParseImport(tr, p); break; case "package": package = tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "syntax": //This is not a supported protobuf keyword, used in Google internally tr.ReadNextOrThrow("="); tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "extend": ParseExtend(tr, p, package); break; default: throw new ProtoFormatException("Unexpected/not implemented: " + token, tr); } lastComment.Clear(); } catch (EndOfStreamException) { throw new ProtoFormatException("Unexpected EOF", tr); } } }
public void Merge(ProtoCollection proto) { foreach (var m in proto.Messages.Values) { Messages.Add(m.ProtoName, m); m.Parent = this; } foreach (var e in proto.Enums.Values) { Enums.Add(e.ProtoName, e); e.Parent = this; } }
public void Merge(ProtoCollection proto) { foreach (var m in proto.Messages.Values) { Messages.Add(m.ProtoName, m); m.Parent = this; } foreach (var e in proto.Enums.Values) { Enums.Add(e.ProtoName, e); e.Parent = this; } Comments = Comments == null ? proto.Comments : Comments + "\n" + proto.Comments; }
public static int Main(string[] args) { var options = Options.Parse(args); if (options == null) { return(-1); } ProtoCollection collection = new ProtoCollection(); foreach (string protoPath in options.InputProto) { try { Console.WriteLine("Parsing " + protoPath); var proto = new ProtoCollection(); ProtoParser.Parse(protoPath, proto); collection.Merge(proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return(-1); } } Console.WriteLine(collection); //Interpret and reformat try { var pp = new ProtoPrepare(options); pp.Prepare(collection); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return(-1); } //Generate code ProtoCode.Save(collection, options); Console.WriteLine("Saved: " + options.OutputPath); return(0); }
public void Prepare(ProtoCollection file) { foreach (ProtoMessage m in file.Messages.Values) { if (m.OptionNamespace == null) m.OptionNamespace = GetCamelCase(m.Package); PrepareMessage(m); } foreach (ProtoEnum e in file.Enums.Values) { if (e.OptionNamespace == null) e.OptionNamespace = GetCamelCase(e.Package); e.CsType = GetCamelCase(e.ProtoName); } }
public static int Main(string[] args) { var options = Options.Parse(args); if(options == null) return -1; ProtoCollection collection = new ProtoCollection(); foreach(string protoPath in options.InputProto) { try { Console.WriteLine("Parsing " + protoPath); var proto = new ProtoCollection(); ProtoParser.Parse(protoPath, proto); collection.Merge(proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return -1; } } Console.WriteLine(collection); //Interpret and reformat try { var pp = new ProtoPrepare(options); pp.Prepare(collection); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return -1; } //Generate code ProtoCode.Save(collection, options); Console.WriteLine("Saved: " + options.OutputPath); return 0; }
static public void Prepare(ProtoCollection file) { foreach (ProtoMessage m in file.Messages.Values) { if (m.OptionNamespace == null) { m.OptionNamespace = GetCamelCase(m.Package); } PrepareMessage(m); } foreach (ProtoEnum e in file.Enums.Values) { if (e.OptionNamespace == null) { e.OptionNamespace = GetCamelCase(e.Package); } e.CsType = GetCamelCase(e.ProtoName); } }
static void ParseImport(TokenReader tr, ProtoCollection collection) { string path = tr.ReadNext(); bool publicImport = path == "public"; if (publicImport) { path = tr.ReadNext(); } tr.ReadNextOrThrow(";"); if (publicImport) { collection.ImportPublic.Add(path); } else { collection.Import.Add(path); } }
/// <summary> /// Parse a single .proto file. /// Return true if successful/no errors. /// </summary> public static void Parse(string path, ProtoCollection p) { //Preparation for parsing //Real parsing is done in ParseMessages lastComment.Clear(); var codeFile = Path.GetExtension(path).ToLower().Equals(".cs"); //Read entire file and pass it into a TokenReader string t = ""; using (TextReader reader = new StreamReader(path, Encoding.UTF8)) { if (codeFile) { t = ReadAllLinesCodeFile(reader); } else { t = ReadAllLinesProto(reader); } } if (t.Length == 0) { return; } Console.WriteLine("Parsing " + path); TokenReader tr = new TokenReader(t, path); try { ParseMessages(tr, p); } catch (EndOfStreamException) { return; } }
public static void Build(Options options) { ProtoCollection collection = new ProtoCollection(); foreach (string protoPath in options.InputProto) { try { var proto = new ProtoCollection(); ProtoParser.Parse(protoPath, proto); collection.Merge(proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); throw; } } Console.WriteLine(collection); //Interpret and reformat try { var pp = new ProtoPrepare(options); pp.Prepare(collection); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); throw; } //Generate code ProtoCode.Save(collection, options); Console.WriteLine("Saved: " + options.OutputPath); }
/// <summary> /// Generate code for reading and writing protocol buffer messages /// </summary> public static void Save(ProtoCollection file, string csPath) { string ext = Path.GetExtension(csPath); string prefix = csPath.Substring(0, csPath.Length - ext.Length); string csDir = Path.GetDirectoryName(csPath); if (Directory.Exists(csDir) == false) { Directory.CreateDirectory(csDir); } //Basic structures using (var cw = new CodeWriter(csPath)) { cw.Comment(@"Classes and structures being serialized"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run. To make custom modifications, edit the .proto file and add //:external before the message line then write the code and the changes in a separate file."); //cw.WriteLine("using System;"); //cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); //string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) {/* * if (ns != m.CsNamespace) * { * if (ns != null) //First time * cw.EndBracket(); * cw.Bracket("namespace " + m.CsNamespace); * ns = m.CsNamespace; * }*/ MessageCode.GenerateClass(m, cw); cw.WriteLine(); } foreach (ProtoEnum e in file.Enums.Values) {/* * if (ns != e.CsNamespace) * { * if (ns != null) //First time * cw.EndBracket(); * cw.Bracket("namespace " + e.CsNamespace); * ns = e.CsNamespace; * }*/ MessageCode.GenerateEnum(e, cw); cw.WriteLine(); } //cw.EndBracket(); } //.Serializer.cs //Code for Reading/Writing using (var cw = new CodeWriter(prefix + ".Serializer" + ext)) { cw.Comment(@"This is the backend code for reading and writing"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run."); //cw.WriteLine("using System;"); //cw.WriteLine("using System.IO;"); cw.WriteLine(); //string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { //if (ns != m.CsNamespace) //{ // if (ns != null) //First time // cw.EndBracket(); // cw.Bracket("namespace " + m.CsNamespace); // ns = m.CsNamespace; //} MessageSerializer.GenerateClassSerializer(m, cw); } //cw.EndBracket(); } string libPath = Path.Combine(Path.GetDirectoryName(csPath), "ProtocolParser.cs"); using (TextWriter codeWriter = new StreamWriter(libPath, false, Encoding.UTF8)) { ReadCode(codeWriter, "ProtocolParser", true); ReadCode(codeWriter, "ProtocolParserFixed", false); ReadCode(codeWriter, "ProtocolParserKey", false); ReadCode(codeWriter, "ProtocolParserVarInt", false); } string output1 = File.ReadAllText(libPath); string output2 = File.ReadAllText(csPath); string output3 = File.ReadAllText(prefix + ".Serializer" + ext); File.WriteAllText(prefix + ".Serializer" + ".ci.cs", output1 + output2 + output3); }
/// <summary> /// Generate code for reading and writing protocol buffer messages /// </summary> public static void Save(ProtoCollection file, Options options) { string csPath = options.OutputPath; CodeWriter.DefaultIndentPrefix = options.UseTabs ? "\t" : " "; string ext = Path.GetExtension(csPath); string prefix = csPath.Substring(0, csPath.Length - ext.Length); string csDir = Path.GetDirectoryName(csPath); if (Directory.Exists(csDir) == false) { Directory.CreateDirectory(csDir); } //Basic structures using (var cw = new CodeWriter(csPath)) { if (string.IsNullOrWhiteSpace(file.Comments) == false) { cw.Comment(file.Comments); cw.WriteLine(); } cw.Comment(@"Classes and structures being serialized"); cw.WriteLine(); cw.Comment(Disclamer); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run. To make custom modifications, edit the .proto file and add //:external before the message line then write the code and the changes in a separate file."); cw.WriteLine(); cw.Comment("ReSharper disable InconsistentNaming"); cw.WriteLine(); cw.WriteLine("using System;"); cw.WriteLine("using System.Collections.Generic;"); if (options.DataContractAttributes) { cw.WriteLine("using System.Runtime.Serialization;"); } cw.WriteLine(); var messageCode = new MessageCode(cw, options); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } messageCode.GenerateClass(m); cw.WriteLine(); } foreach (ProtoEnum e in file.Enums.Values) { if (ns != e.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } cw.Bracket("namespace " + e.CsNamespace); ns = e.CsNamespace; } messageCode.GenerateEnum(e); cw.WriteLine(); } if (ns != null) { cw.EndBracket(); } } //.Serializer.cs //Code for Reading/Writing using (var cw = new CodeWriter(prefix + ".Serializer" + ext)) { if (string.IsNullOrWhiteSpace(file.Comments) == false) { cw.Comment(file.Comments); cw.WriteLine(); } cw.Comment(@"This is the backend code for reading and writing"); cw.WriteLine(); cw.Comment(Disclamer); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run."); cw.WriteLine(); cw.Comment("ReSharper disable InconsistentNaming"); cw.WriteLine(); cw.WriteLine("using System;"); cw.WriteLine("using System.IO;"); cw.WriteLine("using System.Text;"); cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } var messageSerializer = new MessageSerializer(cw, options); messageSerializer.GenerateClassSerializer(m); } if (ns != null) { cw.EndBracket(); } } //Option to no include ProtocolParser.cs in the output directory if (options.NoProtocolParser) { Console.Error.WriteLine("ProtocolParser.cs not (re)generated"); } else { string libPath = Path.Combine(Path.GetDirectoryName(csPath), "ProtocolParser.cs"); using (TextWriter codeWriter = new StreamWriter(libPath, false, Encoding.UTF8)) { codeWriter.NewLine = "\r\n"; ReadCode(codeWriter, "ProtocolParser", true); ReadCode(codeWriter, "ProtocolParserExceptions", false); ReadCode(codeWriter, "ProtocolParserFixed", false); ReadCode(codeWriter, "ProtocolParserKey", false); ReadCode(codeWriter, "ProtocolParserMemory", false); if (options.Net2 == false) { ReadCode(codeWriter, "ProtocolParserMemory4", false); } ReadCode(codeWriter, "ProtocolParserVarInt", false); } } }
static void ParseMessages(TokenReader tr, ProtoCollection p) { string package = "Example"; while (true) { string token = tr.ReadNextComment(); if (ParseComment(token)) { continue; } try { switch (token) { case ";": break; case "message": ParseMessage(tr, p, package); break; case "enum": ParseEnum(tr, p, package); break; case "option": //Save options ParseOption(tr, p); break; case "import": ParseImport(tr, p); break; case "package": package = tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "syntax": //This is not a supported protobuf keyword, used in Google internally tr.ReadNextOrThrow("="); tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "extend": ParseExtend(tr, p, package); break; default: throw new ProtoFormatException("Unexpected/not implemented: " + token, tr); } lastComment.Clear(); } catch (EndOfStreamException) { throw new ProtoFormatException("Unexpected EOF", tr); } } }
public static int Main(string[] args) { if (args.Length == 0) { Console.Error.WriteLine("Usage:\n\tCodeGenerator.exe [--preserve-names] [--use-tabs] path-to.proto [path-to-second.proto [...]] [output.cs]"); return(-1); } ProtoCollection collection = new ProtoCollection(); string outputPath = null; int argIndex = 0; while (args.Length > argIndex && args [argIndex].StartsWith("--")) { switch (args[argIndex]) { case "--preserve-names": ProtoPrepare.ConvertToCamelCase = false; break; case ProtoPrepare.FixNameclashArgument: ProtoPrepare.FixNameclash = true; break; case "--use-tabs": CodeWriter.IndentPrefix = "\t"; break; default: Console.Error.WriteLine("Unknown option: " + args[argIndex]); return(-1); } argIndex++; } while (argIndex < args.Length) { string protoPath = Path.GetFullPath(args[argIndex]); string protoBase = Path.Combine( Path.GetDirectoryName(protoPath), Path.GetFileNameWithoutExtension(protoPath)); argIndex += 1; //First .proto filename is used as output unless specified later if (outputPath == null) { outputPath = protoBase + ".cs"; } //Handle last argument as the output .cs path if (argIndex == args.Length && protoPath.EndsWith(".cs")) { outputPath = protoPath; break; } //Handle last argument as the output path //Filename is taken from first .proto argument if (argIndex == args.Length && protoPath.EndsWith(Path.DirectorySeparatorChar.ToString())) { Directory.CreateDirectory(protoPath); // Replace the original output directory with the custom one outputPath = Path.Combine(protoPath, Path.GetFileName(outputPath)); break; } if (File.Exists(protoPath) == false) { Console.Error.WriteLine("File not found: " + protoPath); return(-1); } try { var proto = new ProtoCollection(); //Parse .proto Console.WriteLine("Parsing " + protoPath); ProtoParser.Parse(protoPath, proto); collection.Merge(proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return(-1); } } Console.WriteLine(collection); //Interpret and reformat try { ProtoPrepare.Prepare(collection); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return(-1); } //Generate code ProtoCode.Save(collection, outputPath); Console.WriteLine("Saved: " + outputPath); return(0); }
/// <summary> /// Generate code for reading and writing protocol buffer messages /// </summary> public static void Save(ProtoCollection file, Options options) { string csPath = options.OutputPath; CodeWriter.DefaultIndentPrefix = options.UseTabs ? "\t" : " "; string ext = Path.GetExtension(csPath); string prefix = csPath.Substring(0, csPath.Length - ext.Length); string csDir = Path.GetDirectoryName(csPath); if (Directory.Exists(csDir) == false) { Directory.CreateDirectory(csDir); } //Basic structures using (var cw = new CodeWriter(csPath)) { cw.Comment(@"Classes and structures being serialized"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run. To make custom modifications, edit the .proto file and add //:external before the message line then write the code and the changes in a separate file."); cw.WriteLine("using System;"); cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); var messageCode = new MessageCode(cw, options); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } if (m.CsNamespace == "global") { ns = null; } else { cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } } messageCode.GenerateClass(m); cw.WriteLine(); } foreach (ProtoEnum e in file.Enums.Values) { if (ns != e.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } cw.Bracket("namespace " + e.CsNamespace); ns = e.CsNamespace; } messageCode.GenerateEnum(e); cw.WriteLine(); } if (ns != null) { cw.EndBracket(); } } //.Serializer.cs //Code for Reading/Writing using (var cw = new CodeWriter(prefix + ".Serializer" + ext)) { cw.Comment(@"This is the backend code for reading and writing"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run."); cw.WriteLine("using System;"); cw.WriteLine("using System.IO;"); cw.WriteLine("using System.Text;"); cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); cw.WriteLine("#pragma warning disable 0472, 0162"); cw.WriteLine(); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time { cw.EndBracket(); } if (m.CsNamespace == "global") { ns = null; } else { cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } } var messageSerializer = new MessageSerializer(cw, options); messageSerializer.GenerateClassSerializer(m); } if (ns != null) { cw.EndBracket(); } } string libPath = Path.Combine(Path.GetDirectoryName(csPath), "ProtocolParser.cs"); using (TextWriter codeWriter = new StreamWriter(libPath, false, Encoding.UTF8)) { codeWriter.NewLine = "\r\n"; ReadCode(codeWriter, "MessageTable", true); ReadCode(codeWriter, "ProtocolParser", false); ReadCode(codeWriter, "ProtocolParserExceptions", false); ReadCode(codeWriter, "ProtocolParserFixed", false); ReadCode(codeWriter, "ProtocolParserKey", false); ReadCode(codeWriter, "ProtocolParserMemory", false); ReadCode(codeWriter, "ProtocolParserVarInt", false); } }
public static int Main(string[] args) { if (args.Length == 0) { Console.Error.WriteLine("Usage:\n\tCodeGenerator.exe [--preserve-names] [--use-tabs] path-to.proto [path-to-second.proto [...]] [output.cs]"); return -1; } ProtoCollection collection = new ProtoCollection(); string outputPath = null; int argIndex = 0; while (args.Length > argIndex && args [argIndex].StartsWith("--")) { switch (args[argIndex]) { case "--preserve-names": ProtoPrepare.ConvertToCamelCase = false; break; case ProtoPrepare.FixNameclashArgument: ProtoPrepare.FixNameclash = true; break; case "--use-tabs": CodeWriter.IndentPrefix = "\t"; break; default: Console.Error.WriteLine("Unknown option: " + args[argIndex]); return -1; } argIndex++; } while (argIndex < args.Length) { string protoPath = Path.GetFullPath(args[argIndex]); string protoBase = Path.Combine( Path.GetDirectoryName(protoPath), Path.GetFileNameWithoutExtension(protoPath)); argIndex += 1; //First .proto filename is used as output unless specified later if (outputPath == null) outputPath = protoBase + ".cs"; //Handle last argument as the output .cs path if (argIndex == args.Length && protoPath.EndsWith(".cs")) { outputPath = protoPath; break; } //Handle last argument as the output path //Filename is taken from first .proto argument if (argIndex == args.Length && protoPath.EndsWith(Path.DirectorySeparatorChar.ToString())) { Directory.CreateDirectory(protoPath); // Replace the original output directory with the custom one outputPath = Path.Combine(protoPath, Path.GetFileName(outputPath)); break; } if (File.Exists(protoPath) == false) { Console.Error.WriteLine("File not found: " + protoPath); return -1; } try { var proto = new ProtoCollection(); //Parse .proto Console.WriteLine("Parsing " + protoPath); ProtoParser.Parse(protoPath, proto); collection.Merge(proto); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return -1; } } Console.WriteLine(collection); //Interpret and reformat try { ProtoPrepare.Prepare(collection); } catch (ProtoFormatException pfe) { Console.WriteLine(); Console.WriteLine(pfe.SourcePath.Path + "(" + pfe.SourcePath.Line + "," + pfe.SourcePath.Column + "): error CS001: " + pfe.Message); return -1; } //Generate code ProtoCode.Save(collection, outputPath); Console.WriteLine("Saved: " + outputPath); return 0; }
static void ParseImport(TokenReader tr, ProtoCollection collection) { string path = tr.ReadNext(); bool publicImport = path == "public"; if (publicImport) path = tr.ReadNext(); tr.ReadNextOrThrow(";"); if (publicImport) collection.ImportPublic.Add(path); else collection.Import.Add(path); }
static void ParseMessages(TokenReader tr, ProtoCollection p) { string package = "Example"; while (true) { string token = tr.ReadNext(); if (ParseComment(token)) continue; try { switch (token) { case ";": lastComment.Clear(); continue; case "message": ParseMessage(tr, p, package); break; case "enum": ParseEnum(tr, p, package); break; case "option": //Save options ParseOption(tr, p); break; case "import": //Ignored tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "package": package = tr.ReadNext(); tr.ReadNextOrThrow(";"); break; case "extend": ParseExtend(tr, p, package); break; default: throw new ProtoFormatException("Unexpected/not implemented: " + token, tr); } } catch (EndOfStreamException) { throw new ProtoFormatException("Unexpected EOF", tr); } } }
/// <summary> /// Generate code for reading and writing protocol buffer messages /// </summary> public static void Save(ProtoCollection file, Options options) { string csPath = options.OutputPath; CodeWriter.DefaultIndentPrefix = options.UseTabs ? "\t" : " "; string ext = Path.GetExtension(csPath); string prefix = csPath.Substring(0, csPath.Length - ext.Length); string csDir = Path.GetDirectoryName(csPath); if (Directory.Exists(csDir) == false) Directory.CreateDirectory(csDir); //Basic structures using (var cw = new CodeWriter(csPath)) { cw.Comment(@"Classes and structures being serialized"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run. To make custom modifications, edit the .proto file and add //:external before the message line then write the code and the changes in a separate file."); cw.WriteLine("using System;"); cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time cw.EndBracket(); cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } MessageCode.GenerateClass(m, cw, options); cw.WriteLine(); } foreach (ProtoEnum e in file.Enums.Values) { if (ns != e.CsNamespace) { if (ns != null) //First time cw.EndBracket(); cw.Bracket("namespace " + e.CsNamespace); ns = e.CsNamespace; } MessageCode.GenerateEnum(e, cw); cw.WriteLine(); } cw.EndBracket(); } //.Serializer.cs //Code for Reading/Writing using (var cw = new CodeWriter(prefix + ".Serializer" + ext)) { cw.Comment(@"This is the backend code for reading and writing"); cw.WriteLine(); cw.Comment(@"Generated by ProtocolBuffer - a pure c# code generation implementation of protocol buffers Report bugs to: https://silentorbit.com/protobuf/"); cw.WriteLine(); cw.Comment(@"DO NOT EDIT This file will be overwritten when CodeGenerator is run."); cw.WriteLine("using System;"); cw.WriteLine("using System.IO;"); cw.WriteLine("using System.Text;"); cw.WriteLine("using System.Collections.Generic;"); cw.WriteLine(); string ns = null; //avoid writing namespace between classes if they belong to the same foreach (ProtoMessage m in file.Messages.Values) { if (ns != m.CsNamespace) { if (ns != null) //First time cw.EndBracket(); cw.Bracket("namespace " + m.CsNamespace); ns = m.CsNamespace; } MessageSerializer.GenerateClassSerializer(m, cw); } cw.EndBracket(); } string libPath = Path.Combine(Path.GetDirectoryName(csPath), "ProtocolParser.cs"); using (TextWriter codeWriter = new StreamWriter(libPath, false, Encoding.UTF8)) { codeWriter.NewLine = "\r\n"; ReadCode(codeWriter, "ProtocolParser", true); ReadCode(codeWriter, "ProtocolParserFixed", false); ReadCode(codeWriter, "ProtocolParserKey", false); ReadCode(codeWriter, "ProtocolParserVarInt", false); } }