| File: parent\Shared\TaskHostBuildResponse.cs | Web Access |
| Project: MSBuild.csproj (MSBuild) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using Microsoft.Build.Framework; namespace Microsoft.Build.BackEnd { /// <summary> /// Response packet from owning worker node to TaskHost with BuildProjectFile* results. /// Carries the build success/failure and target outputs per project. /// </summary> internal class TaskHostBuildResponse : INodePacket, ITaskHostCallbackPacket { private int _requestId; private bool _success; /// <summary> /// Target outputs per project. Each entry is a dictionary mapping target names to TaskParameter /// wrapping ITaskItem[] outputs. Uses the same TaskParameter serialization as TaskHostTaskComplete. /// </summary> private List<Dictionary<string, TaskParameter>>? _targetOutputsPerProject; public TaskHostBuildResponse() { } public TaskHostBuildResponse(int requestId, bool success, List<Dictionary<string, TaskParameter>>? targetOutputsPerProject) { _requestId = requestId; _success = success; _targetOutputsPerProject = targetOutputsPerProject; } public NodePacketType Type => NodePacketType.TaskHostBuildResponse; public int RequestId { get => _requestId; set => _requestId = value; } /// <summary>Whether the build succeeded.</summary> public bool Success => _success; /// <summary>Per-project target outputs, or null if outputs were not requested.</summary> public List<Dictionary<string, TaskParameter>>? TargetOutputsPerProject => _targetOutputsPerProject; /// <summary> /// Reconstructs a <see cref="BuildEngineResult"/> from this response packet. /// Converts <see cref="TaskParameter"/> values back to <see cref="ITaskItem"/>[] arrays. /// </summary> public BuildEngineResult ToBuildEngineResult() { List<IDictionary<string, ITaskItem[]>>? result = null; if (_targetOutputsPerProject is not null) { result = new List<IDictionary<string, ITaskItem[]>>(_targetOutputsPerProject.Count); foreach (Dictionary<string, TaskParameter> projectOutputs in _targetOutputsPerProject) { var dict = new Dictionary<string, ITaskItem[]>(projectOutputs.Count, StringComparer.OrdinalIgnoreCase); if (projectOutputs is not null) { foreach (KeyValuePair<string, TaskParameter> entry in projectOutputs) { dict[entry.Key] = (ITaskItem[]?)entry.Value?.WrappedParameter ?? []; } } result.Add(dict); } } return new BuildEngineResult(_success, result ?? []); } /// <summary> /// Creates a response from a <see cref="BuildEngineResult"/>. /// Wraps <see cref="ITaskItem"/>[] arrays in <see cref="TaskParameter"/> for serialization. /// </summary> internal static TaskHostBuildResponse FromBuildEngineResult(int requestId, BuildEngineResult engineResult) { List<Dictionary<string, TaskParameter>>? outputs = null; if (engineResult.TargetOutputsPerProject is not null && engineResult.TargetOutputsPerProject.Count > 0) { outputs = new List<Dictionary<string, TaskParameter>>(engineResult.TargetOutputsPerProject.Count); foreach (IDictionary<string, ITaskItem[]> projectOutputs in engineResult.TargetOutputsPerProject) { var dict = new Dictionary<string, TaskParameter>(projectOutputs?.Count ?? 0, StringComparer.OrdinalIgnoreCase); if (projectOutputs is not null) { foreach (KeyValuePair<string, ITaskItem[]> entry in projectOutputs) { dict[entry.Key] = new TaskParameter(entry.Value); } } outputs.Add(dict); } } return new TaskHostBuildResponse(requestId, engineResult.Result, outputs); } public void Translate(ITranslator translator) { translator.Translate(ref _requestId); translator.Translate(ref _success); TranslateTargetOutputs(translator); } private void TranslateTargetOutputs(ITranslator translator) { bool hasOutputs = _targetOutputsPerProject is not null; translator.Translate(ref hasOutputs); if (!hasOutputs) { _targetOutputsPerProject = null; return; } int count = _targetOutputsPerProject?.Count ?? 0; translator.Translate(ref count); if (translator.Mode == TranslationDirection.ReadFromStream) { _targetOutputsPerProject = new List<Dictionary<string, TaskParameter>>(count); for (int i = 0; i < count; i++) { Dictionary<string, TaskParameter>? dict = null; translator.TranslateDictionary(ref dict, StringComparer.OrdinalIgnoreCase, TaskParameter.FactoryForDeserialization); _targetOutputsPerProject.Add(dict!); } } else { for (int i = 0; i < count; i++) { Dictionary<string, TaskParameter>? dict = _targetOutputsPerProject![i]; translator.TranslateDictionary(ref dict, StringComparer.OrdinalIgnoreCase, TaskParameter.FactoryForDeserialization); } } } internal static INodePacket FactoryForDeserialization(ITranslator translator) { var packet = new TaskHostBuildResponse(); packet.Translate(translator); return packet; } } }