Beispiel #1
0
        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();
    }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #7
0
        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));
                }
            }
        }
Beispiel #8
0
        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) { }
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        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));
        }
Beispiel #11
0
        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();
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        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) { }
        }
Beispiel #15
0
    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}");
		}
    }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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);
        }
Beispiel #19
0
        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);
        }
Beispiel #21
0
        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);
        }
Beispiel #22
0
        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);
            }
        }
Beispiel #23
0
        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);
        }
Beispiel #24
0
        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);
            }
        }
Beispiel #25
0
        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);
        }
Beispiel #26
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);
        }
Beispiel #27
0
        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);
        }
Beispiel #28
0
        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);
            }
        }