File: FindInList.cs
Web Access
Project: ..\..\..\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.IO;
 
using Microsoft.Build.Framework;
using Microsoft.Build.Shared;
 
#nullable disable
 
namespace Microsoft.Build.Tasks
{
    /// <summary>
    /// A task that finds an item with the specified itemspec, if present,
    /// in the provided list.
    /// </summary>
    public class FindInList : TaskExtension
    {
        private ITaskItem[] _list;
 
        /// <summary>
        /// The list to search through
        /// </summary>
        [Required]
        public ITaskItem[] List
        {
            get
            {
                ErrorUtilities.VerifyThrowArgumentNull(_list, nameof(List));
                return _list;
            }
            set => _list = value;
        }
 
        /// <summary>
        /// Whether to match against just the file part of the itemspec,
        /// or the whole itemspec (the default)
        /// </summary>
        public bool MatchFileNameOnly { get; set; }
 
        /// <summary>
        /// The first matching item found in the list, if any
        /// </summary>
        [Output]
        public ITaskItem ItemFound { get; set; }
 
        /// <summary>
        /// The itemspec to try to find
        /// </summary>
        [Required]
        public string ItemSpecToFind { get; set; }
 
        /// <summary>
        /// Whether or not to match case sensitively
        /// </summary>
        public bool CaseSensitive { get; set; }
 
        /// <summary>
        /// Whether or not to return the last match, instead of
        /// the first one
        /// </summary>
        public bool FindLastMatch { get; set; }
 
        /// <summary>
        /// Entry point
        /// </summary>
        public override bool Execute()
        {
            StringComparison comparison = CaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
 
            if (!FindLastMatch)
            {
                // Walk forwards
                foreach (ITaskItem item in List)
                {
                    if (IsMatchingItem(comparison, item))
                    {
                        return true;
                    }
                }
            }
            else
            {
                // Walk backwards
                for (int i = List.Length - 1; i >= 0; i--)
                {
                    if (IsMatchingItem(comparison, List[i]))
                    {
                        return true;
                    }
                }
            }
 
            // Not found
            return true;
        }
 
        /// <summary>
        /// Examines the item to see if it matches what we are looking for.
        /// If it does, returns true.
        /// </summary>
        private bool IsMatchingItem(StringComparison comparison, ITaskItem item)
        {
            try
            {
                var path = FileUtilities.FixFilePath(item.ItemSpec);
                string filename = (MatchFileNameOnly ? Path.GetFileName(path) : path);
 
                if (String.Equals(filename, ItemSpecToFind, comparison))
                {
                    ItemFound = item;
                    Log.LogMessageFromResources(MessageImportance.Low, "FindInList.Found", path);
                    return true;
                }
            }
            catch (ArgumentException ex)
            {
                // Just log this: presumably this item spec is not intended to be
                // a file path
                Log.LogMessageFromResources(MessageImportance.Low, "FindInList.InvalidPath", item.ItemSpec, ex.Message);
            }
            return false;
        }
    }
}