Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private ProjectLoggingContext(
List<string> targets,
string toolsVersion,
PropertyDictionary<ProjectPropertyInstance> projectProperties,
ItemDictionary<ProjectItemInstance> projectItems,
IItemDictionary<ProjectItemInstance> projectItems,
BuildEventContext parentBuildEventContext,
int evaluationId,
int projectContextId)
Expand Down
14 changes: 7 additions & 7 deletions src/Build/BackEnd/Components/RequestBuilder/Lookup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ internal class Lookup : IPropertyProvider<ProjectPropertyInstance>, IItemProvide
/// <summary>
/// Construct a lookup over specified items and properties.
/// </summary>
internal Lookup(ItemDictionary<ProjectItemInstance> projectItems, PropertyDictionary<ProjectPropertyInstance> properties)
internal Lookup(IItemDictionary<ProjectItemInstance> projectItems, PropertyDictionary<ProjectPropertyInstance> properties)
{
ErrorUtilities.VerifyThrowInternalNull(projectItems, nameof(projectItems));
ErrorUtilities.VerifyThrowInternalNull(properties, nameof(properties));
Expand Down Expand Up @@ -120,7 +120,7 @@ private Lookup(Lookup that)
// Convenience private properties
// "Primary" is the "top" or "innermost" scope
// "Secondary" is the next from the top.
private ItemDictionary<ProjectItemInstance> PrimaryTable
private IItemDictionary<ProjectItemInstance> PrimaryTable
{
get { return _lookupScopes.First.Value.Items; }
set { _lookupScopes.First.Value.Items = value; }
Expand Down Expand Up @@ -150,7 +150,7 @@ private PropertyDictionary<ProjectPropertyInstance> PrimaryPropertySets
set { _lookupScopes.First.Value.PropertySets = value; }
}

private ItemDictionary<ProjectItemInstance> SecondaryTable
private IItemDictionary<ProjectItemInstance> SecondaryTable
{
get { return _lookupScopes.First.Next.Value.Items; }
set { _lookupScopes.First.Next.Value.Items = value; }
Expand Down Expand Up @@ -870,7 +870,7 @@ private ProjectItemInstance RetrieveOriginalFromCloneTable(ProjectItemInstance i
/// Applies a list of modifications to the appropriate <see cref="ItemDictionary{ProjectItemInstance}" /> in a main table.
/// If any modifications conflict, these modifications win.
/// </summary>
private void ApplyModificationsToTable(ItemDictionary<ProjectItemInstance> table, string itemType, ItemsMetadataUpdateDictionary modify)
private void ApplyModificationsToTable(IItemDictionary<ProjectItemInstance> table, string itemType, ItemsMetadataUpdateDictionary modify)
{
ICollection<ProjectItemInstance> existing = table[itemType];
if (existing != null)
Expand Down Expand Up @@ -1295,7 +1295,7 @@ internal class Scope
/// <summary>
/// Contains all of the original items at this level in the Lookup
/// </summary>
private ItemDictionary<ProjectItemInstance> _items;
private IItemDictionary<ProjectItemInstance> _items;

/// <summary>
/// Contains all of the items which have been added at this level in the Lookup
Expand Down Expand Up @@ -1344,7 +1344,7 @@ internal class Scope
/// </summary>
private bool _truncateLookupsAtThisScope;

internal Scope(Lookup lookup, string description, ItemDictionary<ProjectItemInstance> items, PropertyDictionary<ProjectPropertyInstance> properties)
internal Scope(Lookup lookup, string description, IItemDictionary<ProjectItemInstance> items, PropertyDictionary<ProjectPropertyInstance> properties)
{
_owningLookup = lookup;
_description = description;
Expand All @@ -1364,7 +1364,7 @@ internal Scope(Lookup lookup, string description, ItemDictionary<ProjectItemInst
/// include adds or removes unless it's the table in
/// the outermost scope.
/// </summary>
internal ItemDictionary<ProjectItemInstance> Items
internal IItemDictionary<ProjectItemInstance> Items
{
get { return _items; }
set { _items = value; }
Expand Down
31 changes: 31 additions & 0 deletions src/Build/Collections/IConstrainableDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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;

namespace Microsoft.Build.Collections
{
/// <summary>
/// Represents an <see cref="IDictionary{String, TValue}"/> that supports use of an
/// <see cref="IConstrainedEqualityComparer{T}"/>.
/// </summary>
/// <typeparam name="TValue">The type of the values in the dictionary. The key is assumed
/// to always be <see cref="String"/>.</typeparam>
internal interface IConstrainableDictionary<TValue> : IDictionary<string, TValue>
{
/// <summary>
/// Get the value with the specified key or null if it is not present.
/// The key used for lookup is the substring of <paramref name="keyString"/>
/// starting at <paramref name="startIndex"/> and ending at <paramref name="endIndex"/>
/// (e.g. if the key is just the first character in <paramref name="keyString"/>, then
/// the value for <paramref name="startIndex"/> should be 0 and the value for
/// <paramref name="endIndex"/> should also be 0.)
/// </summary>
/// <param name="keyString">A string that contains the key of the item to retrieve.</param>
/// <param name="startIndex">The start index of the substring of <paramref name="keyString"/> that contains the key.</param>
/// <param name="endIndex">The end index of the substring of <paramref name="keyString"/> that contains the key.</param>
/// <returns>If it's found, the item whose key matches the calculated substring. Null otherwise.</returns>
TValue? Get(string keyString, int startIndex, int endIndex);
}
}
134 changes: 134 additions & 0 deletions src/Build/Collections/IItemDictionary.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// 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;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Shared;

namespace Microsoft.Build.Collections
{
internal interface IItemDictionary<T> : IEnumerable<T>, IItemProvider<T>
where T : class, IKeyed, IItem
{
/// <summary>
/// Number of items in total, for debugging purposes.
/// </summary>
int Count { get; }

/// <summary>
/// Get the item types that have at least one item in this collection.
/// </summary>
/// <remarks>
/// KeyCollection&lt;K&gt; is already a read only collection, so no protection
/// is necessary.
/// </remarks>
ICollection<string> ItemTypes { get; }

/// <summary>
/// Returns the item list for a particular item type,
/// creating and adding a new item list if necessary.
/// Does not throw if there are no items of this type.
/// This is a read-only list.
/// If the result is not empty it is a live list.
/// Use AddItem or RemoveItem to modify items in this project.
/// Using the return value from this in a multithreaded situation is unsafe.
/// </summary>
ICollection<T> this[string itemType] { get; }

/// <summary>
/// Empty the collection.
/// </summary>
void Clear();

/// <summary>
/// Returns an enumerable which copies the underlying data on read.
/// </summary>
IEnumerable<TResult> GetCopyOnReadEnumerable<TResult>(Func<T, TResult> selector);

/// <summary>
/// Enumerates item lists per each item type under the lock.
/// </summary>
/// <param name="itemTypeCallback">
/// A delegate that accepts the item type string and a list of items of that type.
/// Will be called for each item type in the list.
/// </param>
void EnumerateItemsPerType(Action<string, IEnumerable<T>> itemTypeCallback);

/// <summary>
/// Whether the provided item is in this table or not.
/// </summary>
bool Contains(T projectItem);

/// <summary>
/// Add a new item to the collection, at the
/// end of the list of other items with its key.
/// </summary>
void Add(T projectItem);

/// <summary>
/// Adds each new item to the collection, at the
/// end of the list of other items with the same key.
/// </summary>
void AddRange(IEnumerable<T> projectItems);

/// <summary>
/// Removes an item, if it is in the collection.
/// Returns true if it was found, otherwise false.
/// </summary>
/// <remarks>
/// If a list is emptied, removes the list from the enclosing collection
/// so it can be garbage collected.
/// </remarks>
bool Remove(T projectItem);

/// <summary>
/// Replaces an existing item with a new item. This is necessary to preserve the original ordering semantics of Lookup.GetItems
/// when items with metadata modifications are being returned. See Dev10 bug 480737.
/// If the item is not found, does nothing.
/// </summary>
/// <param name="existingItem">The item to be replaced.</param>
/// <param name="newItem">The replacement item.</param>
void Replace(T existingItem, T newItem);

/// <summary>
/// Add the set of items specified to this dictionary.
/// </summary>
/// <param name="other">An enumerator over the items to remove.</param>
void ImportItems(IEnumerable<T> other);

/// <summary>
/// Add the set of items specified, all sharing an item type, to this dictionary.
/// </summary>
/// <comment>
/// This is a little faster than ImportItems where all the items have the same item type.
/// </comment>
void ImportItemsOfType(string itemType, IEnumerable<T> items);

/// <summary>
/// Remove the set of items specified from this dictionary
/// </summary>
/// <param name="other">An enumerator over the items to remove.</param>
void RemoveItems(IEnumerable<T> other);

/// <summary>
/// Special method used for batching buckets.
/// Adds an explicit marker indicating there are no items for the specified item type.
/// In the general case, this is redundant, but batching buckets use this to indicate that they are
/// batching over the item type, but their bucket does not contain items of that type.
/// See <see cref="HasEmptyMarker">HasEmptyMarker</see>.
/// </summary>
void AddEmptyMarker(string itemType);

/// <summary>
/// Special method used for batching buckets.
/// Lookup can call this to see whether there was an explicit marker placed indicating that
/// there are no items of this type. See comment on <see cref="AddEmptyMarker">AddEmptyMarker</see>.
/// </summary>
bool HasEmptyMarker(string itemType);
}
}
Loading