|  | @@ -20,390 +20,422 @@ using System.Text;
 | 
	
		
			
				|  |  |  using Microsoft.Build.Framework;
 | 
	
		
			
				|  |  |  using Microsoft.Build.Utilities;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -namespace Grpc.Tools {
 | 
	
		
			
				|  |  | -  /// <summary>
 | 
	
		
			
				|  |  | -  /// Run Google proto compiler (protoc).
 | 
	
		
			
				|  |  | -  ///
 | 
	
		
			
				|  |  | -  /// After a successful run, the task reads the dependency file if specified
 | 
	
		
			
				|  |  | -  /// to be saved by the compiler, and returns its output files.
 | 
	
		
			
				|  |  | -  ///
 | 
	
		
			
				|  |  | -  /// This task (unlike PrepareProtoCompile) does not attempt to guess anything
 | 
	
		
			
				|  |  | -  /// about language-specific behavior of protoc, and therefore can be used for
 | 
	
		
			
				|  |  | -  /// any language outputs.
 | 
	
		
			
				|  |  | -  /// </summary>
 | 
	
		
			
				|  |  | -  public class ProtoCompile : ToolTask {
 | 
	
		
			
				|  |  | -  /*
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  Usage: /home/kkm/work/protobuf/src/.libs/lt-protoc [OPTION] PROTO_FILES
 | 
	
		
			
				|  |  | -  Parse PROTO_FILES and generate output based on the options given:
 | 
	
		
			
				|  |  | -    -IPATH, --proto_path=PATH   Specify the directory in which to search for
 | 
	
		
			
				|  |  | -                                imports.  May be specified multiple times;
 | 
	
		
			
				|  |  | -                                directories will be searched in order.  If not
 | 
	
		
			
				|  |  | -                                given, the current working directory is used.
 | 
	
		
			
				|  |  | -    --version                   Show version info and exit.
 | 
	
		
			
				|  |  | -    -h, --help                  Show this text and exit.
 | 
	
		
			
				|  |  | -    --encode=MESSAGE_TYPE       Read a text-format message of the given type
 | 
	
		
			
				|  |  | -                                from standard input and write it in binary
 | 
	
		
			
				|  |  | -                                to standard output.  The message type must
 | 
	
		
			
				|  |  | -                                be defined in PROTO_FILES or their imports.
 | 
	
		
			
				|  |  | -    --decode=MESSAGE_TYPE       Read a binary message of the given type from
 | 
	
		
			
				|  |  | -                                standard input and write it in text format
 | 
	
		
			
				|  |  | -                                to standard output.  The message type must
 | 
	
		
			
				|  |  | -                                be defined in PROTO_FILES or their imports.
 | 
	
		
			
				|  |  | -    --decode_raw                Read an arbitrary protocol message from
 | 
	
		
			
				|  |  | -                                standard input and write the raw tag/value
 | 
	
		
			
				|  |  | -                                pairs in text format to standard output.  No
 | 
	
		
			
				|  |  | -                                PROTO_FILES should be given when using this
 | 
	
		
			
				|  |  | -                                flag.
 | 
	
		
			
				|  |  | -    --descriptor_set_in=FILES   Specifies a delimited list of FILES
 | 
	
		
			
				|  |  | -                                each containing a FileDescriptorSet (a
 | 
	
		
			
				|  |  | -                                protocol buffer defined in descriptor.proto).
 | 
	
		
			
				|  |  | -                                The FileDescriptor for each of the PROTO_FILES
 | 
	
		
			
				|  |  | -                                provided will be loaded from these
 | 
	
		
			
				|  |  | -                                FileDescriptorSets. If a FileDescriptor
 | 
	
		
			
				|  |  | -                                appears multiple times, the first occurrence
 | 
	
		
			
				|  |  | -                                will be used.
 | 
	
		
			
				|  |  | -    -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,
 | 
	
		
			
				|  |  | -      --descriptor_set_out=FILE defined in descriptor.proto) containing all of
 | 
	
		
			
				|  |  | -                                the input files to FILE.
 | 
	
		
			
				|  |  | -    --include_imports           When using --descriptor_set_out, also include
 | 
	
		
			
				|  |  | -                                all dependencies of the input files in the
 | 
	
		
			
				|  |  | -                                set, so that the set is self-contained.
 | 
	
		
			
				|  |  | -    --include_source_info       When using --descriptor_set_out, do not strip
 | 
	
		
			
				|  |  | -                                SourceCodeInfo from the FileDescriptorProto.
 | 
	
		
			
				|  |  | -                                This results in vastly larger descriptors that
 | 
	
		
			
				|  |  | -                                include information about the original
 | 
	
		
			
				|  |  | -                                location of each decl in the source file as
 | 
	
		
			
				|  |  | -                                well as surrounding comments.
 | 
	
		
			
				|  |  | -    --dependency_out=FILE       Write a dependency output file in the format
 | 
	
		
			
				|  |  | -                                expected by make. This writes the transitive
 | 
	
		
			
				|  |  | -                                set of input file paths to FILE
 | 
	
		
			
				|  |  | -    --error_format=FORMAT       Set the format in which to print errors.
 | 
	
		
			
				|  |  | -                                FORMAT may be 'gcc' (the default) or 'msvs'
 | 
	
		
			
				|  |  | -                                (Microsoft Visual Studio format).
 | 
	
		
			
				|  |  | -    --print_free_field_numbers  Print the free field numbers of the messages
 | 
	
		
			
				|  |  | -                                defined in the given proto files. Groups share
 | 
	
		
			
				|  |  | -                                the same field number space with the parent
 | 
	
		
			
				|  |  | -                                message. Extension ranges are counted as
 | 
	
		
			
				|  |  | -                                occupied fields numbers.
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    --plugin=EXECUTABLE         Specifies a plugin executable to use.
 | 
	
		
			
				|  |  | -                                Normally, protoc searches the PATH for
 | 
	
		
			
				|  |  | -                                plugins, but you may specify additional
 | 
	
		
			
				|  |  | -                                executables not in the path using this flag.
 | 
	
		
			
				|  |  | -                                Additionally, EXECUTABLE may be of the form
 | 
	
		
			
				|  |  | -                                NAME=PATH, in which case the given plugin name
 | 
	
		
			
				|  |  | -                                is mapped to the given executable even if
 | 
	
		
			
				|  |  | -                                the executable's own name differs.
 | 
	
		
			
				|  |  | -    --cpp_out=OUT_DIR           Generate C++ header and source.
 | 
	
		
			
				|  |  | -    --csharp_out=OUT_DIR        Generate C# source file.
 | 
	
		
			
				|  |  | -    --java_out=OUT_DIR          Generate Java source file.
 | 
	
		
			
				|  |  | -    --javanano_out=OUT_DIR      Generate Java Nano source file.
 | 
	
		
			
				|  |  | -    --js_out=OUT_DIR            Generate JavaScript source.
 | 
	
		
			
				|  |  | -    --objc_out=OUT_DIR          Generate Objective C header and source.
 | 
	
		
			
				|  |  | -    --php_out=OUT_DIR           Generate PHP source file.
 | 
	
		
			
				|  |  | -    --python_out=OUT_DIR        Generate Python source file.
 | 
	
		
			
				|  |  | -    --ruby_out=OUT_DIR          Generate Ruby source file.
 | 
	
		
			
				|  |  | -    @<filename>                 Read options and filenames from file. If a
 | 
	
		
			
				|  |  | -                                relative file path is specified, the file
 | 
	
		
			
				|  |  | -                                will be searched in the working directory.
 | 
	
		
			
				|  |  | -                                The --proto_path option will not affect how
 | 
	
		
			
				|  |  | -                                this argument file is searched. Content of
 | 
	
		
			
				|  |  | -                                the file will be expanded in the position of
 | 
	
		
			
				|  |  | -                                @<filename> as in the argument list. Note
 | 
	
		
			
				|  |  | -                                that shell expansion is not applied to the
 | 
	
		
			
				|  |  | -                                content of the file (i.e., you cannot use
 | 
	
		
			
				|  |  | -                                quotes, wildcards, escapes, commands, etc.).
 | 
	
		
			
				|  |  | -                                Each line corresponds to a single argument,
 | 
	
		
			
				|  |  | -                                even if it contains spaces.
 | 
	
		
			
				|  |  | -  */
 | 
	
		
			
				|  |  | -    static string[] s_supportedGenerators = new[] {
 | 
	
		
			
				|  |  | -      "cpp", "csharp", "java",
 | 
	
		
			
				|  |  | -      "javanano", "js", "objc",
 | 
	
		
			
				|  |  | -      "php", "python", "ruby",
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Code generator.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Required]
 | 
	
		
			
				|  |  | -    public string Generator { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Protobuf files to compile.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Required]
 | 
	
		
			
				|  |  | -    public ITaskItem[] ProtoBuf { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Directory where protoc dependency files are cached. If provided, dependency
 | 
	
		
			
				|  |  | -    /// output filename is autogenerated from source directory hash and file name.
 | 
	
		
			
				|  |  | -    /// Mutually exclusive with DependencyOut.
 | 
	
		
			
				|  |  | -    /// Switch: --dependency_out (with autogenerated file name).
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public string ProtoDepDir { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Dependency file full name. Mutually exclusive with ProtoDepDir.
 | 
	
		
			
				|  |  | -    /// Autogenerated file name is available in this property after execution.
 | 
	
		
			
				|  |  | -    /// Switch: --dependency_out.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Output]
 | 
	
		
			
				|  |  | -    public string DependencyOut { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// The directories to search for imports. Directories will be searched
 | 
	
		
			
				|  |  | -    /// in order. If not given, the current working directory is used.
 | 
	
		
			
				|  |  | -    /// Switch: --proto_path.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public string[] ProtoPath { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Generated code directory. The generator property determines the language.
 | 
	
		
			
				|  |  | -    /// Switch: --GEN-out= (for different generators GEN).
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Required]
 | 
	
		
			
				|  |  | -    public string OutputDir { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Codegen options. See also OptionsFromMetadata.
 | 
	
		
			
				|  |  | -    /// Switch: --GEN_out= (for different generators GEN).
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public string[] OutputOptions { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// Full path to the gRPC plugin executable. If specified, gRPC generation
 | 
	
		
			
				|  |  | -    /// is enabled for the files.
 | 
	
		
			
				|  |  | -    /// Switch: --plugin=protoc-gen-grpc=
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public string GrpcPluginExe { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +namespace Grpc.Tools
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  |      /// <summary>
 | 
	
		
			
				|  |  | -    /// Generated gRPC  directory. The generator property determines the
 | 
	
		
			
				|  |  | -    /// language. If gRPC is enabled but this is not given, OutputDir is used.
 | 
	
		
			
				|  |  | -    /// Switch: --grpc_out=
 | 
	
		
			
				|  |  | +    /// Run Google proto compiler (protoc).
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// After a successful run, the task reads the dependency file if specified
 | 
	
		
			
				|  |  | +    /// to be saved by the compiler, and returns its output files.
 | 
	
		
			
				|  |  | +    ///
 | 
	
		
			
				|  |  | +    /// This task (unlike PrepareProtoCompile) does not attempt to guess anything
 | 
	
		
			
				|  |  | +    /// about language-specific behavior of protoc, and therefore can be used for
 | 
	
		
			
				|  |  | +    /// any language outputs.
 | 
	
		
			
				|  |  |      /// </summary>
 | 
	
		
			
				|  |  | -    public string GrpcOutputDir { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// gRPC Codegen options. See also OptionsFromMetadata.
 | 
	
		
			
				|  |  | -    /// --grpc_opt=opt1,opt2=val (comma-separated).
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    public string[] GrpcOutputOptions { get; set; }
 | 
	
		
			
				|  |  | +    public class ProtoCompile : ToolTask
 | 
	
		
			
				|  |  | +    {
 | 
	
		
			
				|  |  | +        /*
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Usage: /home/kkm/work/protobuf/src/.libs/lt-protoc [OPTION] PROTO_FILES
 | 
	
		
			
				|  |  | +        Parse PROTO_FILES and generate output based on the options given:
 | 
	
		
			
				|  |  | +          -IPATH, --proto_path=PATH   Specify the directory in which to search for
 | 
	
		
			
				|  |  | +                                      imports.  May be specified multiple times;
 | 
	
		
			
				|  |  | +                                      directories will be searched in order.  If not
 | 
	
		
			
				|  |  | +                                      given, the current working directory is used.
 | 
	
		
			
				|  |  | +          --version                   Show version info and exit.
 | 
	
		
			
				|  |  | +          -h, --help                  Show this text and exit.
 | 
	
		
			
				|  |  | +          --encode=MESSAGE_TYPE       Read a text-format message of the given type
 | 
	
		
			
				|  |  | +                                      from standard input and write it in binary
 | 
	
		
			
				|  |  | +                                      to standard output.  The message type must
 | 
	
		
			
				|  |  | +                                      be defined in PROTO_FILES or their imports.
 | 
	
		
			
				|  |  | +          --decode=MESSAGE_TYPE       Read a binary message of the given type from
 | 
	
		
			
				|  |  | +                                      standard input and write it in text format
 | 
	
		
			
				|  |  | +                                      to standard output.  The message type must
 | 
	
		
			
				|  |  | +                                      be defined in PROTO_FILES or their imports.
 | 
	
		
			
				|  |  | +          --decode_raw                Read an arbitrary protocol message from
 | 
	
		
			
				|  |  | +                                      standard input and write the raw tag/value
 | 
	
		
			
				|  |  | +                                      pairs in text format to standard output.  No
 | 
	
		
			
				|  |  | +                                      PROTO_FILES should be given when using this
 | 
	
		
			
				|  |  | +                                      flag.
 | 
	
		
			
				|  |  | +          --descriptor_set_in=FILES   Specifies a delimited list of FILES
 | 
	
		
			
				|  |  | +                                      each containing a FileDescriptorSet (a
 | 
	
		
			
				|  |  | +                                      protocol buffer defined in descriptor.proto).
 | 
	
		
			
				|  |  | +                                      The FileDescriptor for each of the PROTO_FILES
 | 
	
		
			
				|  |  | +                                      provided will be loaded from these
 | 
	
		
			
				|  |  | +                                      FileDescriptorSets. If a FileDescriptor
 | 
	
		
			
				|  |  | +                                      appears multiple times, the first occurrence
 | 
	
		
			
				|  |  | +                                      will be used.
 | 
	
		
			
				|  |  | +          -oFILE,                     Writes a FileDescriptorSet (a protocol buffer,
 | 
	
		
			
				|  |  | +            --descriptor_set_out=FILE defined in descriptor.proto) containing all of
 | 
	
		
			
				|  |  | +                                      the input files to FILE.
 | 
	
		
			
				|  |  | +          --include_imports           When using --descriptor_set_out, also include
 | 
	
		
			
				|  |  | +                                      all dependencies of the input files in the
 | 
	
		
			
				|  |  | +                                      set, so that the set is self-contained.
 | 
	
		
			
				|  |  | +          --include_source_info       When using --descriptor_set_out, do not strip
 | 
	
		
			
				|  |  | +                                      SourceCodeInfo from the FileDescriptorProto.
 | 
	
		
			
				|  |  | +                                      This results in vastly larger descriptors that
 | 
	
		
			
				|  |  | +                                      include information about the original
 | 
	
		
			
				|  |  | +                                      location of each decl in the source file as
 | 
	
		
			
				|  |  | +                                      well as surrounding comments.
 | 
	
		
			
				|  |  | +          --dependency_out=FILE       Write a dependency output file in the format
 | 
	
		
			
				|  |  | +                                      expected by make. This writes the transitive
 | 
	
		
			
				|  |  | +                                      set of input file paths to FILE
 | 
	
		
			
				|  |  | +          --error_format=FORMAT       Set the format in which to print errors.
 | 
	
		
			
				|  |  | +                                      FORMAT may be 'gcc' (the default) or 'msvs'
 | 
	
		
			
				|  |  | +                                      (Microsoft Visual Studio format).
 | 
	
		
			
				|  |  | +          --print_free_field_numbers  Print the free field numbers of the messages
 | 
	
		
			
				|  |  | +                                      defined in the given proto files. Groups share
 | 
	
		
			
				|  |  | +                                      the same field number space with the parent
 | 
	
		
			
				|  |  | +                                      message. Extension ranges are counted as
 | 
	
		
			
				|  |  | +                                      occupied fields numbers.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +          --plugin=EXECUTABLE         Specifies a plugin executable to use.
 | 
	
		
			
				|  |  | +                                      Normally, protoc searches the PATH for
 | 
	
		
			
				|  |  | +                                      plugins, but you may specify additional
 | 
	
		
			
				|  |  | +                                      executables not in the path using this flag.
 | 
	
		
			
				|  |  | +                                      Additionally, EXECUTABLE may be of the form
 | 
	
		
			
				|  |  | +                                      NAME=PATH, in which case the given plugin name
 | 
	
		
			
				|  |  | +                                      is mapped to the given executable even if
 | 
	
		
			
				|  |  | +                                      the executable's own name differs.
 | 
	
		
			
				|  |  | +          --cpp_out=OUT_DIR           Generate C++ header and source.
 | 
	
		
			
				|  |  | +          --csharp_out=OUT_DIR        Generate C# source file.
 | 
	
		
			
				|  |  | +          --java_out=OUT_DIR          Generate Java source file.
 | 
	
		
			
				|  |  | +          --javanano_out=OUT_DIR      Generate Java Nano source file.
 | 
	
		
			
				|  |  | +          --js_out=OUT_DIR            Generate JavaScript source.
 | 
	
		
			
				|  |  | +          --objc_out=OUT_DIR          Generate Objective C header and source.
 | 
	
		
			
				|  |  | +          --php_out=OUT_DIR           Generate PHP source file.
 | 
	
		
			
				|  |  | +          --python_out=OUT_DIR        Generate Python source file.
 | 
	
		
			
				|  |  | +          --ruby_out=OUT_DIR          Generate Ruby source file.
 | 
	
		
			
				|  |  | +          @<filename>                 Read options and filenames from file. If a
 | 
	
		
			
				|  |  | +                                      relative file path is specified, the file
 | 
	
		
			
				|  |  | +                                      will be searched in the working directory.
 | 
	
		
			
				|  |  | +                                      The --proto_path option will not affect how
 | 
	
		
			
				|  |  | +                                      this argument file is searched. Content of
 | 
	
		
			
				|  |  | +                                      the file will be expanded in the position of
 | 
	
		
			
				|  |  | +                                      @<filename> as in the argument list. Note
 | 
	
		
			
				|  |  | +                                      that shell expansion is not applied to the
 | 
	
		
			
				|  |  | +                                      content of the file (i.e., you cannot use
 | 
	
		
			
				|  |  | +                                      quotes, wildcards, escapes, commands, etc.).
 | 
	
		
			
				|  |  | +                                      Each line corresponds to a single argument,
 | 
	
		
			
				|  |  | +                                      even if it contains spaces.
 | 
	
		
			
				|  |  | +        */
 | 
	
		
			
				|  |  | +        static string[] s_supportedGenerators = new[] { "cpp", "csharp", "java",
 | 
	
		
			
				|  |  | +                                                        "javanano", "js", "objc",
 | 
	
		
			
				|  |  | +                                                        "php", "python", "ruby" };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Code generator.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Required]
 | 
	
		
			
				|  |  | +        public string Generator { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Protobuf files to compile.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Required]
 | 
	
		
			
				|  |  | +        public ITaskItem[] ProtoBuf { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Directory where protoc dependency files are cached. If provided, dependency
 | 
	
		
			
				|  |  | +        /// output filename is autogenerated from source directory hash and file name.
 | 
	
		
			
				|  |  | +        /// Mutually exclusive with DependencyOut.
 | 
	
		
			
				|  |  | +        /// Switch: --dependency_out (with autogenerated file name).
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string ProtoDepDir { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Dependency file full name. Mutually exclusive with ProtoDepDir.
 | 
	
		
			
				|  |  | +        /// Autogenerated file name is available in this property after execution.
 | 
	
		
			
				|  |  | +        /// Switch: --dependency_out.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Output]
 | 
	
		
			
				|  |  | +        public string DependencyOut { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// The directories to search for imports. Directories will be searched
 | 
	
		
			
				|  |  | +        /// in order. If not given, the current working directory is used.
 | 
	
		
			
				|  |  | +        /// Switch: --proto_path.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string[] ProtoPath { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Generated code directory. The generator property determines the language.
 | 
	
		
			
				|  |  | +        /// Switch: --GEN-out= (for different generators GEN).
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Required]
 | 
	
		
			
				|  |  | +        public string OutputDir { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Codegen options. See also OptionsFromMetadata.
 | 
	
		
			
				|  |  | +        /// Switch: --GEN_out= (for different generators GEN).
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string[] OutputOptions { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Full path to the gRPC plugin executable. If specified, gRPC generation
 | 
	
		
			
				|  |  | +        /// is enabled for the files.
 | 
	
		
			
				|  |  | +        /// Switch: --plugin=protoc-gen-grpc=
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string GrpcPluginExe { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// Generated gRPC  directory. The generator property determines the
 | 
	
		
			
				|  |  | +        /// language. If gRPC is enabled but this is not given, OutputDir is used.
 | 
	
		
			
				|  |  | +        /// Switch: --grpc_out=
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string GrpcOutputDir { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// gRPC Codegen options. See also OptionsFromMetadata.
 | 
	
		
			
				|  |  | +        /// --grpc_opt=opt1,opt2=val (comma-separated).
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        public string[] GrpcOutputOptions { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// List of files written in addition to generated outputs. Includes a
 | 
	
		
			
				|  |  | +        /// single item for the dependency file if written.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Output]
 | 
	
		
			
				|  |  | +        public ITaskItem[] AdditionalFileWrites { get; private set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        /// <summary>
 | 
	
		
			
				|  |  | +        /// List of language files generated by protoc. Empty unless DependencyOut
 | 
	
		
			
				|  |  | +        /// or ProtoDepDir is set, since the file writes are extracted from protoc
 | 
	
		
			
				|  |  | +        /// dependency output file.
 | 
	
		
			
				|  |  | +        /// </summary>
 | 
	
		
			
				|  |  | +        [Output]
 | 
	
		
			
				|  |  | +        public ITaskItem[] GeneratedFiles { get; private set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Hide this property from MSBuild, we should never use a shell script.
 | 
	
		
			
				|  |  | +        private new bool UseCommandProcessor { get; set; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        protected override string ToolName => Platform.IsWindows ? "protoc.exe" : "protoc";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Since we never try to really locate protoc.exe somehow, just try ToolExe
 | 
	
		
			
				|  |  | +        // as the full tool location. It will be either just protoc[.exe] from
 | 
	
		
			
				|  |  | +        // ToolName above if not set by the user, or a user-supplied full path. The
 | 
	
		
			
				|  |  | +        // base class will then resolve the former using system PATH.
 | 
	
		
			
				|  |  | +        protected override string GenerateFullPathToTool() => ToolExe;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Log protoc errors with the High priority (bold white in MsBuild,
 | 
	
		
			
				|  |  | +        // printed with -v:n, and shown in the Output windows in VS).
 | 
	
		
			
				|  |  | +        protected override MessageImportance StandardErrorLoggingImportance => MessageImportance.High;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Called by base class to validate arguments and make them consistent.
 | 
	
		
			
				|  |  | +        protected override bool ValidateParameters()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            // Part of proto command line switches, must be lowercased.
 | 
	
		
			
				|  |  | +            Generator = Generator.ToLowerInvariant();
 | 
	
		
			
				|  |  | +            if (!System.Array.Exists(s_supportedGenerators, g => g == Generator))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Log.LogError("Invalid value for Generator='{0}'. Supported generators: {1}",
 | 
	
		
			
				|  |  | +                             Generator, string.Join(", ", s_supportedGenerators));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (ProtoDepDir != null && DependencyOut != null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Log.LogError("Properties ProtoDepDir and DependencyOut may not be both specified");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (ProtoBuf.Length > 1 && (ProtoDepDir != null || DependencyOut != null))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                Log.LogError("Proto compiler currently allows only one input when " +
 | 
	
		
			
				|  |  | +                             "--dependency_out is specified (via ProtoDepDir or DependencyOut). " +
 | 
	
		
			
				|  |  | +                             "Tracking issue: https://github.com/google/protobuf/pull/3959");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Use ProtoDepDir to autogenerate DependencyOut
 | 
	
		
			
				|  |  | +            if (ProtoDepDir != null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                DependencyOut = DepFileUtil.GetDepFilenameForProto(ProtoDepDir, ProtoBuf[0].ItemSpec);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (GrpcPluginExe == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                GrpcOutputOptions = null;
 | 
	
		
			
				|  |  | +                GrpcOutputDir = null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else if (GrpcOutputDir == null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // Use OutputDir for gRPC output if not specified otherwise by user.
 | 
	
		
			
				|  |  | +                GrpcOutputDir = OutputDir;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return !Log.HasLoggedErrors && base.ValidateParameters();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// List of files written in addition to generated outputs. Includes a
 | 
	
		
			
				|  |  | -    /// single item for the dependency file if written.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Output]
 | 
	
		
			
				|  |  | -    public ITaskItem[] AdditionalFileWrites { get; private set; }
 | 
	
		
			
				|  |  | +        // Protoc chokes on BOM, naturally. I would!
 | 
	
		
			
				|  |  | +        static readonly Encoding s_utf8WithoutBom = new UTF8Encoding(false);
 | 
	
		
			
				|  |  | +        protected override Encoding ResponseFileEncoding => s_utf8WithoutBom;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // Protoc takes one argument per line from the response file, and does not
 | 
	
		
			
				|  |  | +        // require any quoting whatsoever. Otherwise, this is similar to the
 | 
	
		
			
				|  |  | +        // standard CommandLineBuilder
 | 
	
		
			
				|  |  | +        class ProtocResponseFileBuilder
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            StringBuilder _data = new StringBuilder(1000);
 | 
	
		
			
				|  |  | +            public override string ToString() => _data.ToString();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // If 'value' is not empty, append '--name=value\n'.
 | 
	
		
			
				|  |  | +            public void AddSwitchMaybe(string name, string value)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (!string.IsNullOrEmpty(value))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    _data.Append("--").Append(name).Append("=")
 | 
	
		
			
				|  |  | +                         .Append(value).Append('\n');
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Add switch with the 'values' separated by commas, for options.
 | 
	
		
			
				|  |  | +            public void AddSwitchMaybe(string name, string[] values)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                if (values?.Length > 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    _data.Append("--").Append(name).Append("=")
 | 
	
		
			
				|  |  | +                         .Append(string.Join(",", values)).Append('\n');
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Add a positional argument to the file data.
 | 
	
		
			
				|  |  | +            public void AddArg(string arg)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                _data.Append(arg).Append('\n');
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /// <summary>
 | 
	
		
			
				|  |  | -    /// List of language files generated by protoc. Empty unless DependencyOut
 | 
	
		
			
				|  |  | -    /// or ProtoDepDir is set, since the file writes are extracted from protoc
 | 
	
		
			
				|  |  | -    /// dependency output file.
 | 
	
		
			
				|  |  | -    /// </summary>
 | 
	
		
			
				|  |  | -    [Output]
 | 
	
		
			
				|  |  | -    public ITaskItem[] GeneratedFiles { get; private set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Hide this property from MSBuild, we should never use a shell script.
 | 
	
		
			
				|  |  | -    private new bool UseCommandProcessor { get; set; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    protected override string ToolName =>
 | 
	
		
			
				|  |  | -      Platform.IsWindows ? "protoc.exe" : "protoc";
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Since we never try to really locate protoc.exe somehow, just try ToolExe
 | 
	
		
			
				|  |  | -    // as the full tool location. It will be either just protoc[.exe] from
 | 
	
		
			
				|  |  | -    // ToolName above if not set by the user, or a user-supplied full path. The
 | 
	
		
			
				|  |  | -    // base class will then resolve the former using system PATH.
 | 
	
		
			
				|  |  | -    protected override string GenerateFullPathToTool() => ToolExe;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Log protoc errors with the High priority (bold white in MsBuild,
 | 
	
		
			
				|  |  | -    // printed with -v:n, and shown in the Output windows in VS).
 | 
	
		
			
				|  |  | -    protected override MessageImportance StandardErrorLoggingImportance =>
 | 
	
		
			
				|  |  | -      MessageImportance.High;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Called by base class to validate arguments and make them consistent.
 | 
	
		
			
				|  |  | -    protected override bool ValidateParameters() {
 | 
	
		
			
				|  |  | -      // Part of proto command line switches, must be lowercased.
 | 
	
		
			
				|  |  | -      Generator = Generator.ToLowerInvariant();
 | 
	
		
			
				|  |  | -      if (!System.Array.Exists(s_supportedGenerators, g => g == Generator))
 | 
	
		
			
				|  |  | -        Log.LogError("Invalid value for Generator='{0}'. Supported generators: {1}",
 | 
	
		
			
				|  |  | -                     Generator, string.Join(", ", s_supportedGenerators));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (ProtoDepDir != null && DependencyOut != null)
 | 
	
		
			
				|  |  | -        Log.LogError("Properties ProtoDepDir and DependencyOut may not be both specified");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (ProtoBuf.Length > 1 && (ProtoDepDir != null || DependencyOut != null))
 | 
	
		
			
				|  |  | -        Log.LogError("Proto compiler currently allows only one input when " +
 | 
	
		
			
				|  |  | -                     "--dependency_out is specified (via ProtoDepDir or DependencyOut). " +
 | 
	
		
			
				|  |  | -                     "Tracking issue: https://github.com/google/protobuf/pull/3959");
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Use ProtoDepDir to autogenerate DependencyOut
 | 
	
		
			
				|  |  | -      if (ProtoDepDir != null) {
 | 
	
		
			
				|  |  | -        DependencyOut = DepFileUtil.GetDepFilenameForProto(ProtoDepDir, ProtoBuf[0].ItemSpec);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (GrpcPluginExe == null) {
 | 
	
		
			
				|  |  | -        GrpcOutputOptions = null;
 | 
	
		
			
				|  |  | -        GrpcOutputDir = null;
 | 
	
		
			
				|  |  | -      } else if (GrpcOutputDir == null) {
 | 
	
		
			
				|  |  | -        // Use OutputDir for gRPC output if not specified otherwise by user.
 | 
	
		
			
				|  |  | -        GrpcOutputDir = OutputDir;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      return !Log.HasLoggedErrors && base.ValidateParameters();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Protoc chokes on BOM, naturally. I would!
 | 
	
		
			
				|  |  | -    static readonly Encoding s_utf8WithoutBom = new UTF8Encoding(false);
 | 
	
		
			
				|  |  | -    protected override Encoding ResponseFileEncoding => s_utf8WithoutBom;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Protoc takes one argument per line from the response file, and does not
 | 
	
		
			
				|  |  | -    // require any quoting whatsoever. Otherwise, this is similar to the
 | 
	
		
			
				|  |  | -    // standard CommandLineBuilder
 | 
	
		
			
				|  |  | -    class ProtocResponseFileBuilder {
 | 
	
		
			
				|  |  | -      StringBuilder _data = new StringBuilder(1000);
 | 
	
		
			
				|  |  | -      public override string ToString() => _data.ToString();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // If 'value' is not empty, append '--name=value\n'.
 | 
	
		
			
				|  |  | -      public void AddSwitchMaybe(string name, string value) {
 | 
	
		
			
				|  |  | -        if (!string.IsNullOrEmpty(value)) {
 | 
	
		
			
				|  |  | -          _data.Append("--").Append(name).Append("=")
 | 
	
		
			
				|  |  | -               .Append(value).Append('\n');
 | 
	
		
			
				|  |  | +        // Called by the base ToolTask to get response file contents.
 | 
	
		
			
				|  |  | +        protected override string GenerateResponseFileCommands()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var cmd = new ProtocResponseFileBuilder();
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe(Generator + "_out", TrimEndSlash(OutputDir));
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe(Generator + "_opt", OutputOptions);
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe("plugin=protoc-gen-grpc", GrpcPluginExe);
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe("grpc_out", TrimEndSlash(GrpcOutputDir));
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe("grpc_opt", GrpcOutputOptions);
 | 
	
		
			
				|  |  | +            if (ProtoPath != null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                foreach (string path in ProtoPath)
 | 
	
		
			
				|  |  | +                    cmd.AddSwitchMaybe("proto_path", TrimEndSlash(path));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            cmd.AddSwitchMaybe("dependency_out", DependencyOut);
 | 
	
		
			
				|  |  | +            foreach (var proto in ProtoBuf)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                cmd.AddArg(proto.ItemSpec);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return cmd.ToString();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -      // Add switch with the 'values' separated by commas, for options.
 | 
	
		
			
				|  |  | -      public void AddSwitchMaybe(string name, string[] values) {
 | 
	
		
			
				|  |  | -        if (values?.Length > 0) {
 | 
	
		
			
				|  |  | -          _data.Append("--").Append(name).Append("=")
 | 
	
		
			
				|  |  | -               .Append(string.Join(",", values)).Append('\n');
 | 
	
		
			
				|  |  | +        // Protoc cannot digest trailing slashes in directory names,
 | 
	
		
			
				|  |  | +        // curiously under Linux, but not in Windows.
 | 
	
		
			
				|  |  | +        static string TrimEndSlash(string dir)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if (dir == null || dir.Length <= 1)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return dir;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            string trim = dir.TrimEnd('/', '\\');
 | 
	
		
			
				|  |  | +            // Do not trim the root slash, drive letter possible.
 | 
	
		
			
				|  |  | +            if (trim.Length == 0)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // Slashes all the way down.
 | 
	
		
			
				|  |  | +                return dir.Substring(0, 1);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            if (trim.Length == 2 && dir.Length > 2 && trim[1] == ':')
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // We have a drive letter and root, e. g. 'C:\'
 | 
	
		
			
				|  |  | +                return dir.Substring(0, 3);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            return trim;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Add a positional argument to the file data.
 | 
	
		
			
				|  |  | -      public void AddArg(string arg) {
 | 
	
		
			
				|  |  | -        _data.Append(arg).Append('\n');
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    // Called by the base ToolTask to get response file contents.
 | 
	
		
			
				|  |  | -    protected override string GenerateResponseFileCommands() {
 | 
	
		
			
				|  |  | -      var cmd = new ProtocResponseFileBuilder();
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe(Generator + "_out", TrimEndSlash(OutputDir));
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe(Generator + "_opt", OutputOptions);
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe("plugin=protoc-gen-grpc", GrpcPluginExe);
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe("grpc_out", TrimEndSlash(GrpcOutputDir));
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe("grpc_opt", GrpcOutputOptions);
 | 
	
		
			
				|  |  | -      if (ProtoPath != null) {
 | 
	
		
			
				|  |  | -        foreach (string path in ProtoPath)
 | 
	
		
			
				|  |  | -          cmd.AddSwitchMaybe("proto_path", TrimEndSlash(path));
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      cmd.AddSwitchMaybe("dependency_out", DependencyOut);
 | 
	
		
			
				|  |  | -      foreach (var proto in ProtoBuf) {
 | 
	
		
			
				|  |  | -        cmd.AddArg(proto.ItemSpec);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      return cmd.ToString();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Protoc cannot digest trailing slashes in directory names,
 | 
	
		
			
				|  |  | -    // curiously under Linux, but not in Windows.
 | 
	
		
			
				|  |  | -    static string TrimEndSlash(string dir) {
 | 
	
		
			
				|  |  | -      if (dir == null || dir.Length <= 1) {
 | 
	
		
			
				|  |  | -        return dir;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      string trim = dir.TrimEnd('/', '\\');
 | 
	
		
			
				|  |  | -      // Do not trim the root slash, drive letter possible.
 | 
	
		
			
				|  |  | -      if (trim.Length == 0) {
 | 
	
		
			
				|  |  | -        // Slashes all the way down.
 | 
	
		
			
				|  |  | -        return dir.Substring(0, 1);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      if (trim.Length == 2 && dir.Length > 2 && trim[1] == ':') {
 | 
	
		
			
				|  |  | -        // We have a drive letter and root, e. g. 'C:\'
 | 
	
		
			
				|  |  | -        return dir.Substring(0, 3);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      return trim;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Called by the base class to log tool's command line.
 | 
	
		
			
				|  |  | -    //
 | 
	
		
			
				|  |  | -    // Protoc command file is peculiar, with one argument per line, separated
 | 
	
		
			
				|  |  | -    // by newlines. Unwrap it for log readability into a single line, and also
 | 
	
		
			
				|  |  | -    // quote arguments, lest it look weird and so it may be copied and pasted
 | 
	
		
			
				|  |  | -    // into shell. Since this is for logging only, correct enough is correct.
 | 
	
		
			
				|  |  | -    protected override void LogToolCommand(string cmd) {
 | 
	
		
			
				|  |  | -      var printer = new StringBuilder(1024);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Print 'str' slice into 'printer', wrapping in quotes if contains some
 | 
	
		
			
				|  |  | -      // interesting characters in file names, or if empty string. The list of
 | 
	
		
			
				|  |  | -      // characters requiring quoting is not by any means exhaustive; we are
 | 
	
		
			
				|  |  | -      // just striving to be nice, not guaranteeing to be nice.
 | 
	
		
			
				|  |  | -      var quotable = new[] { ' ', '!', '$', '&', '\'', '^' };
 | 
	
		
			
				|  |  | -      void PrintQuoting(string str, int start, int count) {
 | 
	
		
			
				|  |  | -        bool wrap = count == 0 || str.IndexOfAny(quotable, start, count) >= 0;
 | 
	
		
			
				|  |  | -        if (wrap) printer.Append('"');
 | 
	
		
			
				|  |  | -        printer.Append(str, start, count);
 | 
	
		
			
				|  |  | -        if (wrap) printer.Append('"');
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      for (int ib = 0, ie; (ie = cmd.IndexOf('\n', ib)) >= 0; ib = ie + 1) {
 | 
	
		
			
				|  |  | -        // First line only contains both the program name and the first switch.
 | 
	
		
			
				|  |  | -        // We can rely on at least the '--out_dir' switch being always present.
 | 
	
		
			
				|  |  | -        if (ib == 0) {
 | 
	
		
			
				|  |  | -          int iep = cmd.IndexOf(" --");
 | 
	
		
			
				|  |  | -          if (iep > 0) {
 | 
	
		
			
				|  |  | -            PrintQuoting(cmd, 0, iep);
 | 
	
		
			
				|  |  | -            ib = iep + 1;
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        printer.Append(' ');
 | 
	
		
			
				|  |  | -        if (cmd[ib] == '-') {
 | 
	
		
			
				|  |  | -          // Print switch unquoted, including '=' if any.
 | 
	
		
			
				|  |  | -          int iarg = cmd.IndexOf('=', ib, ie - ib);
 | 
	
		
			
				|  |  | -          if (iarg < 0) {
 | 
	
		
			
				|  |  | -            // Bare switch without a '='.
 | 
	
		
			
				|  |  | -            printer.Append(cmd, ib, ie - ib);
 | 
	
		
			
				|  |  | -            continue;
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -          printer.Append(cmd, ib, iarg + 1 - ib);
 | 
	
		
			
				|  |  | -          ib = iarg + 1;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        // A positional argument or switch value.
 | 
	
		
			
				|  |  | -        PrintQuoting(cmd, ib, ie - ib);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      base.LogToolCommand(printer.ToString());
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    // Main task entry point.
 | 
	
		
			
				|  |  | -    public override bool Execute() {
 | 
	
		
			
				|  |  | -      base.UseCommandProcessor = false;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      bool ok = base.Execute();
 | 
	
		
			
				|  |  | -      if (!ok) {
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      // Read dependency output file from the compiler to retrieve the
 | 
	
		
			
				|  |  | -      // definitive list of created files. Report the dependency file
 | 
	
		
			
				|  |  | -      // itself as having been written to.
 | 
	
		
			
				|  |  | -      if (DependencyOut != null) {
 | 
	
		
			
				|  |  | -        string[] outputs = DepFileUtil.ReadDependencyOutputs(DependencyOut, Log);
 | 
	
		
			
				|  |  | -        if (HasLoggedErrors) {
 | 
	
		
			
				|  |  | -          return false;
 | 
	
		
			
				|  |  | +        // Called by the base class to log tool's command line.
 | 
	
		
			
				|  |  | +        //
 | 
	
		
			
				|  |  | +        // Protoc command file is peculiar, with one argument per line, separated
 | 
	
		
			
				|  |  | +        // by newlines. Unwrap it for log readability into a single line, and also
 | 
	
		
			
				|  |  | +        // quote arguments, lest it look weird and so it may be copied and pasted
 | 
	
		
			
				|  |  | +        // into shell. Since this is for logging only, correct enough is correct.
 | 
	
		
			
				|  |  | +        protected override void LogToolCommand(string cmd)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var printer = new StringBuilder(1024);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Print 'str' slice into 'printer', wrapping in quotes if contains some
 | 
	
		
			
				|  |  | +            // interesting characters in file names, or if empty string. The list of
 | 
	
		
			
				|  |  | +            // characters requiring quoting is not by any means exhaustive; we are
 | 
	
		
			
				|  |  | +            // just striving to be nice, not guaranteeing to be nice.
 | 
	
		
			
				|  |  | +            var quotable = new[] { ' ', '!', '$', '&', '\'', '^' };
 | 
	
		
			
				|  |  | +            void PrintQuoting(string str, int start, int count)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                bool wrap = count == 0 || str.IndexOfAny(quotable, start, count) >= 0;
 | 
	
		
			
				|  |  | +                if (wrap) printer.Append('"');
 | 
	
		
			
				|  |  | +                printer.Append(str, start, count);
 | 
	
		
			
				|  |  | +                if (wrap) printer.Append('"');
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (int ib = 0, ie; (ie = cmd.IndexOf('\n', ib)) >= 0; ib = ie + 1)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                // First line only contains both the program name and the first switch.
 | 
	
		
			
				|  |  | +                // We can rely on at least the '--out_dir' switch being always present.
 | 
	
		
			
				|  |  | +                if (ib == 0)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    int iep = cmd.IndexOf(" --");
 | 
	
		
			
				|  |  | +                    if (iep > 0)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        PrintQuoting(cmd, 0, iep);
 | 
	
		
			
				|  |  | +                        ib = iep + 1;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                printer.Append(' ');
 | 
	
		
			
				|  |  | +                if (cmd[ib] == '-')
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    // Print switch unquoted, including '=' if any.
 | 
	
		
			
				|  |  | +                    int iarg = cmd.IndexOf('=', ib, ie - ib);
 | 
	
		
			
				|  |  | +                    if (iarg < 0)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        // Bare switch without a '='.
 | 
	
		
			
				|  |  | +                        printer.Append(cmd, ib, ie - ib);
 | 
	
		
			
				|  |  | +                        continue;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                    printer.Append(cmd, ib, iarg + 1 - ib);
 | 
	
		
			
				|  |  | +                    ib = iarg + 1;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                // A positional argument or switch value.
 | 
	
		
			
				|  |  | +                PrintQuoting(cmd, ib, ie - ib);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            base.LogToolCommand(printer.ToString());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        GeneratedFiles = new ITaskItem[outputs.Length];
 | 
	
		
			
				|  |  | -        for (int i = 0; i < outputs.Length; i++) {
 | 
	
		
			
				|  |  | -          GeneratedFiles[i] = new TaskItem(outputs[i]);
 | 
	
		
			
				|  |  | +        // Main task entry point.
 | 
	
		
			
				|  |  | +        public override bool Execute()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            base.UseCommandProcessor = false;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            bool ok = base.Execute();
 | 
	
		
			
				|  |  | +            if (!ok)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                return false;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // Read dependency output file from the compiler to retrieve the
 | 
	
		
			
				|  |  | +            // definitive list of created files. Report the dependency file
 | 
	
		
			
				|  |  | +            // itself as having been written to.
 | 
	
		
			
				|  |  | +            if (DependencyOut != null)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                string[] outputs = DepFileUtil.ReadDependencyOutputs(DependencyOut, Log);
 | 
	
		
			
				|  |  | +                if (HasLoggedErrors)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    return false;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                GeneratedFiles = new ITaskItem[outputs.Length];
 | 
	
		
			
				|  |  | +                for (int i = 0; i < outputs.Length; i++)
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    GeneratedFiles[i] = new TaskItem(outputs[i]);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                AdditionalFileWrites = new ITaskItem[] { new TaskItem(DependencyOut) };
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return true;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        AdditionalFileWrites = new ITaskItem[] {
 | 
	
		
			
				|  |  | -          new TaskItem(DependencyOut)
 | 
	
		
			
				|  |  | -        };
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  };
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  |  }
 |