public static List <FileDescriptorProto>?Parse(string file, string @namespace) { // https://github.com/protobuf-net/protobuf-net/blob/master/src/protogen/Program.cs#L136 var filePath = Path.GetFullPath(file); var directoryPath = Path.GetDirectoryName(filePath); var fileDescriptorSet = new FileDescriptorSet { DefaultPackage = @namespace }; fileDescriptorSet.AddImportPath(directoryPath); if (!fileDescriptorSet.Add(file, true)) { Console.WriteLine($"Couldn't add file: {file}"); return(null); } fileDescriptorSet.Process(); var errors = fileDescriptorSet.GetErrors(); if (errors.Length > 0) { foreach (var error in errors) { throw new InvalidOperationException(error.ToString()); } } return(fileDescriptorSet.Files); }
static void Generate(string inpath, string[] inprotos, string outpath) { var set = new FileDescriptorSet(); set.AddImportPath(inpath); foreach (var inproto in inprotos) { set.Add(inproto, true); } set.Process(); var errors = set.GetErrors(); CSharpCodeGenerator.ClearTypeNames(); var files = CSharpCodeGenerator.Default.Generate(set); int idx = 1; foreach (var file in files) { EditorUtility.DisplayProgressBar("Generate", file.Name, idx / (1.0f * inprotos.Length)); var path = Path.Combine(outpath, file.Name); File.WriteAllText(path, file.Text); Debug.Log($"generated: {path}"); } EditorUtility.ClearProgressBar(); AssetDatabase.Refresh(); }
public void DescriptorProtoVB() { var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); var path = "descriptor.proto"; var set = new FileDescriptorSet(); set.AddImportPath(schemaPath); set.Add(path, includeInOutput: true); set.Process(); #pragma warning disable CS0618 var sourceFiles = VBCodeGenerator.Default.Generate(set).Select(x => x.Text).ToArray(); #pragma warning restore CS0618 Assert.Single(sourceFiles); _output.WriteLine(sourceFiles[0]); var vb = new VBCodeProvider(new Dictionary <string, string> { { "CompilerVersion", "v3.5" } }); var p = new CompilerParameters { GenerateInMemory = true }; p.ReferencedAssemblies.Add(typeof(ProtoContractAttribute).Assembly.Location); // add protobuf-net reference p.ReferencedAssemblies.Add("System.dll"); // for [DefaultValue] p.ReferencedAssemblies.Add("System.Core.dll"); // for extension methods var results = vb.CompileAssemblyFromSource(p, sourceFiles); Assert.Empty(results.Errors); }
public void LargeDefaultValueIsCorrect() { var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); const string path = "bigIntegerDefaultValue.proto"; var set = new FileDescriptorSet(); set.AddImportPath(schemaPath); set.Add(path, includeInOutput: true); set.Process(); var langver = set.Files[0].Options.GetOptions()?.CSharpLanguageVersion; Assert.Equal("3", langver); var sourceFiles = CSharpCodeGenerator.Default.Generate(set).Select(x => x.Text).ToArray(); Assert.Single(sourceFiles); _output.WriteLine(sourceFiles[0]); var csharp = new CSharpCodeProvider(new Dictionary <string, string> { { "CompilerVersion", "v3.5" } }); var p = new CompilerParameters { GenerateInMemory = true }; p.ReferencedAssemblies.Add(typeof(ProtoContractAttribute).Assembly.Location); // add protobuf-net reference p.ReferencedAssemblies.Add("System.dll"); // for [DefaultValue] p.ReferencedAssemblies.Add("System.Core.dll"); // for extension methods CompilerResults results; try { results = csharp.CompileAssemblyFromSource(p, sourceFiles); Assert.Empty(results.Errors); } catch (PlatformNotSupportedException) { return; } var assembly = results.CompiledAssembly; var messageType = assembly.GetType("TestMessage"); var properties = messageType.GetProperties(); Assert.Equal(2, properties.Length); foreach (var property in properties) { var defaultValueAttribute = (DefaultValueAttribute)Attribute.GetCustomAttribute(property, typeof(DefaultValueAttribute)); Assert.NotNull(defaultValueAttribute); Assert.Equal(18446744073709551615UL, defaultValueAttribute.Value); } }
public GenerateResult Generate(string schema = null, string tooling = null) { if (string.IsNullOrWhiteSpace(schema)) { return(null); } var result = new GenerateResult(); try { using (var reader = new StringReader(schema)) { var set = new FileDescriptorSet { ImportValidator = path => ValidateImport(path), }; set.AddImportPath(Path.Combine(_host.WebRootPath, "protoc")); set.Add("my.proto", true, reader); set.Process(); var errors = set.GetErrors(); if (!ProtocTooling.IsDefined(tooling)) { if (errors.Length > 0) { result.ParserExceptions = errors; } result.Files = CSharpCodeGenerator.Default.Generate(set).ToArray(); } else { // we're going to offer protoc! hold me... if (errors.Length != 0 && schema.Contains("import")) { // code output disabled because of import } else { result.Files = RunProtoc(_host, schema, tooling, out errors); if (errors.Length > 0) { result.ParserExceptions = errors; } } } } } catch (Exception ex) { result.Exception = ex; } return(result); }
private static FileDescriptorSet GetSet(IEnumerable <DirectoryInfo> importPaths) { var set = new FileDescriptorSet(); foreach (var path in importPaths) { set.AddImportPath(path.FullName); } return(set); }
public IActionResult Generate([FromBody] GeneratorViewModel generatorViewModel) { using (var reader = new StringReader(generatorViewModel.ProtoContent)) { var set = new FileDescriptorSet { ImportValidator = path => ValidateImport(path), }; set.AddImportPath(Path.Combine(_host.WebRootPath, "protoc")); set.Add("my.proto", true, reader); set.Process(); var errors = set.GetErrors(); if (errors.Length != 0) { //code parsing is supposed to happening client side, so we don't send error here return(BadRequest()); } if (generatorViewModel.IsProtobugGen()) { return(Ok( generatorViewModel .GetCodeGenerator() .Generate(set, generatorViewModel.GetNameNormalizerForConvention(), generatorViewModel.GetOptions()) .ToList())); } // we're going to offer protoc! hold me... if (generatorViewModel.ProtoContent.Contains("import")) { // code output disabled because of import return(BadRequest()); } else { var files = RunProtoc(_host, generatorViewModel.ProtoContent, generatorViewModel.GetProtocTooling(), out var stdout, out var stderr, out var exitCode); if (exitCode != 0) { return(base.StatusCode(500, new { stderr, stdout, exitCode })); } return(Ok(files)); } } }
public void EverythingProtoLangver3() { Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows)); var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); const string path = "everything.proto"; var set = new FileDescriptorSet(); set.AddImportPath(schemaPath); set.Add(path, includeInOutput: true); set.Process(); var langver = set.Files[0].Options.GetOptions()?.CSharpLanguageVersion; Assert.Equal("3", langver); var sourceFiles = CSharpCodeGenerator.Default.Generate(set).Select(x => x.Text).ToArray(); Assert.Single(sourceFiles); _output.WriteLine(sourceFiles[0]); using var csharp = new CSharpCodeProvider(new Dictionary <string, string> { { "CompilerVersion", "v3.5" } }); var p = new CompilerParameters { GenerateInMemory = true }; p.ReferencedAssemblies.Add(typeof(ProtoContractAttribute).Assembly.Location); // add protobuf-net reference p.ReferencedAssemblies.Add("System.dll"); // for [DefaultValue] p.ReferencedAssemblies.Add("System.Core.dll"); // for extension methods try { var results = csharp.CompileAssemblyFromSource(p, sourceFiles); var count = results.Errors.Count; Assert.Equal(3, count); foreach (CompilerError error in results.Errors) { Assert.Equal("CS0619", error.ErrorNumber); var txt = error.ErrorText; bool expected = txt.StartsWith("'ProtoBuf.ProtoMemberAttribute.AsReference' is obsolete") || txt.StartsWith("'ProtoBuf.ProtoMemberAttribute.DynamicType' is obsolete"); Assert.True(expected); } } catch (PlatformNotSupportedException) { } }
public void CanParseCustomOptionsFromExternalSchema() { var set = new FileDescriptorSet(); set.AddImportPath("./Schemas"); Assert.True(set.Add("nanopb_test.proto")); set.Process(); Assert.Empty(set.GetErrors()); var bar = set.Files.Single(x => x.Name == "nanopb_test.proto") .MessageTypes.Single() .Fields.Single(x => x.Number == 3); // normally you'd just use an "if (Extensible.TryGetValue(...)" here; I'm proving it for the test Assert.True(Extensible.TryGetValue <NanoPBOptions>(RuntimeTypeModel.Default, bar.Options, 1010, out var options)); Assert.True(options.ShouldSerializeMaxSize()); // this is "actively set" vs "set via the default" etc Assert.Equal(42, options.MaxSize); }
public IActionResult Generate([FromBody] GeneratorViewModel generatorViewModel) { using var reader = new StringReader(generatorViewModel.ProtoContent); var set = new FileDescriptorSet { ImportValidator = path => ValidateImport(path), }; set.AddImportPath(Path.Combine(_host.WebRootPath, "protoc")); set.Add("my.proto", true, reader); set.Process(); var errors = set.GetErrors(); if (errors.Length != 0) { //code parsing is supposed to happening client side, so we don't send error here return(BadRequest()); } if (generatorViewModel.IsProtogen()) { return(Ok( generatorViewModel .GetCodeGenerator() .Generate(set, generatorViewModel.GetNameNormalizerForConvention(), generatorViewModel.GetOptions()) .ToList())); } // if we got this far, it means that we resolved all the imports, so // we don't need to worry about protoc going out-of-bounds with external files // (since we constrain with ValidateImport), so: off to 'protoc' we go! var files = RunProtoc(_host, generatorViewModel.ProtoContent, generatorViewModel.GetProtocTooling(), out var stdout, out var stderr, out var exitCode); if (exitCode != 0) { return(base.StatusCode(500, new { stderr, stdout, exitCode })); } return(Ok(files)); }
private static void Generate(string inpath, string[] inprotos, string outpath) { if (!Directory.Exists(outpath)) { Directory.CreateDirectory(outpath); } var set = new FileDescriptorSet(); set.AddImportPath(inpath); foreach (var inproto in inprotos) { var s = inproto; if (!inproto.Contains(".proto")) { s += ".proto"; } set.Add(s, true); } set.Process(); var errors = set.GetErrors(); CSharpCodeGenerator.ClearTypeNames(); var files = CSharpCodeGenerator.Default.Generate(set); foreach (var file in files) { CSharpCodeGenerator.ClearTypeNames(); var path = Path.Combine(outpath, file.Name); File.WriteAllText(path, file.Text); Log.Print($"Generated cs file for {file.Name.Replace(".cs",".proto")} successfully to: {path}"); } EditorUtility.DisplayDialog("Complete", "Proto文件已转CS,详细请看控制台输出" + "\n" + "Proto files has been convert into CS files, please go to console and view details", "Close window"); win.Close(); }
static FileDescriptorSet ParseFiles(Options arguments) { var set = new FileDescriptorSet { DefaultPackage = arguments.Namespace }; set.AddImportPath(Path.GetDirectoryName(arguments.ProtobufPath)); var fileName = Path.GetFileName(arguments.ProtobufPath); if (!set.Add(fileName, includeInOutput: true)) { Console.Error.WriteLine($"Could not find file '{fileName}'."); return(null); } set.Process(); return(set); }
static FileDescriptorSet ReparseFiles(Options arguments, FileDescriptorSet firstPass) { var set = new FileDescriptorSet { DefaultPackage = firstPass.DefaultPackage }; set.AddImportPath(Path.GetDirectoryName(arguments.ProtobufPath)); foreach (var file in firstPass.Files) { if (string.IsNullOrEmpty(file.Syntax)) { file.Syntax = "proto2"; } set.Files.Add(file); } set.Process(); return(set); }
public void EverythingProtoLangver3() { var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); const string path = "everything.proto"; var set = new FileDescriptorSet(); set.AddImportPath(schemaPath); set.Add(path, includeInOutput: true); set.Process(); var langver = set.Files[0].Options.GetOptions()?.CSharpLanguageVersion; Assert.Equal("3", langver); var sourceFiles = CSharpCodeGenerator.Default.Generate(set).Select(x => x.Text).ToArray(); Assert.Single(sourceFiles); _output.WriteLine(sourceFiles[0]); var csharp = new CSharpCodeProvider(new Dictionary <string, string> { { "CompilerVersion", "v3.5" } }); var p = new CompilerParameters { GenerateInMemory = true }; p.ReferencedAssemblies.Add(typeof(ProtoContractAttribute).Assembly.Location); // add protobuf-net reference p.ReferencedAssemblies.Add("System.dll"); // for [DefaultValue] p.ReferencedAssemblies.Add("System.Core.dll"); // for extension methods try { var results = csharp.CompileAssemblyFromSource(p, sourceFiles); Assert.Empty(results.Errors); } catch (PlatformNotSupportedException) { } }
static void Generate(string inpath,string[] inprotos,string outpath) { var set = new FileDescriptorSet(); set.AddImportPath(inpath); foreach (var inproto in inprotos) { set.Add (inproto, true); } set.Process(); var errors = set.GetErrors(); CSharpCodeGenerator.ClearTypeNames (); var files = CSharpCodeGenerator.Default.Generate(set); foreach (var file in files) { var path = Path.Combine(outpath, file.Name); File.WriteAllText(path, file.Text); Debug.Log($"generated: {path}"); } }
static ErrorCode GenerateCode(StreamWriter writer, string basePath, string inputPath, string outputPath, bool current) { string inputFolder = GetFolderName(inputPath); string inputRelativePath = MakeRelativePath(basePath, inputPath); #region Get the list of .proto files. var fileDescriptorSet = new FileDescriptorSet { AllowNameOnlyImport = true, }; fileDescriptorSet.AddImportPath(inputPath); var inputFiles = new List <string>(); foreach (var path in Directory.EnumerateFiles(inputPath, "*.proto", SearchOption.AllDirectories)) { inputFiles.Add(MakeRelativePath(inputPath, path)); } bool error = false; foreach (var proto in inputFiles) { if (!fileDescriptorSet.Add(proto, true)) { error = true; ConsoleOutput.OutputError($"Error Loading: {proto}"); } } if (error) { return(ErrorCode.InvalidProto); } fileDescriptorSet.Process(); var errors = fileDescriptorSet.GetErrors(); if (errors.Length > 0) { foreach (var err in errors) { ConsoleOutput.OutputError(err.ToString()); } return(ErrorCode.FileDescriptorSetProcessFailure); } #endregion Get the list of .proto files. #region Generate the files. Dictionary <string, string> options = new Dictionary <string, string>(); if (!current) { string version = inputFolder; options.Add("PROTO_VERSION", version); outputPath = Path.Combine(outputPath, version); } string outputRelativePath = MakeRelativePath(basePath, outputPath); writer.WriteLine($"<!-- {outputRelativePath} -->"); writer.WriteLine(" <ItemGroup>"); foreach (var file in GM_CSharpCodeGenerator.Default.Generate(fileDescriptorSet, null, options)) { var filePath = Path.Combine(outputPath, file.Name); var fileFolder = Path.GetDirectoryName(filePath); if (!Directory.Exists(fileFolder)) { ConsoleOutput.OutputWarning($"Output directory does not exist, creating... {fileFolder}"); Directory.CreateDirectory(fileFolder); } File.WriteAllText(filePath, file.Text); writer.WriteLine($" <Compile Include=\"{Path.Combine(outputRelativePath, file.Name)}\">"); writer.WriteLine($" <Visible>true</Visible>"); writer.WriteLine($" </Compile>"); ConsoleOutput.OutputSuccess($"generated: {filePath}"); } writer.WriteLine(" </ItemGroup>"); writer.WriteLine(" <ItemGroup>"); foreach (var file in fileDescriptorSet.Files) { writer.WriteLine($" <None Include=\"{Path.Combine(inputRelativePath, file.Name)}\">"); writer.WriteLine($" <Visible>true</Visible>"); writer.WriteLine($" </None>"); } writer.WriteLine(" </ItemGroup>"); writer.WriteLine(); ConsoleOutput.OutputSuccess($"generated: {ProjFile}"); #endregion Generate the files. return(ErrorCode.Success); }
static int Main(string[] args) { try { string outPath = null; // -o{FILE}, --descriptor_set_out={FILE} bool version = false; // --version bool help = false; // -h, --help var importPaths = new List <string>(); // -I{PATH}, --proto_path={PATH} var inputFiles = new List <string>(); // {PROTO_FILES} (everything not `-`) bool exec = false; string package = null; // --package=foo CodeGenerator codegen = null; Dictionary <string, string> options = null; foreach (string arg in args) { string lhs = arg, rhs = ""; int index = arg.IndexOf('='); if (index > 0) { lhs = arg.Substring(0, index); rhs = arg.Substring(index + 1); } else if (arg.StartsWith("-o")) { lhs = "--descriptor_set_out"; rhs = arg.Substring(2); } else if (arg.StartsWith("-I")) { lhs = "--proto_path"; rhs = arg.Substring(2); } if (lhs.StartsWith("+")) { if (options == null) { options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } options[lhs.Substring(1)] = rhs; continue; } switch (lhs) { case "": break; case "--version": version = true; break; case "--package": package = rhs; break; case "-h": case "--help": help = true; break; case "--csharp_out": outPath = rhs; codegen = CSharpCodeGenerator.Default; exec = true; break; case "--vb_out": outPath = rhs; #pragma warning disable CS0618 codegen = VBCodeGenerator.Default; #pragma warning restore CS0618 exec = true; break; case "--descriptor_set_out": outPath = rhs; codegen = null; exec = true; break; case "--proto_path": importPaths.Add(rhs); break; default: if (lhs.StartsWith("-") || !string.IsNullOrWhiteSpace(rhs)) { help = true; break; } else { inputFiles.Add(lhs); } break; } } if (help) { ShowHelp(); return(0); } else if (version) { Console.WriteLine($"protogen {GetVersion<Program>()}"); Console.WriteLine($"protobuf-net {GetVersion<ProtoReader>()}"); Console.WriteLine($"protobuf-net.Reflection {GetVersion<FileDescriptorSet>()}"); return(0); } else if (inputFiles.Count == 0) { Console.Error.WriteLine("Missing input file."); return(-1); } else if (!exec) { Console.Error.WriteLine("Missing output directives."); return(-1); } else { int exitCode = 0; var set = new FileDescriptorSet { DefaultPackage = package }; if (importPaths.Count == 0) { set.AddImportPath(Directory.GetCurrentDirectory()); } else { foreach (var dir in importPaths) { if (Directory.Exists(dir)) { set.AddImportPath(dir); } else { Console.Error.WriteLine($"Directory not found: {dir}"); exitCode = 1; } } } if (inputFiles.Count == 1 && importPaths.Count == 1) { SearchOption?searchOption = null; if (inputFiles[0] == "**/*.proto" || inputFiles[0] == "**\\*.proto") { searchOption = SearchOption.AllDirectories; set.AllowNameOnlyImport = true; } else if (inputFiles[0] == "*.proto") { searchOption = SearchOption.TopDirectoryOnly; } if (searchOption != null) { inputFiles.Clear(); var searchRoot = importPaths[0]; foreach (var path in Directory.EnumerateFiles(importPaths[0], "*.proto", searchOption.Value)) { inputFiles.Add(MakeRelativePath(searchRoot, path)); } } } foreach (var input in inputFiles) { if (!set.Add(input, true)) { Console.Error.WriteLine($"File not found: {input}"); exitCode = 1; } } if (exitCode != 0) { return(exitCode); } set.Process(); var errors = set.GetErrors(); foreach (var err in errors) { if (err.IsError) { exitCode++; } Console.Error.WriteLine(err.ToString()); } if (exitCode != 0) { return(exitCode); } if (codegen == null) { using (var fds = File.Create(outPath)) { Serializer.Serialize(fds, set); } } var files = codegen.Generate(set, options: options); foreach (var file in files) { var path = Path.Combine(outPath, file.Name); var dir = Path.GetDirectoryName(path); if (!Directory.Exists(dir)) { Console.Error.WriteLine($"Output directory does not exist, creating... {dir}"); Directory.CreateDirectory(dir); } File.WriteAllText(path, file.Text); Console.WriteLine($"generated: {path}"); } return(0); } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); return(-1); } }
public bool WriteLuaFile() { DirectoryInfo scanDir = new DirectoryInfo(Path.GetFullPath(m_strProtoPath)); FileDescriptorSet lset = new FileDescriptorSet(); lset.AddImportPath(Directory.GetCurrentDirectory()); lset.AddImportPath(Path.GetFullPath(m_strProtoPath)); var files = GenLuaForProto.GetFilesExclude(scanDir);// scanDir.GetFiles("*.proto", SearchOption.TopDirectoryOnly); foreach (FileInfo file in files) { string proto_file = file.FullName.Replace(scanDir.FullName + Path.DirectorySeparatorChar, ""); //int exitCode = 0; if (!lset.Add(proto_file, true)) { //exitCode = 1; } } lset.Process(); string dirPath = Path.GetFullPath(m_strOutputFile); dirPath = Path.GetDirectoryName(dirPath); //Write using (FileStream fs = new FileStream(m_strOutputFile, FileMode.Create, FileAccess.Write)) { using (StreamWriter sw = new StreamWriter(fs, new System.Text.UTF8Encoding(false))) { WriteRequireBegin(sw); string createPath = Path.GetFullPath(dirPath + "/" + m_ns); if (!Directory.Exists(createPath)) { Directory.CreateDirectory(createPath); } foreach (FileDescriptorProto fileDesc in lset.Files) { foreach (DescriptorProto desc in fileDesc.MessageTypes) { if (desc.EnumTypes.Count != 0) { string createFile = Path.GetFullPath(createPath + "/" + desc.Name + "_EnumTypes.lua"); using (FileStream luaFileS = new FileStream(createFile, FileMode.Create, FileAccess.Write)) { using (StreamWriter luaFileW = new StreamWriter(luaFileS, new System.Text.UTF8Encoding(false))) { WriteRequire(sw, desc.Name); WriteEnumLuaHeaderBegin(luaFileW, fileDesc.Name, desc.Name); foreach (EnumDescriptorProto enumDesc in desc.EnumTypes) { WriteEnumLuaBegin(luaFileW, enumDesc.Name); foreach (EnumValueDescriptorProto enumValDesc in enumDesc.Values) { WriteEnumLuaValue(luaFileW, enumValDesc.Name, enumValDesc.Number); } WriteEnumLuaEnd(luaFileW, enumDesc.Name); } WriteEnumLuaHeaderEnd(luaFileW); luaFileW.Close(); } luaFileS.Close(); } } } } WriteRequireEnd(sw); sw.Close(); } fs.Close(); } return(true); }
public override bool Execute() { var codegen = GetCodeGenForLanguage(Language); if (ProtoDef == null || ProtoDef.Length == 0) { return(true); } var set = new FileDescriptorSet { DefaultPackage = DefaultNamespace }; if (ImportPaths == null || ImportPaths.Length == 0) { set.AddImportPath(Directory.GetCurrentDirectory()); } else { foreach (var dir in ImportPaths) { if (Directory.Exists(dir.ItemSpec)) { set.AddImportPath(dir.ItemSpec); } else { this.Log.LogError($"Directory not found: {dir}"); return(false); } } } foreach (var input in ProtoDef) { if (!set.Add(input.ItemSpec, true)) { Log.LogError($"File not found: {input}"); return(false); } } set.Process(); var errors = set.GetErrors(); if (errors != null && errors.Length > 0) { foreach (var error in errors) { var endCol = error.LineNumber + error.Text.Length; int errNum = error.ErrorNumber; var errCode = errNum == 0 ? null : ("PBN" + errNum.ToString("0000")); if (error.IsError) { this.Log.LogError("protogen", errCode, null, error.File, error.LineNumber, error.ColumnNumber, error.LineNumber, endCol, error.Message); } else if (error.IsWarning) { this.Log.LogWarning("protogen", errCode, null, error.File, error.LineNumber, error.ColumnNumber, error.LineNumber, endCol, error.Message); } } return(false); } var options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var codeFiles = new List <ITaskItem>(); var files = codegen.Generate(set, options: options); foreach (var file in files) { var path = Path.Combine(OutputPath, file.Name); var dir = Path.GetDirectoryName(path); Directory.CreateDirectory(dir); File.WriteAllText(path, file.Text); codeFiles.Add(new TaskItem(path)); } this.ProtoCodeFile = codeFiles.Cast <ITaskItem>().ToArray(); return(true); }
public void CompareProtoToParser(string path) { var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); _output.WriteLine(Path.GetDirectoryName( Path.Combine(schemaPath, path).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))); bool includeComments = IncludeComments(path); var protocBinPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "protoc.bin")); int exitCode; using (var proc = new Process()) { var psi = proc.StartInfo; psi.FileName = "protoc"; psi.Arguments = $"--descriptor_set_out={protocBinPath} {path}"; if (includeComments) { psi.Arguments += " --include_source_info"; } psi.RedirectStandardError = psi.RedirectStandardOutput = true; psi.UseShellExecute = false; psi.WorkingDirectory = schemaPath; proc.Start(); var stdout = proc.StandardOutput.ReadToEndAsync(); var stderr = proc.StandardError.ReadToEndAsync(); if (!proc.WaitForExit(5000)) { try { proc.Kill(); } catch { } } exitCode = proc.ExitCode; string err = "", @out = ""; if (stdout.Wait(1000)) { @out = stdout.Result; } if (stderr.Wait(1000)) { err = stderr.Result; } if (!string.IsNullOrWhiteSpace(@out)) { _output.WriteLine("stdout: "); _output.WriteLine(@out); } if (!string.IsNullOrWhiteSpace(err)) { _output.WriteLine("stderr: "); _output.WriteLine(err); } } FileDescriptorSet set; string protocJson = null, jsonPath; if (exitCode == 0) { using (var file = File.OpenRead(protocBinPath)) { set = Serializer.Deserialize <FileDescriptorSet>(file); protocJson = JsonConvert.SerializeObject(set, Formatting.Indented, jsonSettings); jsonPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "protoc.json")); File.WriteAllText(jsonPath, protocJson); } } set = new FileDescriptorSet(); set.AddImportPath(schemaPath); bool isProto3 = set.Add(path, includeInOutput: true) && set.Files[0].Syntax == "proto3"; if (isProto3) { using (var proc = new Process()) { var psi = proc.StartInfo; psi.FileName = "protoc"; psi.Arguments = $"--csharp_out={Path.GetDirectoryName(protocBinPath)} {path}"; psi.RedirectStandardError = psi.RedirectStandardOutput = true; psi.UseShellExecute = false; psi.WorkingDirectory = schemaPath; proc.Start(); var stdout = proc.StandardOutput.ReadToEndAsync(); var stderr = proc.StandardError.ReadToEndAsync(); if (!proc.WaitForExit(5000)) { try { proc.Kill(); } catch { } } exitCode = proc.ExitCode; string err = "", @out = ""; if (stdout.Wait(1000)) { @out = stdout.Result; } if (stderr.Wait(1000)) { err = stderr.Result; } if (!string.IsNullOrWhiteSpace(@out)) { _output.WriteLine("stdout (C#): "); _output.WriteLine(@out); } if (!string.IsNullOrWhiteSpace(err)) { _output.WriteLine("stderr (C#): "); _output.WriteLine(err); } _output.WriteLine("exit code(C#): " + exitCode); } } set.Process(); var parserBinPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "parser.bin")); using (var file = File.Create(parserBinPath)) { set.Serialize(file, false); } var parserJson = set.Serialize((s, o) => JsonConvert.SerializeObject(s, Formatting.Indented, jsonSettings), false); var errors = set.GetErrors(); Exception genError = null; try { foreach (var file in CSharpCodeGenerator.Default.Generate(set)) { var newExtension = "parser" + Path.GetExtension(file.Name); var newFileName = Path.ChangeExtension(file.Name, newExtension); File.WriteAllText(Path.Combine(schemaPath, newFileName), file.Text); } } catch (Exception ex) { genError = ex; _output.WriteLine(ex.Message); _output.WriteLine(ex.StackTrace); } jsonPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "parser.json")); File.WriteAllText(jsonPath, parserJson); if (errors.Any()) { _output.WriteLine("Parser errors:"); foreach (var err in errors) { _output.WriteLine(err.ToString()); } } _output.WriteLine("Protoc exited with code " + exitCode); var errorCount = errors.Count(x => x.IsError); if (exitCode == 0) { Assert.Equal(0, errorCount); } else { Assert.NotEqual(0, errorCount); } var parserBytes = File.ReadAllBytes(parserBinPath); using (var ms = new MemoryStream(parserBytes)) { var selfLoad = Serializer.Deserialize <FileDescriptorSet>(ms); var selfLoadJson = JsonConvert.SerializeObject(selfLoad, Formatting.Indented, jsonSettings); // should still be the same! Assert.Equal(parserJson, selfLoadJson); } var parserHex = GetPrettyHex(parserBytes); File.WriteAllText(Path.ChangeExtension(parserBinPath, "parser.hex"), parserHex); if (exitCode == 0) { var protocHex = GetPrettyHex(File.ReadAllBytes(protocBinPath)); File.WriteAllText(Path.ChangeExtension(protocBinPath, "protoc.hex"), protocHex); switch (path) { case "google/protobuf/unittest_custom_options.proto": // this is a special case; the two encoders choose slightly different // layouts for the same data; both are valid; I'm happy that this is OK // - this was why the "decode" tool (on the website) was written! break; default: // compare results Assert.Equal(protocJson, parserJson); Assert.Equal(protocHex, parserHex); break; } } Assert.Null(genError); }
public bool ReadFile() { //Read using (StreamReader sr = new StreamReader(m_strInputFile, new System.Text.UTF8Encoding(false))) { string str = sr.ReadToEnd(); //匹配所有得到MSGTYPE_DECLARE string regstr = @"MSGTYPE_DECLARE[\s\S]*"; Match m = Regex.Match(str, regstr, RegexOptions.IgnoreCase | RegexOptions.Multiline); //匹配所有的MSGTYPE_DECLARE()中的内容 string regstr1 = @"^MSGTYPE_DECLARE\((?<MsgDefine>[\s\S]*?)\)"; MatchCollection mCollect = Regex.Matches(m.Value, regstr1, RegexOptions.IgnoreCase | RegexOptions.Multiline); //去空格、制表符 List <string> lstParse = new List <string>(); foreach (Match v in mCollect) { string sv = Regex.Replace(v.Groups["MsgDefine"].Value, @"[\s]|[\t]*", ""); lstParse.Add(sv); } //解析每一行 Dictionary <string, uint> dctNameToType = new Dictionary <string, uint>(); Dictionary <uint, List <string> > dctTypeToName = new Dictionary <uint, List <string> >(); //这个对象存储去掉_的消息号 Dictionary <uint, List <string> > dctTypeToNameParse = new Dictionary <uint, List <string> >(); Action <uint, string> actAddMsg = (uint stype, string sname) => { dctNameToType[sname] = stype; List <string> lst = null; if (dctTypeToName.TryGetValue(stype, out lst)) { lst.Add(sname); } else { lst = new List <string>(); lst.Add(sname); dctTypeToName[stype] = lst; } lst = null; if (dctTypeToNameParse.TryGetValue(stype, out lst)) { lst.Add(sname.Replace("_", "")); } else { lst = new List <string>(); lst.Add(sname.Replace("_", "")); dctTypeToNameParse[stype] = lst; } }; foreach (var v in lstParse) { //_MSG_CREATE_GAME,_MSG_LP_SERVER_BASE+1 string[] a1 = v.Split(','); if (a1.Length == 2) { //a1[0] = _MSG_CREATE_GAME string name = a1[0]; //a1[1] = _MSG_LP_SERVER_BASE + 1 string type = a1[1]; //_MSG_LP_SERVER_BASE+1 string[] atype = type.Split('+'); if (atype.Length == 2) { uint basetype = 0; if (dctNameToType.TryGetValue(atype[0], out basetype)) { uint stype = 0; if (uint.TryParse(atype[1], out stype)) { stype += basetype; actAddMsg(stype, name); } else { } } } else { uint stype = 0; if (uint.TryParse(atype[0], out stype)) { actAddMsg(stype, name); } else { //重定义的消息,如MSGTYPE_DECLARE( _MSG_BOOTH , _MSG_ACTION) if (dctNameToType.TryGetValue(atype[0], out stype)) { actAddMsg(stype, name); } } } } } //解析Proto Func <DirectoryInfo, string, FileDescriptorSet> lambdaFunc = (DirectoryInfo scanDir, string exclude_suffix) => { FileDescriptorSet lset = new FileDescriptorSet(); lset.AddImportPath(Directory.GetCurrentDirectory()); lset.AddImportPath(scanDir.FullName); var files = GenLuaForProto.GetFilesExclude(scanDir, exclude_suffix);// scanDir.GetFiles("*.proto", SearchOption.TopDirectoryOnly); foreach (FileInfo file in files) { string proto_file = file.FullName.Replace(scanDir.FullName + Path.DirectorySeparatorChar, ""); //int exitCode = 0; if (!lset.Add(proto_file, true)) { //exitCode = 1; } } lset.Process(); return(lset); }; //拿到所有解析完的Proto文件做分析对比 allProtoSet = lambdaFunc(new DirectoryInfo(m_strProtoPath), null); excludeLuaProtoSet = lambdaFunc(new DirectoryInfo(m_strProtoPath), GenLuaForProto.LUASuffix); //dctTypeToNameParse = dctTypeToNameParse.OrderByDescending(p => p.Key).ToDictionary(p => p.Key, o => o.Value); #region forcs foreach (FileDescriptorProto v in allProtoSet.Files) { foreach (DescriptorProto vi in v.MessageTypes) { string src = vi.Name; bool bFind = false; foreach (var vj in dctTypeToNameParse) { foreach (var vk in vj.Value) { //先一次精确匹配,再一次模糊搜索 string key = vk; if (src.Equals(key, StringComparison.OrdinalIgnoreCase)) { bFind = true; if (v.Package.Length == 0) { m_typeToMsg[vj.Key] = vi.Name; } else { m_typeToMsg[vj.Key] = v.Package + "." + vi.Name; } break; } } } if (!bFind) { foreach (var vj in dctTypeToNameParse) { foreach (var vk in vj.Value) { string key = vk; string key2 = "(?is)"; for (int i = 0; i < key.Length; ++i) { key2 += key[i].ToString(); if (i < key.Length - 1) { key2 += @"\s*"; } } Match mj = Regex.Match(src, key2, RegexOptions.Singleline | RegexOptions.IgnoreCase); if (mj.Success && !m_typeToMsg.ContainsKey(vj.Key)) { bFind = true; if (v.Package.Length == 0) { m_typeToMsg[vj.Key] = vi.Name; } else { m_typeToMsg[vj.Key] = v.Package + "." + vi.Name; } break; } } } } } } #endregion forcs foreach (FileDescriptorProto v in excludeLuaProtoSet.Files) { foreach (DescriptorProto vi in v.MessageTypes) { AddMessages(vi, v.Package);//把所有message缓存起来 } } foreach (var kv in Messages) { string ns = "Magic.Cougar"; string cls_name = kv.Key; Dictionary <string, DescriptorProto> dic; if (!cls_name.StartsWith(ns)) { ns = kv.Key.Substring(0, cls_name.IndexOf(".")); } if (NameSapceMessages.ContainsKey(ns)) { NameSapceMessages.TryGetValue(ns, out dic); } else { dic = new Dictionary <string, DescriptorProto>(); NameSapceMessages.Add(ns, dic); } dic.Add(cls_name, kv.Value); } #region forexcludelua foreach (FileDescriptorProto v in excludeLuaProtoSet.Files) { foreach (DescriptorProto vi in v.MessageTypes) { string src = vi.Name; bool bFind = false; foreach (var vj in dctTypeToNameParse) { foreach (var vk in vj.Value) { //先一次精确匹配,再一次模糊搜索 string key = vk; if (src.Equals(key, StringComparison.OrdinalIgnoreCase)) { bFind = true; if (v.Package.Length == 0) { m_typeToExcludeLuaMsg[vj.Key] = vi.Name; } else { m_typeToExcludeLuaMsg[vj.Key] = v.Package + "." + vi.Name; } break; } } } if (!bFind) { foreach (var vj in dctTypeToNameParse) { foreach (var vk in vj.Value) { string key = vk; string key2 = "(?is)"; for (int i = 0; i < key.Length; ++i) { key2 += key[i].ToString(); if (i < key.Length - 1) { key2 += @"\s*"; } } Match mj = Regex.Match(src, key2, RegexOptions.Singleline | RegexOptions.IgnoreCase); if (mj.Success && !m_typeToExcludeLuaMsg.ContainsKey(vj.Key)) { bFind = true; if (v.Package.Length == 0) { m_typeToExcludeLuaMsg[vj.Key] = vi.Name; } else { m_typeToExcludeLuaMsg[vj.Key] = v.Package + "." + vi.Name; } break; } } } } if (bFind) { DescriptorProto proto_msg; Messages.TryGetValue(GetMessageCSharpName(vi, v.Package), out proto_msg); AddMessagesToReset(proto_msg, v); continue; } } } #endregion forexcludelua //foreach(var kv in MessagesReceive) //{ // Console.WriteLine(kv.Key + "=======" + kv.Value.Name); //} //排序 m_typeToMsg = m_typeToMsg.OrderBy(p => p.Key).ToDictionary(p => p.Key, o => o.Value); m_typeToExcludeLuaMsg = m_typeToExcludeLuaMsg.OrderBy(p => p.Key).ToDictionary(p => p.Key, o => o.Value); } return(true); }
private static async Task <int> Main(string[] args) { try { string outPath = null; // -o{FILE}, --descriptor_set_out={FILE} bool version = false; // --version bool help = false; // -h, --help var importPaths = new List <string>(); // -I{PATH}, --proto_path={PATH} var inputFiles = new List <string>(); // {PROTO_FILES} (everything not `-`) bool exec = false; string package = null; // --package=foo string grpcMode = null, grpcUrl = null, grpcService = null; CodeGenerator codegen = null; Dictionary <string, string> options = null; for (int i = 0; i < args.Length; i++) { var arg = args[i]; string lhs = arg, rhs = ""; int index = arg.IndexOf('='); if (index > 0) { lhs = arg.Substring(0, index); rhs = arg.Substring(index + 1); } else if (arg.StartsWith("-o")) { lhs = "--descriptor_set_out"; rhs = arg.Substring(2); } else if (arg.StartsWith("-I")) { lhs = "--proto_path"; rhs = arg.Substring(2); } if (lhs.StartsWith("+")) { if (options == null) { options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } options[lhs.Substring(1)] = rhs; continue; } switch (lhs) { case "": break; case "--version": version = true; break; case "--package": package = rhs; break; case "-h": case "--help": help = true; break; case "--csharp_out": outPath = rhs; codegen = CSharpCodeGenerator.Default; exec = true; break; case "--vb_out": outPath = rhs; #pragma warning disable CS0618 codegen = VBCodeGenerator.Default; #pragma warning restore CS0618 exec = true; break; case "--descriptor_set_out": outPath = rhs; codegen = null; exec = true; break; case "--proto_path": importPaths.Add(rhs); break; case "--pwd": Console.WriteLine($"Current Directory: {Directory.GetCurrentDirectory()}"); #if NETCOREAPP2_1 || NETSTANDARD2_0 Console.WriteLine($"Program: {typeof(Program).Assembly.Location}"); Console.WriteLine($"CodeGenerator: {typeof(CodeGenerator).Assembly.Location}"); #endif break; case "--grpc": if (++i < args.Length) { grpcMode = args[i]; if (++i < args.Length) { grpcUrl = args[i]; if (string.Equals(grpcMode, "get", StringComparison.OrdinalIgnoreCase) && ++i < args.Length) { grpcService = args[i]; } } } break; default: if (lhs.StartsWith("-") || !string.IsNullOrWhiteSpace(rhs)) { help = true; break; } else { inputFiles.Add(lhs); } break; } } if (help) { ShowHelp(); return(0); } else if (version) { var ver = GetVersion(typeof(Program)); Console.WriteLine($"protogen {ver}"); var tmp = GetVersion <ProtoReader>(); if (tmp != ver) { Console.WriteLine($"protobuf-net {tmp}"); } tmp = GetVersion <FileDescriptorSet>(); if (tmp != ver) { Console.WriteLine($"protobuf-net.Reflection {tmp}"); } return(0); } else if (grpcMode is object) { #if GRPC_TOOLS return(await GrpcTools.ExecuteAsync(grpcMode, grpcUrl, grpcService, codegen, outPath, options)); #else Console.Error.Write("gRPC tools are not available on this platform"); await Task.Yield(); // this is just to make the compiler happy, and doesn't really matter return(1); #endif } else if (inputFiles.Count == 0) { Console.Error.WriteLine("Missing input file."); return(-1); } else if (!exec) { Console.Error.WriteLine("Missing output directives."); return(-1); } else { int exitCode = 0; var set = new FileDescriptorSet { DefaultPackage = package }; if (importPaths.Count == 0) { set.AddImportPath(Directory.GetCurrentDirectory()); } else { foreach (var dir in importPaths) { if (Directory.Exists(dir)) { set.AddImportPath(dir); } else { Console.Error.WriteLine($"Directory not found: {dir}"); exitCode = 1; } } } // add the library area for auto-imports (library inbuilts) set.AddImportPath(Path.GetDirectoryName(typeof(Program).Assembly.Location)); if (inputFiles.Count == 1 && importPaths.Count == 1) { SearchOption?searchOption = null; if (inputFiles[0] == "**/*.proto" || inputFiles[0] == "**\\*.proto") { searchOption = SearchOption.AllDirectories; set.AllowNameOnlyImport = true; } else if (inputFiles[0] == "*.proto") { searchOption = SearchOption.TopDirectoryOnly; } if (searchOption != null) { inputFiles.Clear(); var searchRoot = importPaths[0]; foreach (var path in Directory.EnumerateFiles(importPaths[0], "*.proto", searchOption.Value)) { inputFiles.Add(MakeRelativePath(searchRoot, path)); } } } foreach (var input in inputFiles) { if (!set.Add(input, true)) { Console.Error.WriteLine($"File not found: {input}"); exitCode = 1; } } if (exitCode != 0) { return(exitCode); } set.Process(); var errors = set.GetErrors(); foreach (var err in errors) { if (err.IsError) { exitCode++; } Console.Error.WriteLine(err.ToString()); } if (exitCode != 0) { return(exitCode); } if (codegen == null) { using (var fds = File.Create(outPath)) { Serializer.Serialize(fds, set); } return(0); } var files = codegen.Generate(set, options: options); WriteFiles(files, outPath); return(0); } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); return(-1); } }
public override bool Execute() { var codegen = GetCodeGenForLanguage(Language); if (ProtoDef == null || ProtoDef.Length == 0) { return(true); } var set = new FileDescriptorSet { DefaultPackage = DefaultNamespace }; if (ImportPaths == null || ImportPaths.Length == 0) { set.AddImportPath(Directory.GetCurrentDirectory()); } else { foreach (var dir in ImportPaths) { if (Directory.Exists(dir.ItemSpec)) { set.AddImportPath(dir.ItemSpec); } else { this.Log.LogError($"Directory not found: {dir}"); return(false); } } } foreach (var input in ProtoDef) { if (!set.Add(input.ItemSpec, true)) { Log.LogError($"File not found: {input}"); return(false); } } set.Process(); var options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); var codeFiles = new List <ITaskItem>(); var files = codegen.Generate(set, options: options); foreach (var file in files) { var path = Path.Combine(OutputPath, file.Name); var dir = Path.GetDirectoryName(path); Directory.CreateDirectory(dir); File.WriteAllText(path, file.Text); codeFiles.Add(new TaskItem(path)); } this.ProtoCodeFile = codeFiles.Cast <ITaskItem>().ToArray(); return(true); }
static int Main(string[] args) { try { string outPath = null; // -o{FILE}, --descriptor_set_out={FILE} bool version = false; // --version bool help = false; // -h, --help var importPaths = new List <string>(); // -I{PATH}, --proto_path={PATH} var inputFiles = new List <string>(); // {PROTO_FILES} (everything not `-`) bool exec = false; CodeGenerator codegen = null; foreach (string arg in args) { string lhs = arg, rhs = ""; int index = arg.IndexOf('='); if (index > 0) { lhs = arg.Substring(0, index); rhs = arg.Substring(index + 1); } else if (arg.StartsWith("-o")) { lhs = "--descriptor_set_out"; rhs = arg.Substring(2); } else if (arg.StartsWith("-I")) { lhs = "--proto_path"; rhs = arg.Substring(2); } switch (lhs) { case "": break; case "--version": version = true; break; case "-h": case "--help": help = true; break; case "--csharp_out": outPath = rhs; codegen = CSharpCodeGenerator.Default; exec = true; break; case "--descriptor_set_out": outPath = rhs; codegen = null; exec = true; break; case "--proto_path": importPaths.Add(rhs); break; default: if (lhs.StartsWith("-") || !string.IsNullOrWhiteSpace(rhs)) { help = true; break; } else { inputFiles.Add(lhs); } break; } } if (help) { ShowHelp(); return(0); } else if (version) { Console.WriteLine($"protogen {GetVersion<Program>()}"); Console.WriteLine($"protobuf-net {GetVersion<ProtoReader>()}"); Console.WriteLine($"protobuf-net.Reflection {GetVersion<FileDescriptorSet>()}"); return(0); } else if (inputFiles.Count == 0) { Console.Error.WriteLine("Missing input file."); return(-1); } else if (!exec) { Console.Error.WriteLine("Missing output directives."); return(-1); } else { int exitCode = 0; var set = new FileDescriptorSet(); if (importPaths.Count == 0) { set.AddImportPath(Directory.GetCurrentDirectory()); } else { foreach (var dir in importPaths) { if (Directory.Exists(dir)) { set.AddImportPath(dir); } else { Console.Error.WriteLine($"Directory not found: {dir}"); exitCode = 1; } } } foreach (var input in inputFiles) { if (!set.Add(input, true)) { Console.Error.WriteLine($"File not found: {input}"); exitCode = 1; } } if (exitCode != 0) { return(exitCode); } set.Process(); var errors = set.GetErrors(); foreach (var err in errors) { if (err.IsError) { exitCode++; } Console.Error.WriteLine(err.ToString()); } if (exitCode != 0) { return(exitCode); } if (codegen == null) { using (var fds = File.Create(outPath)) { Serializer.Serialize(fds, set); } } else { var files = codegen.Generate(set); foreach (var file in files) { var path = Path.Combine(outPath, file.Name); File.WriteAllText(path, file.Text); Console.WriteLine($"generated: {path}"); } } return(0); } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); return(-1); } }
private int Export() { textBox3.Text = ""; System.Text.StringBuilder tnewmsg = new StringBuilder(); int exitCode = 0; mSPath = textBox1.Text; mDPaht = textBox2.Text; if (string.IsNullOrEmpty(mSPath) || string.IsNullOrEmpty(mDPaht)) { return(1); } string tpathfile = Directory.GetCurrentDirectory() + mPathsFile; StringBuilder tstrb = new StringBuilder(); tstrb.AppendLine(mSPath); tstrb.AppendLine(mDPaht); File.WriteAllText(tpathfile, tstrb.ToString()); tnewmsg.AppendLine(System.DateTime.Now.ToString() + ":开始导出."); textBox3.Text = tnewmsg.ToString(); ILCodeGen codegen = ILCodeGen.Default; var set = new FileDescriptorSet(); set.AddImportPath(mSPath); string[] tpaths = Directory.GetDirectories(mSPath); foreach (string tp in tpaths) { set.AddImportPath(tp); } DirectoryInfo tdirfolder = new DirectoryInfo(mSPath); FileInfo[] tfileinfos = tdirfolder.GetFiles("*.proto", System.IO.SearchOption.AllDirectories); foreach (var input in tfileinfos) { if (!set.Add(input.Name, true)) { Console.Error.WriteLine($"File not found: {input}"); exitCode = 1; } } set.Process(); var errors = set.GetErrors(); foreach (var err in errors) { if (err.IsError) { exitCode++; } tnewmsg.AppendLine(err.ToString()); Console.Error.WriteLine(err.ToString()); } textBox3.Text = tnewmsg.ToString(); if (exitCode != 0) { return(exitCode); } var files = codegen.Generate(set); foreach (var file in files) { var path = Path.Combine(mDPaht, file.Name); File.WriteAllText(path, file.Text); } tnewmsg.AppendLine(System.DateTime.Now.ToString() + ":导出结束."); textBox3.Text = tnewmsg.ToString(); return(0); }
public void CompareProtoToParser(string path, bool includeImports) { if (path == "google/protobuf/map_unittest_proto3.proto") { return; // TODO known oddity } var schemaPath = Path.Combine(Directory.GetCurrentDirectory(), SchemaPath); _output.WriteLine(Path.GetDirectoryName( Path.Combine(schemaPath, path).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar))); bool includeComments = IncludeComments(path); var protocBinPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "protoc.bin")); int exitCode; string protocExe = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? @"windows\protoc" : RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? @"macosx/protoc" : ""; if (string.IsNullOrWhiteSpace(protocExe)) { throw new PlatformNotSupportedException(RuntimeInformation.OSDescription); } using (var proc = new Process()) { var psi = proc.StartInfo; psi.FileName = protocExe; psi.Arguments = $"--experimental_allow_proto3_optional --descriptor_set_out={protocBinPath} {path}"; if (includeComments) { psi.Arguments += " --include_source_info"; } if (includeImports) { psi.Arguments += " --include_imports"; } psi.RedirectStandardError = psi.RedirectStandardOutput = true; psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.WorkingDirectory = schemaPath; proc.Start(); var stdout = proc.StandardOutput.ReadToEndAsync(); var stderr = proc.StandardError.ReadToEndAsync(); if (!proc.WaitForExit(5000)) { try { proc.Kill(); } catch { } } exitCode = proc.ExitCode; string err = "", @out = ""; if (stdout.Wait(1000)) { @out = stdout.Result; } if (stderr.Wait(1000)) { err = stderr.Result; } if (!string.IsNullOrWhiteSpace(@out)) { _output.WriteLine("stdout: "); _output.WriteLine(@out); } if (!string.IsNullOrWhiteSpace(err)) { _output.WriteLine("stderr: "); _output.WriteLine(err); } } FileDescriptorSet set; string protocJson = null, jsonPath; if (exitCode == 0) { using var file = File.OpenRead(protocBinPath); set = CustomProtogenSerializer.Instance.Deserialize <FileDescriptorSet>(file); protocJson = JsonConvert.SerializeObject(set, Formatting.Indented, jsonSettings); jsonPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "protoc.json")); File.WriteAllText(jsonPath, protocJson); } set = new FileDescriptorSet(); set.AddImportPath(schemaPath); bool isProto3 = set.Add(path, includeInOutput: true) && set.Files[0].Syntax == "proto3"; if (isProto3) { using var proc = new Process(); var psi = proc.StartInfo; psi.FileName = protocExe; psi.Arguments = $"--experimental_allow_proto3_optional --csharp_out={Path.GetDirectoryName(protocBinPath)} {path}"; psi.RedirectStandardError = psi.RedirectStandardOutput = true; psi.CreateNoWindow = true; psi.UseShellExecute = false; psi.WorkingDirectory = schemaPath; proc.Start(); var stdout = proc.StandardOutput.ReadToEndAsync(); var stderr = proc.StandardError.ReadToEndAsync(); if (!proc.WaitForExit(5000)) { try { proc.Kill(); } catch { } } exitCode = proc.ExitCode; string err = "", @out = ""; if (stdout.Wait(1000)) { @out = stdout.Result; } if (stderr.Wait(1000)) { err = stderr.Result; } if (!string.IsNullOrWhiteSpace(@out)) { _output.WriteLine("stdout (C#): "); _output.WriteLine(@out); } if (!string.IsNullOrWhiteSpace(err)) { _output.WriteLine("stderr (C#): "); _output.WriteLine(err); } _output.WriteLine("exit code(C#): " + exitCode); } set.Process(); set.ApplyFileDependencyOrder(); var parserBinPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "parser.bin")); using (var file = File.Create(parserBinPath)) { set.Serialize(CustomProtogenSerializer.Instance, file, includeImports); } var parserJson = set.Serialize((s, _) => JsonConvert.SerializeObject(s, Formatting.Indented, jsonSettings), includeImports); var errors = set.GetErrors(); Exception genError = null; try { var options = new Dictionary <string, string> { { "services", "true" }, }; foreach (var file in CSharpCodeGenerator.Default.Generate(set, options: options)) { var newExtension = "parser" + Path.GetExtension(file.Name); var newFileName = Path.ChangeExtension(file.Name, newExtension); File.WriteAllText(Path.Combine(schemaPath, newFileName), file.Text); } } catch (Exception ex) { genError = ex; _output.WriteLine(ex.Message); _output.WriteLine(ex.StackTrace); } jsonPath = Path.Combine(schemaPath, Path.ChangeExtension(path, "parser.json")); File.WriteAllText(jsonPath, parserJson); if (errors.Length > 0) { _output.WriteLine("Parser errors:"); foreach (var err in errors) { _output.WriteLine(err.ToString()); } } _output.WriteLine("Protoc exited with code " + exitCode); var errorCount = errors.Count(x => x.IsError); if (exitCode == 0) { Assert.Equal(0, errorCount); } else { Assert.NotEqual(0, errorCount); } var parserBytes = File.ReadAllBytes(parserBinPath); using (var ms = new MemoryStream(parserBytes)) { var selfLoad = CustomProtogenSerializer.Instance.Deserialize <FileDescriptorSet>(ms); var selfLoadJson = JsonConvert.SerializeObject(selfLoad, Formatting.Indented, jsonSettings); // should still be the same! Assert.Equal(parserJson, selfLoadJson); } var parserHex = GetPrettyHex(parserBytes); File.WriteAllText(Path.ChangeExtension(parserBinPath, "parser.hex"), parserHex); if (exitCode == 0) { var protocHex = GetPrettyHex(File.ReadAllBytes(protocBinPath)); File.WriteAllText(Path.ChangeExtension(protocBinPath, "protoc.hex"), protocHex); switch (path) { case "google/protobuf/unittest_custom_options.proto": case "advancedOptions.proto": // these are special cases; the two encoders choose slightly different // layouts for the same data; both are valid; I'm happy that this is OK // - this was why the "decode" tool (on the website) was written! break; case "google/protobuf/unittest.proto": // ^^^ different layout of an integer; "2e+8" vs "200000000" - I'm fine with it // // the following end up importing unittest.proto, so have the same symptom case "google/protobuf/map_unittest.proto" when(includeImports): case "google/protobuf/unittest_optimize_for.proto" when(includeImports): case "google/protobuf/unittest_embed_optimize_for.proto" when(includeImports): case "google/protobuf/unittest_lite_imports_nonlite.proto" when(includeImports): case "google/protobuf/unittest_no_field_presence.proto" when(includeImports): break; default: // compare results Assert.Equal(protocJson, parserJson); Assert.Equal(protocHex, parserHex); break; } } Assert.Null(genError); }
public GenerateResult Generate(string schema = null, string tooling = null, string names = null) { if (string.IsNullOrWhiteSpace(schema)) { return(null); } Dictionary <string, string> options = null; foreach (var field in Request.Form) { switch (field.Key) { case nameof(schema): case nameof(tooling): case nameof(names): break; // handled separately default: string s = field.Value; if (!string.IsNullOrWhiteSpace(s)) { if (options == null) { options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); } options[field.Key] = s; } break; } } NameNormalizer nameNormalizer = null; switch (names) { case "auto": nameNormalizer = NameNormalizer.Default; break; case "original": nameNormalizer = NameNormalizer.Null; break; } var result = new GenerateResult(); try { using (var reader = new StringReader(schema)) { var set = new FileDescriptorSet { ImportValidator = path => ValidateImport(path), }; set.AddImportPath(Path.Combine(_host.WebRootPath, "protoc")); set.Add("my.proto", true, reader); set.Process(); var errors = set.GetErrors(); if (!ProtocTooling.IsDefined(tooling)) { if (errors.Length > 0) { result.ParserExceptions = errors; } CodeGenerator codegen; switch (tooling) { case "protogen:VB": #pragma warning disable 0618 codegen = VBCodeGenerator.Default; #pragma warning restore 0618 break; case "protogen:C#": default: codegen = CSharpCodeGenerator.Default; break; } result.Files = codegen.Generate(set, nameNormalizer, options).ToArray(); } else { // we're going to offer protoc! hold me... if (errors.Length != 0 && schema.Contains("import")) { // code output disabled because of import } else { result.Files = RunProtoc(_host, schema, tooling, out errors); if (errors.Length > 0) { result.ParserExceptions = errors; } } } } } catch (Exception ex) { result.Exception = ex; } return(result); }
static ErrorCode GenerateCode(string inputBaseFolder, string projectBaseFolder, string codeOutputRelativeFolder) { #region Validate Parameters if (!Directory.Exists(inputBaseFolder)) { ConsoleOutput.OutputError($"inputBaseFolder not found: \"{inputBaseFolder}\""); return(ErrorCode.InputBaseFolderDoesNotExist); } if (!Directory.Exists(projectBaseFolder)) { ConsoleOutput.OutputWarning($"projectBaseFolder not found, creating \"{projectBaseFolder}\"..."); Directory.CreateDirectory(projectBaseFolder); if (!Directory.Exists(projectBaseFolder)) { ConsoleOutput.OutputError($"Could not create projectBaseFolder: \"{projectBaseFolder}\""); return(ErrorCode.ProjectBaseFolderCouldNotBeCreated); } else { ConsoleOutput.OutputSuccess("Success"); } } string codeOutputBaseFolder = Path.Combine(projectBaseFolder, codeOutputRelativeFolder); if (!Directory.Exists(codeOutputBaseFolder)) { ConsoleOutput.OutputWarning($"codeOutputRelativeFolder not found, creating \"{codeOutputBaseFolder}\"..."); Directory.CreateDirectory(codeOutputBaseFolder); if (!Directory.Exists(codeOutputBaseFolder)) { ConsoleOutput.OutputError($"Could not create codeOutputRelativeFolder: \"{codeOutputBaseFolder}\""); return(ErrorCode.CodeOutputFolderCouldNotBeCreated); } else { ConsoleOutput.OutputSuccess("Success"); } } #endregion Validate Parameters try { ErrorCode result = ErrorCode.Success; var fileDescriptorSet = new FileDescriptorSet { AllowNameOnlyImport = true }; fileDescriptorSet.AddImportPath(inputBaseFolder); var inputFiles = new List <string>(); foreach (var path in Directory.EnumerateFiles(inputBaseFolder, "*.proto", SearchOption.AllDirectories)) { inputFiles.Add(MakeRelativePath(inputBaseFolder, path)); } bool error = false; foreach (var proto in inputFiles) { if (!fileDescriptorSet.Add(proto, true)) { error = true; ConsoleOutput.OutputError($"Error Loading: {proto}"); } } if (error) { return(ErrorCode.InvalidProto); } fileDescriptorSet.Process(); var errors = fileDescriptorSet.GetErrors(); if (errors.Length > 0) { StringBuilder stringBuilder = new StringBuilder(); foreach (var err in errors) { stringBuilder.AppendLine(err.ToString()); } ConsoleOutput.OutputError(stringBuilder.ToString()); return(ErrorCode.FileDescriptorSetProcessFailure); } #region Generate the files. Dictionary <string, string> options = new Dictionary <string, string>(); using (StreamWriter writer = new StreamWriter(Path.Combine(projectBaseFolder, ProjFile))) { writer.WriteLine("<Project xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">"); writer.WriteLine(" <!-- ======================================================================= -->"); writer.WriteLine(" <!-- =============== This file is generated by GM_protogen. ================ -->"); writer.WriteLine(" <!-- ======================================================================= -->"); writer.WriteLine(); writer.WriteLine(" <!-- Generated .cs files -->"); writer.WriteLine(" <ItemGroup>"); foreach (var file in GM_CSharpCodeGenerator.Default.Generate(fileDescriptorSet, null, options)) { var filePath = Path.Combine(codeOutputBaseFolder, file.Name); var fileFolder = Path.GetDirectoryName(filePath); if (!Directory.Exists(fileFolder)) { ConsoleOutput.OutputWarning($"Output directory does not exist, creating... {fileFolder}"); Directory.CreateDirectory(fileFolder); } File.WriteAllText(filePath, file.Text); writer.WriteLine($" <Compile Include=\"{Path.Combine(codeOutputRelativeFolder, file.Name)}\">"); writer.WriteLine($" <Visible>true</Visible>"); writer.WriteLine($" </Compile>"); ConsoleOutput.OutputSuccess($"generated: {filePath}"); } writer.WriteLine(" </ItemGroup>"); writer.WriteLine(); writer.WriteLine("</Project>"); } ConsoleOutput.OutputSuccess($"generated: {ProjFile}"); #endregion Generate the files. return(result); } catch (Exception ex) { ConsoleOutput.OutputException(ex); return(ErrorCode.Exception); } }