| File: AssemblyDependency\Node\RarNodeExecuteResponse.cs | Web Access |
| Project: src\msbuild\src\Tasks\Microsoft.Build.Tasks.csproj (Microsoft.Build.Tasks.Core) |
// 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.BackEnd; using Microsoft.Build.Framework; using Microsoft.Build.Shared; using ParameterType = Microsoft.Build.Tasks.AssemblyDependency.RarTaskParameters.ParameterType; namespace Microsoft.Build.Tasks.AssemblyDependency { /// <summary> /// Extracts and hydrates task outputs for ResolveAssemblyReference. /// </summary> internal sealed class RarNodeExecuteResponse : INodePacket { private Dictionary<string, TaskParameter> _taskOutputs = new(StringComparer.Ordinal); private int _numCopyLocalFiles; private bool _success; internal RarNodeExecuteResponse(ResolveAssemblyReference rar, bool success) { _taskOutputs = RarTaskParameters.Get(ParameterType.Output, rar); _numCopyLocalFiles = rar.CopyLocalFiles.Length; _success = success; } internal RarNodeExecuteResponse(ITranslator translator) => Translate(translator); public NodePacketType Type => NodePacketType.RarNodeExecuteResponse; internal bool Success => _success; public void Translate(ITranslator translator) { // TODO: The main outputs (e.g. ResolvedFiles, ResolvedDependencyFiles) will go through a different TaskItem // serialization path. Sequential items in each output share the same set of metadata keys and similar values, // so we can save a ton of overhead (and precompute the CopyLocal check) by breaking out of TaskParameter. translator.TranslateDictionary(ref _taskOutputs, StringComparer.Ordinal, TaskParameter.FactoryForDeserialization); translator.Translate(ref _numCopyLocalFiles); translator.Translate(ref _success); } internal void SetTaskOutputs(ResolveAssemblyReference rar) { RarTaskParameters.Set(ParameterType.Output, rar, _taskOutputs); if (_numCopyLocalFiles == 0) { return; } // CopyLocalFiles consists of a list of references. Although the reference equality itself doesn't matter since // the engine will later create copies, we can skip serializing these and reconstruct them on the client. int i = 0; ITaskItem[] copyLocalFiles = new ITaskItem[_numCopyLocalFiles]; FindCopyLocalFiles(copyLocalFiles, ref i, rar.ResolvedFiles); FindCopyLocalFiles(copyLocalFiles, ref i, rar.ResolvedDependencyFiles); FindCopyLocalFiles(copyLocalFiles, ref i, rar.RelatedFiles); FindCopyLocalFiles(copyLocalFiles, ref i, rar.SatelliteFiles); FindCopyLocalFiles(copyLocalFiles, ref i, rar.SerializationAssemblyFiles); FindCopyLocalFiles(copyLocalFiles, ref i, rar.ScatterFiles); static void FindCopyLocalFiles(ITaskItem[] copyLocalFiles, ref int i, ITaskItem[] items) { foreach (ITaskItem taskItem in items) { // Prefer ITaskItem2 as it skips escaping checks. This should always be true coming from RAR. string isCopyLocal = taskItem is ITaskItem2 taskItem2 ? taskItem2.GetMetadataValueEscaped(ItemMetadataNames.copyLocal) : taskItem.GetMetadata(ItemMetadataNames.copyLocal); if (string.Equals(isCopyLocal, "true", StringComparison.OrdinalIgnoreCase)) { copyLocalFiles[i] = taskItem; i++; } } } rar.CopyLocalFiles = copyLocalFiles; } } }