static CapnpGenJob ToGenJob(ITaskItem item)
        {
            var job = new CapnpGenJob()
            {
                CapnpPath        = item.GetMetadata("FullPath"),
                WorkingDirectory = item.GetMetadata("WorkingDirectory")
            };

            string importPaths = item.GetMetadata("ImportPaths");

            if (!string.IsNullOrWhiteSpace(importPaths))
            {
                job.AdditionalArguments.AddRange(importPaths.Split(new char[] { ';' },
                                                                   StringSplitOptions.RemoveEmptyEntries).Select(p => $"-I\"{p.TrimEnd('\\')}\""));
            }

            string sourcePrefix = item.GetMetadata("SourcePrefix");

            if (!string.IsNullOrWhiteSpace(sourcePrefix))
            {
                job.AdditionalArguments.Add(sourcePrefix);
            }


            string verbose = item.GetMetadata("Verbose");

            if ("true".Equals(verbose, StringComparison.OrdinalIgnoreCase))
            {
                job.AdditionalArguments.Add("--verbose");
            }

            return(job);
        }
        public CsFileGeneratorResult GenerateCodeBehindFile(CapnpGenJob job)
        {
            string capnpFile = job.CapnpPath;

            // Works around a weird capnp.exe behavior: When the input file is empty, it will spit out an exception dump
            // instead of a parse error. But the parse error is nice because it contains a generated ID. We want the parse error!
            // Workaround: Generate a temporary file that contains a single line break (such that it is not empty...)
            try
            {
                if (File.Exists(capnpFile) && new FileInfo(capnpFile).Length == 0)
                {
                    string tempFile = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".capnp");

                    File.WriteAllText(tempFile, Environment.NewLine);
                    try
                    {
                        var jobCopy = new CapnpGenJob()
                        {
                            CapnpPath        = tempFile,
                            WorkingDirectory = job.WorkingDirectory
                        };

                        jobCopy.AdditionalArguments.AddRange(job.AdditionalArguments);

                        return(GenerateCodeBehindFile(jobCopy));
                    }
                    finally
                    {
                        File.Delete(tempFile);
                    }
                }
            }
            catch
            {
            }

            var args = new List <string>();

            args.AddRange(job.AdditionalArguments);
            args.Add(capnpFile);

            var result = CapnpCompilation.InvokeCapnpAndGenerate(args, job.WorkingDirectory);

            if (result.IsSuccess)
            {
                if (result.GeneratedFiles.Count == 1)
                {
                    return(new CsFileGeneratorResult(
                               result.GeneratedFiles[0],
                               capnpFile + ".cs",
                               result.Messages));
                }
                else
                {
                    return(new CsFileGeneratorResult(
                               "Code generation produced more than one file. This is not supported.",
                               result.Messages));
                }
            }
            else
            {
                switch (result.ErrorCategory)
                {
                case CapnpProcessFailure.NotFound:
                    return(new CsFileGeneratorResult("Unable to find capnp.exe - please install capnproto on your system first."));

                case CapnpProcessFailure.BadInput:
                    return(new CsFileGeneratorResult("Invalid schema", result.Messages));

                case CapnpProcessFailure.BadOutput:
                    return(new CsFileGeneratorResult(
                               "Internal error: capnp.exe produced a binary code generation request which was not understood by the backend",
                               result.Messages));

                default:
                    throw new NotSupportedException("Invalid error category");
                }
            }
        }