#region Copyright notice and license // Copyright 2018 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #endregion using System.Collections.Generic; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; namespace Grpc.Tools { public class ProtoCompilerOutputs : Task { /// /// Code generator. Currently supported are "csharp", "cpp". /// [Required] public string Generator { get; set; } /// /// All Proto files in the project. The task computes possible outputs /// from these proto files, and returns them in the PossibleOutputs list. /// Not all of these might be actually produced by protoc; this is dealt /// with later in the ProtoCompile task which returns the list of /// files actually produced by the compiler. /// [Required] public ITaskItem[] ProtoBuf { get; set; } /// /// Output items per each potential output. We do not look at existing /// cached dependency even if they exist, since file may be refactored, /// affecting whether or not gRPC code file is generated from a given proto. /// Instead, all potentially possible generated sources are collected. /// It is a wise idea to generate empty files later for those potentials /// that are not actually created by protoc, so the dependency checks /// result in a minimal recompilation. The Protoc task can output the /// list of files it actually produces, given right combination of its /// properties. /// Output items will have the Source metadata set on them: /// /// [Output] public ITaskItem[] PossibleOutputs { get; private set; } public override bool Execute() { var generator = GeneratorServices.GetForLanguage(Generator, Log); if (generator == null) { // Error already logged, just return. return false; } // Get language-specific possible output. The generator expects certain // metadata be set on the proto item. var possible = new List(); foreach (var proto in ProtoBuf) { var outputs = generator.GetPossibleOutputs(proto); foreach (string output in outputs) { var ti = new TaskItem(output); ti.SetMetadata(Metadata.Source, proto.ItemSpec); possible.Add(ti); } } PossibleOutputs = possible.ToArray(); return !Log.HasLoggedErrors; } }; }