Skip to content
Open
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 @@ -808,7 +808,7 @@ internal int LastIndexOf(T item, int index, int count, IEqualityComparer<T>? equ

Requires.Range(index >= 0 && index < this.Count, nameof(index));
Requires.Range(count >= 0 && count <= this.Count, nameof(count));
Requires.Argument(index - count + 1 >= 0);
Requires.Range(index - count + 1 >= 0, nameof(count));
Copy link

Copilot AI Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change to use nameof(count) correctly aligns with ImmutableArray<T>.LastIndexOf and follows the established pattern in this codebase where range validation errors involving index + count or index - count are attributed to the count parameter (see line 765 for a similar pattern). However, there's an inconsistency with the FindLastIndex method at line 1249, which uses nameof(startIndex) for the equivalent validation check. Consider updating FindLastIndex in a follow-up change to use nameof(count) for consistency across both methods.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@prozolic prozolic Feb 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also change nameof(startIndex) in FindLastIndex(int, int, Predicate<T>) to nameof(count)?
If it should be changed, I'll also update the tests to validate the parameter as well.


equalityComparer ??= EqualityComparer<T>.Default;
using (var enumerator = new Enumerator(this, startIndex: index, count: count, reversed: true))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ public void LastIndexOf()
(b, v, eq) => b.LastIndexOf(v, b.Count > 0 ? b.Count - 1 : 0, b.Count, eq),
(b, v, i) => b.LastIndexOf(v, i),
(b, v, i, c) => b.LastIndexOf(v, i, c),
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq));
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq),
"startIndex",
"count");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -802,7 +802,9 @@ public void LastIndexOf()
(b, v, eq) => b.LastIndexOf(v, eq),
(b, v, i) => b.LastIndexOf(v, i),
(b, v, i, c) => b.LastIndexOf(v, i, c),
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq));
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq),
"startIndex",
"count");
}

[Theory]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,9 @@ public void LastIndexOf()
(b, v, eq) => b.LastIndexOf(v, b.Count > 0 ? b.Count - 1 : 0, b.Count, eq),
(b, v, i) => b.LastIndexOf(v, i),
(b, v, i, c) => b.LastIndexOf(v, i, c),
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq));
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq),
"index",
"count");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -512,14 +512,18 @@ public void LastIndexOf()
(b, v, eq) => b.LastIndexOf(v, eq),
(b, v, i) => b.LastIndexOf(v, i),
(b, v, i, c) => b.LastIndexOf(v, i, c),
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq));
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq),
"index",
"count");
IndexOfTests.LastIndexOfTest(
seq => (IImmutableList<int>)ImmutableList.CreateRange(seq),
(b, v) => b.LastIndexOf(v),
(b, v, eq) => b.LastIndexOf(v, eq),
(b, v, i) => b.LastIndexOf(v, i),
(b, v, i, c) => b.LastIndexOf(v, i, c),
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq));
(b, v, i, c, eq) => b.LastIndexOf(v, i, c, eq),
"index",
"count");
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,14 +177,17 @@ public void FindLastIndexTest()
ImmutableList<int> singleElementList = ImmutableList.Create(10);
Assert.Equal(0, this.GetListQuery(singleElementList).FindLastIndex(0, 1, n => n == 10));
Assert.Equal(-1, this.GetListQuery(singleElementList).FindLastIndex(0, 1, n => n == 99));
Assert.Throws<ArgumentOutOfRangeException>(() => this.GetListQuery(singleElementList).FindLastIndex(1, n => n == 10));
Assert.Throws<ArgumentOutOfRangeException>(() => this.GetListQuery(singleElementList).FindLastIndex(1, 1, n => n == 10));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(singleElementList).FindLastIndex(1, n => n == 10));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(singleElementList).FindLastIndex(1, 1, n => n == 10));
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => this.GetListQuery(singleElementList).FindLastIndex(0, 2, n => n == 10));

ImmutableList<int> multipleElementList = ImmutableList.Create(1, 2, 3, 4);
Assert.Equal(2, this.GetListQuery(multipleElementList).FindLastIndex(3, 4, n => n == 3));
Assert.Throws<ArgumentOutOfRangeException>(() => this.GetListQuery(multipleElementList).FindLastIndex(4, n => n == 1));
Assert.Throws<ArgumentOutOfRangeException>(() => this.GetListQuery(multipleElementList).FindLastIndex(4, 1, n => n == 1));
Assert.Throws<ArgumentOutOfRangeException>(() => this.GetListQuery(multipleElementList).FindLastIndex(4, 4, n => n == 1));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(multipleElementList).FindLastIndex(4, n => n == 1));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(multipleElementList).FindLastIndex(2, 4, n => n == 1));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(multipleElementList).FindLastIndex(4, 1, n => n == 1));
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => this.GetListQuery(multipleElementList).FindLastIndex(4, 4, n => n == 1));
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => this.GetListQuery(multipleElementList).FindLastIndex(3, 5, n => n == 1));

// Create a list with contents: 100,101,102,103,104,100,101,102,103,104
ImmutableList<int> list = ImmutableList<int>.Empty.AddRange(Enumerable.Range(100, 5).Concat(Enumerable.Range(100, 5)));
Expand Down
33 changes: 18 additions & 15 deletions src/libraries/System.Collections.Immutable/tests/IndexOfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,26 +85,29 @@ public static void LastIndexOfTest<TCollection>(
Func<TCollection, int, IEqualityComparer<int>, int> lastIndexOfItemEQ,
Func<TCollection, int, int, int> lastIndexOfItemIndex,
Func<TCollection, int, int, int, int> lastIndexOfItemIndexCount,
Func<TCollection, int, int, int, IEqualityComparer<int>, int> lastIndexOfItemIndexCountEQ)
Func<TCollection, int, int, int, IEqualityComparer<int>, int> lastIndexOfItemIndexCountEQ,
string expectedIndexParamName,
string expectedCountParamName)
{
TCollection emptyCollection = factory(new int[0]);
TCollection singleCollection = factory(new[] { 10 });
TCollection collection1256 = factory(new[] { 1, 2, 5, 6 });

Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(emptyCollection, 100, 1, 1, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(emptyCollection, 100, -1, 1, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(singleCollection, 100, 1, 1, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(singleCollection, 100, -1, 1, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, 20, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, -1, EqualityComparer<int>.Default));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(emptyCollection, 100, 1, 1, new CustomComparer(50)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(emptyCollection, 100, -1, 1, new CustomComparer(50)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(singleCollection, 100, 1, 1, new CustomComparer(50)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(singleCollection, 100, -1, 1, new CustomComparer(50)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, 20, new CustomComparer(1)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, -1, new CustomComparer(1)));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndex(collection1256, 2, 5));
Assert.Throws<ArgumentOutOfRangeException>(() => lastIndexOfItemIndexCountEQ(collection1256, 6, 4, 4, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(emptyCollection, 100, 1, 1, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(emptyCollection, 100, -1, 1, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(singleCollection, 100, 1, 1, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(singleCollection, 100, -1, 1, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedCountParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, 20, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedCountParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, -1, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(emptyCollection, 100, 1, 1, new CustomComparer(50)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(emptyCollection, 100, -1, 1, new CustomComparer(50)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(singleCollection, 100, 1, 1, new CustomComparer(50)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(singleCollection, 100, -1, 1, new CustomComparer(50)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedCountParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, 20, new CustomComparer(1)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedCountParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 100, 1, -1, new CustomComparer(1)));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndex(collection1256, 2, 5));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedCountParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 6, 2, 4, EqualityComparer<int>.Default));
AssertExtensions.Throws<ArgumentOutOfRangeException>(expectedIndexParamName, () => lastIndexOfItemIndexCountEQ(collection1256, 6, 4, 4, EqualityComparer<int>.Default));

Assert.Equal(-1, lastIndexOfItem(emptyCollection, 5));
Assert.Equal(-1, lastIndexOfItemEQ(emptyCollection, 5, EqualityComparer<int>.Default));
Expand Down
Loading