• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #region Copyright notice and license
2 
3 // Copyright 2018 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #endregion
18 
19 using System.Collections.Generic;
20 using Microsoft.Build.Framework;
21 using Microsoft.Build.Utilities;
22 
23 namespace Grpc.Tools
24 {
25     public class ProtoCompilerOutputs : Task
26     {
27         /// <summary>
28         /// Code generator. Currently supported are "csharp", "cpp".
29         /// </summary>
30         [Required]
31         public string Generator { get; set; }
32 
33         /// <summary>
34         /// All Proto files in the project. The task computes possible outputs
35         /// from these proto files, and returns them in the PossibleOutputs list.
36         /// Not all of these might be actually produced by protoc; this is dealt
37         /// with later in the ProtoCompile task which returns the list of
38         /// files actually produced by the compiler.
39         /// </summary>
40         [Required]
41         public ITaskItem[] Protobuf { get; set; }
42 
43         /// <summary>
44         /// All Proto files in the project. A patched copy of all items from
45         /// Protobuf that might contain updated OutputDir and GrpcOutputDir
46         /// attributes.
47         /// </summary>
48         [Output]
49         public ITaskItem[] PatchedProtobuf { get; set; }
50 
51         /// <summary>
52         /// Output items per each potential output. We do not look at existing
53         /// cached dependency even if they exist, since file may be refactored,
54         /// affecting whether or not gRPC code file is generated from a given proto.
55         /// Instead, all potentially possible generated sources are collected.
56         /// It is a wise idea to generate empty files later for those potentials
57         /// that are not actually created by protoc, so the dependency checks
58         /// result in a minimal recompilation. The Protoc task can output the
59         /// list of files it actually produces, given right combination of its
60         /// properties.
61         /// Output items will have the Source metadata set on them:
62         ///     <ItemName Include="MyProto.cs" Source="my_proto.proto" />
63         /// </summary>
64         [Output]
65         public ITaskItem[] PossibleOutputs { get; private set; }
66 
Execute()67         public override bool Execute()
68         {
69             var generator = GeneratorServices.GetForLanguage(Generator, Log);
70             if (generator == null)
71             {
72                 // Error already logged, just return.
73                 return false;
74             }
75 
76             // Get language-specific possible output. The generator expects certain
77             // metadata be set on the proto item.
78             var possible = new List<ITaskItem>();
79             var patched = new List<ITaskItem>();
80             foreach (var proto in Protobuf)
81             {
82                 var patchedProto = generator.PatchOutputDirectory(proto);
83                 patched.Add(patchedProto);
84 
85                 var outputs = generator.GetPossibleOutputs(patchedProto);
86                 foreach (string output in outputs)
87                 {
88                     var ti = new TaskItem(output);
89                     ti.SetMetadata(Metadata.Source, patchedProto.ItemSpec);
90                     possible.Add(ti);
91                 }
92             }
93 
94             PatchedProtobuf = patched.ToArray();
95             PossibleOutputs = possible.ToArray();
96 
97             return !Log.HasLoggedErrors;
98         }
99     };
100 }
101