コード例 #1
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);
        }
コード例 #2
0
        /// <inheritdoc/>
        protected override Task InitializeAsync(CancellationToken cancellationToken)
        {
            var proto = ""; //todo

            var fileDescriptorSet = new FileDescriptorSet();

            fileDescriptorSet.Add("" /* todo */, true, new StringReader(proto));
            fileDescriptorSet.Process();
            var errors = fileDescriptorSet.GetErrors();

            foreach (var file in fileDescriptorSet.Files)
            {
                foreach (var service in file.Services)
                {
                    foreach (var method in service.Methods)
                    {
                        //todo: if method.Deprecated => display warning
                    }
                }
            }

            var channel     = GrpcChannel.ForAddress($"{EnvironmentVariables.Api.HostName.Value}:8080");
            var serviceName = "";
            var client      = new GrpcClient(channel, serviceName);

            return(Task.CompletedTask);
        }
コード例 #3
0
        /// <summary>
        /// Eexecute this code generator against a set of code file
        /// </summary>
        public CompilerResult Compile(params CodeFile[] files)
        {
            var set = new FileDescriptorSet();

            foreach (var file in files)
            {
                using (var reader = new StringReader(file.Text))
                {
                    Console.WriteLine($"Parsing {file.Name}...");
                    set.Add(file.Name, true, reader);
                }
            }
            set.Process();
            var results   = new List <CodeFile>();
            var newErrors = new List <Error>();

            try
            {
                results.AddRange(Generate(set));
            }
            catch (Exception ex)
            {
                set.Errors.Add(new Error(default(Token), ex.Message, true));
            }
            var errors = set.GetErrors();

            return(new CompilerResult(errors, results.ToArray()));
        }
コード例 #4
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);

        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();
    }
コード例 #5
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);
        }
コード例 #6
0
ファイル: SchemaTests.cs プロジェクト: szehetner/protobuf-net
        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);
            }
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        public void EmbeddedImportsWork()
        {
            var set = new FileDescriptorSet();

            using (var file = File.OpenText("basic.proto"))
            {
                Assert.True(set.Add("basic.proto", true, file));
            }
            set.Process();
            var err = set.GetErrors();

            Assert.Empty(err);
        }
コード例 #9
0
        internal static FileDescriptorSet Create(IEnumerable <Type> serviceTypes, BinderConfiguration?binderConfiguration = null)
        {
            var fileDescriptorSet = new FileDescriptorSet();

            binderConfiguration ??= BinderConfiguration.Default;

            foreach (var serviceType in serviceTypes)
            {
                Populate(fileDescriptorSet, serviceType, binderConfiguration);
            }

            fileDescriptorSet.Process();
            return(fileDescriptorSet);
        }
コード例 #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.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));
                }
            }
        }
コード例 #11
0
ファイル: Parsers.cs プロジェクト: zhangheGitHub/protobuf-net
        public void BuildTypeHierarchyForServices()
        {
            var set = new FileDescriptorSet();

            using (var file = File.OpenText("basic_service.proto"))
            {
                Assert.True(set.Add("basic_service.proto", true, file));
            }
            set.Process();
            var err = set.GetErrors();

            Assert.Empty(err);

            Assert.Equal(".HelloWorld.HelloService", set.Files[0].Services[0].FullyQualifiedName);
            Assert.Equal(".HelloWorld.HelloService.SayHello", set.Files[0].Services[0].Methods[0].FullyQualifiedName);
        }
コード例 #12
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) { }
        }
コード例 #13
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);
        }
コード例 #14
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));
        }
コード例 #15
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();
        }
コード例 #16
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);
        }
コード例 #17
0
        /// <summary>
        /// Eexecute this code generator against a set of code file
        /// </summary>
        public CompilerResult Compile(params CodeFile[] files)
        {
            var set = new FileDescriptorSet();

            foreach (var file in files)
            {
                using var reader = new StringReader(file.Text);
                Console.WriteLine($"Parsing {file.Name}...");
                set.Add(file.Name, true, reader);
            }
            set.Process();
            var results = new List <CodeFile>();

            try
            {
                results.AddRange(Generate(set));
            }
            catch (Exception ex)
            {
                var errorCode = ex is ParserException pe ? pe.ErrorCode : ErrorCode.Undefined;
                set.Errors.Add(new Error(default, ex.Message, true, errorCode));
コード例 #18
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);
        }
コード例 #19
0
ファイル: Program.cs プロジェクト: dom3d/mojoactor-dotnet
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 1)
                {
                    Console.WriteLine("You need to specify a path to the proto file to use");
                }
                else
                {
                    var set = new FileDescriptorSet();

                    var r = File.OpenText($@"{args[0]}");

                    var defaultOutputName = Path.GetFileName(args[0]);

                    if (args.Length > 1)
                    {
                        defaultOutputName = args[1];
                    }

                    set.Add(defaultOutputName, true, r);

                    set.Process();

                    var gen = new GrainGen();
                    var res = gen.Generate(set).ToList();

                    foreach (var items in res)
                    {
                        File.WriteAllText(items.Name, items.Text);
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
コード例 #20
0
ファイル: SchemaTests.cs プロジェクト: szehetner/protobuf-net
        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) { }
        }
コード例 #21
0
ファイル: Protogen.cs プロジェクト: HusKka/NiuNiu
    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}");
		}
    }
コード例 #22
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);
        }
コード例 #23
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);
            }
        }
コード例 #24
0
 public void Process() =>
 _fileDescriptorSet.Process();
コード例 #25
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);
        }
コード例 #26
0
        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);
        }
コード例 #27
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);
            }
        }
コード例 #28
0
        public void Generate()
        {
            CodeGenResult = null;

            string schema = Monaco.GetCode("protocontainer");

            if (string.IsNullOrWhiteSpace(schema))
            {
                return;
            }

            Dictionary <string, string> options = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

            options["langver"] = LangVer;
            if (OneOfEnum)
            {
                options["oneof"] = "enum";
            }
            if (ListSet)
            {
                options["listset"] = "yes";
            }

            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 (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();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                result.Exception = ex.Message;
            }
            CodeGenResult = result;
            Monaco.SetCode("csharpcontainer", CodeGenResult?.Files?.FirstOrDefault()?.Text ?? "");
            JSInProcess.InvokeVoid("processResults", CodeGenResult);
        }
コード例 #29
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);
        }
コード例 #30
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);
            }
        }