This is an automated email from the ASF dual-hosted git repository. nightowl888 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/lucenenet.git
commit 2632993dbabc4ffe1edcca8bbe0f2e718e3ec32a Author: Shad Storhaug <[email protected]> AuthorDate: Sat Feb 8 15:08:44 2020 +0700 BREAKING: Lucene.Net.Support.ListExtensions: Moved AddRange, Sort, TimSort, and IntroSort extension methods to Lucene.Net.Util.ListExtensions. Marked Lucene.Net.Support.ListExtensions internal. --- .../CharFilter/MappingCharFilterFactory.cs | 6 +- .../Language/Bm/PhoneticEngine.cs | 48 ++--- .../Language/Bm/Rule.cs | 52 ++---- .../Language/DaitchMokotoffSoundex.cs | 23 +-- .../ByTask/Feeds/ContentItemsSource.cs | 2 +- .../RemoveEmptyNonLeafQueryNodeProcessor.cs | 2 +- .../CommonTermsQueryTest.cs | 4 +- .../Index/TestBackwardsCompatibility.cs | 4 +- .../Index/TestBackwardsCompatibility3x.cs | 4 +- src/Lucene.Net.Tests/Search/TestMinShouldMatch2.cs | 1 + src/Lucene.Net.Tests/Search/TestSort.cs | 3 +- src/Lucene.Net/Properties/AssemblyInfo.cs | 1 + src/Lucene.Net/Search/DisjunctionMaxQuery.cs | 2 +- src/Lucene.Net/Search/Spans/NearSpansOrdered.cs | 8 +- src/Lucene.Net/Support/ListExtensions.cs | 198 +++------------------ src/Lucene.Net/Support/Util/ListExtensions.cs | 160 +++++++++++++++++ 16 files changed, 238 insertions(+), 280 deletions(-) diff --git a/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/MappingCharFilterFactory.cs b/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/MappingCharFilterFactory.cs index 7d47f76..13dd334 100644 --- a/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/MappingCharFilterFactory.cs +++ b/src/Lucene.Net.Analysis.Common/Analysis/CharFilter/MappingCharFilterFactory.cs @@ -1,5 +1,5 @@ using Lucene.Net.Analysis.Util; -using Lucene.Net.Support; +using Lucene.Net.Util; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; @@ -57,7 +57,7 @@ namespace Lucene.Net.Analysis.CharFilters { if (mapping != null) { - IList<string> wlist = null; + IList<string> wlist; if (File.Exists(mapping)) { wlist = new List<string>(GetLines(loader, mapping)); @@ -92,7 +92,7 @@ namespace Lucene.Net.Analysis.CharFilters } // "source" => "target" - private static Regex p = new Regex(@"\""(.*)\""\s*=>\s*\""(.*)\""\s*$", RegexOptions.Compiled); + private static readonly Regex p = new Regex(@"\""(.*)\""\s*=>\s*\""(.*)\""\s*$", RegexOptions.Compiled); protected virtual void ParseRules(IList<string> rules, NormalizeCharMap.Builder builder) { diff --git a/src/Lucene.Net.Analysis.Phonetic/Language/Bm/PhoneticEngine.cs b/src/Lucene.Net.Analysis.Phonetic/Language/Bm/PhoneticEngine.cs index 8223c86..283f1d5 100644 --- a/src/Lucene.Net.Analysis.Phonetic/Language/Bm/PhoneticEngine.cs +++ b/src/Lucene.Net.Analysis.Phonetic/Language/Bm/PhoneticEngine.cs @@ -2,6 +2,7 @@ using J2N.Collections.Generic.Extensions; using J2N.Text; using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.Collections.Generic; using System.Linq; @@ -166,10 +167,7 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm /// <summary> /// Gets underlying phoneme set. Please don't mutate. /// </summary> - public IList<Phoneme> Phonemes - { - get { return this.phonemes; } - } + public IList<Phoneme> Phonemes => phonemes; /// <summary> /// Stringifies the phoneme set. This produces a single string of the strings of each phoneme, @@ -231,15 +229,9 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm this.maxPhonemes = maxPhonemes; } - public int I - { - get { return this.i; } - } + public int I => i; - public PhonemeBuilder PhonemeBuilder - { - get { return this.phonemeBuilder; } - } + public PhonemeBuilder PhonemeBuilder => phonemeBuilder; /// <summary> /// Invokes the rules. Loops over the rules list, stopping at the first one that has a matching context @@ -276,10 +268,7 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm return this; } - public bool IsFound - { - get { return this.found; } - } + public bool IsFound => found; } private static readonly IDictionary<NameType, ISet<string>> NAME_PREFIXES = LoadNamePrefixes(); @@ -319,7 +308,7 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm return sb.ToString(); } - private static readonly int DEFAULT_MAX_PHONEMES = 20; + private const int DEFAULT_MAX_PHONEMES = 20; private readonly Lang lang; @@ -534,44 +523,29 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm /// <summary> /// Gets the Lang language guessing rules being used. /// </summary> - public virtual Lang Lang - { - get { return this.lang; } - } + public virtual Lang Lang => lang; /// <summary> /// Gets the <see cref="Bm.NameType"/> being used. /// </summary> - public virtual NameType NameType - { - get { return this.nameType; } - } + public virtual NameType NameType => nameType; /// <summary> /// Gets the <see cref="Bm.RuleType"/> being used. /// </summary> - public virtual RuleType RuleType - { - get { return this.ruleType; } - } + public virtual RuleType RuleType => ruleType; /// <summary> /// Gets if multiple phonetic encodings are concatenated or if just the first one is kept. /// Returns <c>true</c> if multiple phonetic encodings are returned, <c>false</c> if just the first is. /// </summary> - public virtual bool IsConcat - { - get { return this.concat; } - } + public virtual bool IsConcat => concat; /// <summary> /// Gets the maximum number of phonemes the engine will calculate for a given input. /// <para/> /// since 1.7 /// </summary> - public virtual int MaxPhonemes - { - get { return this.maxPhonemes; } - } + public virtual int MaxPhonemes => maxPhonemes; } } diff --git a/src/Lucene.Net.Analysis.Phonetic/Language/Bm/Rule.cs b/src/Lucene.Net.Analysis.Phonetic/Language/Bm/Rule.cs index 7b0d413..b93d980 100644 --- a/src/Lucene.Net.Analysis.Phonetic/Language/Bm/Rule.cs +++ b/src/Lucene.Net.Analysis.Phonetic/Language/Bm/Rule.cs @@ -3,6 +3,7 @@ using J2N; using J2N.Collections.Generic.Extensions; using J2N.Text; using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.Collections.Generic; using System.IO; @@ -87,9 +88,9 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm /// </remarks> public class Rule { - private static Regex PIPE = new Regex("[|]", RegexOptions.Compiled); - private static Regex WHITESPACE = new Regex("\\s+", RegexOptions.Compiled); - private static Regex PLUS = new Regex("[+]", RegexOptions.Compiled); + private static readonly Regex PIPE = new Regex("[|]", RegexOptions.Compiled); + private static readonly Regex WHITESPACE = new Regex("\\s+", RegexOptions.Compiled); + private static readonly Regex PLUS = new Regex("[+]", RegexOptions.Compiled); private class AllStringsRMatcher : IRPattern { @@ -112,11 +113,11 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm public static readonly IRPattern ALL_STRINGS_RMATCHER = new AllStringsRMatcher(); - public static readonly string ALL = "ALL"; + public const string ALL = "ALL"; - private static readonly string DOUBLE_QUOTE = "\""; + private const string DOUBLE_QUOTE = "\""; - private static readonly string HASH_INCLUDE = "#include"; + private const string HASH_INCLUDE = "#include"; private static readonly IDictionary<NameType, IDictionary<RuleType, IDictionary<string, IDictionary<string, IList<Rule>>>>> RULES = LoadRules(); @@ -806,34 +807,22 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm /// <summary> /// Gets the left context pattern. This is a regular expression that must match to the left of the pattern. /// </summary> - public virtual IRPattern LContext - { - get { return this.lContext; } - } + public virtual IRPattern LContext => lContext; /// <summary> /// Gets the pattern. This is a string-literal that must exactly match. /// </summary> - public virtual string Pattern - { - get { return this.pattern; } - } + public virtual string Pattern => pattern; /// <summary> /// Gets the phoneme. If the rule matches, this is the phoneme associated with the pattern match. /// </summary> - public virtual IPhonemeExpr Phoneme - { - get { return this.phoneme; } - } + public virtual IPhonemeExpr Phoneme => phoneme; /// <summary> /// Gets the right context pattern. This is a regular expression that must match to the right of the pattern. /// </summary> - public virtual IRPattern RContext - { - get { return this.rContext; } - } + public virtual IRPattern RContext => rContext; /// <summary> /// Decides if the pattern and context match the input starting at a position. It is a match if the @@ -1018,15 +1007,9 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm return this; } - public LanguageSet Languages - { - get { return this.languages; } - } + public LanguageSet Languages => languages; - public IList<Phoneme> Phonemes - { - get { return new Phoneme[] { this }; } - } + public IList<Phoneme> Phonemes => new Phoneme[] { this }; public string GetPhonemeText() { @@ -1048,17 +1031,12 @@ namespace Lucene.Net.Analysis.Phonetic.Language.Bm public sealed class PhonemeList : IPhonemeExpr { - private readonly IList<Phoneme> phonemes; - public PhonemeList(IList<Phoneme> phonemes) { - this.phonemes = phonemes; + this.Phonemes = phonemes; } - public IList<Phoneme> Phonemes - { - get { return this.phonemes; } - } + public IList<Phoneme> Phonemes { get; private set; } } /// <summary> diff --git a/src/Lucene.Net.Analysis.Phonetic/Language/DaitchMokotoffSoundex.cs b/src/Lucene.Net.Analysis.Phonetic/Language/DaitchMokotoffSoundex.cs index 9c61e45..872b46c 100644 --- a/src/Lucene.Net.Analysis.Phonetic/Language/DaitchMokotoffSoundex.cs +++ b/src/Lucene.Net.Analysis.Phonetic/Language/DaitchMokotoffSoundex.cs @@ -2,6 +2,7 @@ using J2N; using J2N.Text; using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.Collections.Generic; using System.IO; @@ -178,15 +179,9 @@ namespace Lucene.Net.Analysis.Phonetic.Language } // LUCENENET specific - need read access to pattern - public string Pattern - { - get { return pattern; } - } + public string Pattern => pattern; - public int PatternLength - { - get { return pattern.Length; } - } + public int PatternLength => pattern.Length; public string[] GetReplacements(string context, bool atStart) { @@ -222,18 +217,18 @@ namespace Lucene.Net.Analysis.Phonetic.Language } } - private static readonly string COMMENT = "//"; - private static readonly string DOUBLE_QUOTE = "\""; + private const string COMMENT = "//"; + private const string DOUBLE_QUOTE = "\""; - private static readonly string MULTILINE_COMMENT_END = "*/"; + private const string MULTILINE_COMMENT_END = "*/"; - private static readonly string MULTILINE_COMMENT_START = "/*"; + private const string MULTILINE_COMMENT_START = "/*"; /// <summary>The resource file containing the replacement and folding rules</summary> - private static readonly string RESOURCE_FILE = "dmrules.txt"; + private const string RESOURCE_FILE = "dmrules.txt"; /// <summary>The code length of a DM soundex value.</summary> - private static readonly int MAX_LENGTH = 6; + private const int MAX_LENGTH = 6; /// <summary>Transformation rules indexed by the first character of their pattern.</summary> private static readonly IDictionary<char, IList<Rule>> RULES = new Dictionary<char, IList<Rule>>(); diff --git a/src/Lucene.Net.Benchmark/ByTask/Feeds/ContentItemsSource.cs b/src/Lucene.Net.Benchmark/ByTask/Feeds/ContentItemsSource.cs index 77550e2..ef9db09 100644 --- a/src/Lucene.Net.Benchmark/ByTask/Feeds/ContentItemsSource.cs +++ b/src/Lucene.Net.Benchmark/ByTask/Feeds/ContentItemsSource.cs @@ -1,6 +1,6 @@ using J2N.Text; using Lucene.Net.Benchmarks.ByTask.Utils; -using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.Collections.Generic; using System.IO; diff --git a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs index 5b71204..a403f8c 100644 --- a/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs +++ b/src/Lucene.Net.QueryParser/Flexible/Standard/Processors/RemoveEmptyNonLeafQueryNodeProcessor.cs @@ -1,6 +1,6 @@ using Lucene.Net.QueryParsers.Flexible.Core.Nodes; using Lucene.Net.QueryParsers.Flexible.Core.Processors; -using Lucene.Net.Support; +using Lucene.Net.Util; using System.Collections.Generic; namespace Lucene.Net.QueryParsers.Flexible.Standard.Processors diff --git a/src/Lucene.Net.Tests.Queries/CommonTermsQueryTest.cs b/src/Lucene.Net.Tests.Queries/CommonTermsQueryTest.cs index dc46477..d705ff5 100644 --- a/src/Lucene.Net.Tests.Queries/CommonTermsQueryTest.cs +++ b/src/Lucene.Net.Tests.Queries/CommonTermsQueryTest.cs @@ -503,7 +503,7 @@ namespace Lucene.Net.Tests.Queries } private readonly CommonTermsQueryTest parent; - protected override bool LessThan(TermAndFreq a, TermAndFreq b) + protected internal override bool LessThan(TermAndFreq a, TermAndFreq b) { return a.freq > b.freq; } @@ -518,7 +518,7 @@ namespace Lucene.Net.Tests.Queries } private readonly CommonTermsQueryTest parent; - protected override bool LessThan(TermAndFreq a, TermAndFreq b) + protected internal override bool LessThan(TermAndFreq a, TermAndFreq b) { return a.freq < b.freq; } diff --git a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs index e18d217..1e7f83f 100644 --- a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs +++ b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility.cs @@ -202,7 +202,7 @@ namespace Lucene.Net.Index base.BeforeClass(); Assert.IsFalse(OldFormatImpersonationIsActive, "test infra is broken!"); - IList<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); + List<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); names.AddRange(OldNames); names.AddRange(OldSingleSegmentNames); OldIndexDirs = new Dictionary<string, Directory>(); @@ -927,7 +927,7 @@ namespace Lucene.Net.Index [Test] public virtual void TestUpgradeOldIndex() { - IList<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); + List<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); names.AddRange(OldNames); names.AddRange(OldSingleSegmentNames); foreach (string name in names) diff --git a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs index 35812e1..013fdee 100644 --- a/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs +++ b/src/Lucene.Net.Tests/Index/TestBackwardsCompatibility3x.cs @@ -134,7 +134,7 @@ namespace Lucene.Net.Index base.BeforeClass(); assertFalse("test infra is broken!", OldFormatImpersonationIsActive); - IList<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); + List<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); names.AddRange(OldNames); names.AddRange(OldSingleSegmentNames); OldIndexDirs = new Dictionary<string, Directory>(); @@ -888,7 +888,7 @@ namespace Lucene.Net.Index [Test] public virtual void TestUpgradeOldIndex() { - IList<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); + List<string> names = new List<string>(OldNames.Length + OldSingleSegmentNames.Length); names.AddRange(OldNames); names.AddRange(OldSingleSegmentNames); foreach (string name in names) diff --git a/src/Lucene.Net.Tests/Search/TestMinShouldMatch2.cs b/src/Lucene.Net.Tests/Search/TestMinShouldMatch2.cs index 09f6c4c..222073c 100644 --- a/src/Lucene.Net.Tests/Search/TestMinShouldMatch2.cs +++ b/src/Lucene.Net.Tests/Search/TestMinShouldMatch2.cs @@ -2,6 +2,7 @@ using System.Linq; using Lucene.Net.Documents; using Lucene.Net.Index; using Lucene.Net.Support; +using Lucene.Net.Util; using NUnit.Framework; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/Lucene.Net.Tests/Search/TestSort.cs b/src/Lucene.Net.Tests/Search/TestSort.cs index bb2b732..bc7cc65 100644 --- a/src/Lucene.Net.Tests/Search/TestSort.cs +++ b/src/Lucene.Net.Tests/Search/TestSort.cs @@ -1,8 +1,7 @@ using J2N.Collections.Generic.Extensions; using Lucene.Net.Attributes; using Lucene.Net.Documents; -using Lucene.Net.Randomized.Generators; -using Lucene.Net.Support; +using Lucene.Net.Util; using NUnit.Framework; using System; using System.Collections.Generic; diff --git a/src/Lucene.Net/Properties/AssemblyInfo.cs b/src/Lucene.Net/Properties/AssemblyInfo.cs index 82f12d2..28f4861 100644 --- a/src/Lucene.Net/Properties/AssemblyInfo.cs +++ b/src/Lucene.Net/Properties/AssemblyInfo.cs @@ -77,6 +77,7 @@ using System.Runtime.CompilerServices; [assembly: InternalsVisibleTo("Lucene.Net.Tests.Highlighter, PublicKey=" + AssemblyKeys.PublicKey)] [assembly: InternalsVisibleTo("Lucene.Net.Tests.ICU, PublicKey=" + AssemblyKeys.PublicKey)] // For Analysis.Util.TestSegmentingTokenizerBase [assembly: InternalsVisibleTo("Lucene.Net.Tests.Misc, PublicKey=" + AssemblyKeys.PublicKey)] +[assembly: InternalsVisibleTo("Lucene.Net.Tests.Queries, PublicKey=" + AssemblyKeys.PublicKey)] [assembly: InternalsVisibleTo("Lucene.Net.Tests.QueryParser, PublicKey=" + AssemblyKeys.PublicKey)] [assembly: InternalsVisibleTo("Lucene.Net.Tests.Cli, PublicKey=" + AssemblyKeys.PublicKey)] // For lucene-cli [assembly: InternalsVisibleTo("Lucene.Net.Tests.Replicator, PublicKey=" + AssemblyKeys.PublicKey)] diff --git a/src/Lucene.Net/Search/DisjunctionMaxQuery.cs b/src/Lucene.Net/Search/DisjunctionMaxQuery.cs index 70eaaa3..04184a5 100644 --- a/src/Lucene.Net/Search/DisjunctionMaxQuery.cs +++ b/src/Lucene.Net/Search/DisjunctionMaxQuery.cs @@ -1,4 +1,4 @@ -using Lucene.Net.Support; +using Lucene.Net.Util; using System; using System.Collections; using System.Collections.Generic; diff --git a/src/Lucene.Net/Search/Spans/NearSpansOrdered.cs b/src/Lucene.Net/Search/Spans/NearSpansOrdered.cs index 2478444..04f4cf7 100644 --- a/src/Lucene.Net/Search/Spans/NearSpansOrdered.cs +++ b/src/Lucene.Net/Search/Spans/NearSpansOrdered.cs @@ -384,9 +384,7 @@ namespace Lucene.Net.Search.Spans Spans prevSpans = subSpans[i]; if (collectPayloads && prevSpans.IsPayloadAvailable) { - var payload = prevSpans.GetPayload(); - possiblePayload = new List<byte[]>(payload.Count); - possiblePayload.AddRange(payload); + possiblePayload = new List<byte[]>(prevSpans.GetPayload()); // LUCENENET specific - using copy constructor instead of AddRange() } int prevStart = prevSpans.Start; @@ -418,9 +416,7 @@ namespace Lucene.Net.Search.Spans prevEnd = ppEnd; if (collectPayloads && prevSpans.IsPayloadAvailable) { - var payload = prevSpans.GetPayload(); - possiblePayload = new List<byte[]>(payload.Count); - possiblePayload.AddRange(payload); + possiblePayload = new List<byte[]>(prevSpans.GetPayload()); // LUCENENET specific - using copy constructor instead of AddRange() } } } diff --git a/src/Lucene.Net/Support/ListExtensions.cs b/src/Lucene.Net/Support/ListExtensions.cs index 9f1258e..158ef7d 100644 --- a/src/Lucene.Net/Support/ListExtensions.cs +++ b/src/Lucene.Net/Support/ListExtensions.cs @@ -4,39 +4,24 @@ using System.Collections.Generic; namespace Lucene.Net.Support { /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - public static class ListExtensions + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + internal static class ListExtensions { - public static void AddRange<T>(this IList<T> list, IEnumerable<T> values) - { - var lt = list as List<T>; - - if (lt != null) - lt.AddRange(values); - else - { - foreach (var item in values) - { - list.Add(item); - } - } - } - /// <summary> /// Performs a binary search for the specified element in the specified /// sorted list. The list needs to be already sorted in natural sorting @@ -44,24 +29,19 @@ namespace Lucene.Net.Support /// undefined which element is found if there are multiple occurrences of the /// same element. /// </summary> - /// <typeparam name="T">The element type.</typeparam> + /// <typeparam name="T">The element type. Must implement <see cref="IComparable{T}"/>"/>.</typeparam> /// <param name="list">The sorted list to search.</param> /// <param name="item">The element to find.</param> /// <returns>The non-negative index of the element, or a negative index which /// is the <c>-index - 1</c> where the element would be inserted.</returns> - /// <exception cref="InvalidCastException"> - /// If an element in the List or the search element does not - /// implement <see cref="IComparable{T}"/>, or cannot be compared to each other.</exception> + /// <exception cref="ArgumentNullException"><paramref name="list"/> is <c>null</c>.</exception> public static int BinarySearch<T>(this IList<T> list, T item) where T : IComparable<T> { if (list == null) - { throw new ArgumentNullException(nameof(list)); - } + if (list.Count == 0) - { return -1; - } int low = 0, mid = list.Count, high = mid - 1, result = -1; while (low <= high) @@ -84,22 +64,18 @@ namespace Lucene.Net.Support /// has an undefined result. It's also undefined which element is found if /// there are multiple occurrences of the same element. /// </summary> - /// <typeparam name="T">The element type.</typeparam> + /// <typeparam name="T">The element type. Must implement <see cref="IComparable{T}"/>"/>.</typeparam> /// <param name="list">The sorted <see cref="IList{T}"/> to search.</param> /// <param name="item">The element to find.</param> /// <param name="comparer">The comparer. If the comparer is <c>null</c> then the /// search uses the objects' natural ordering.</param> /// <returns>the non-negative index of the element, or a negative index which /// is the <c>-index - 1</c> where the element would be inserted.</returns> - /// <exception cref="InvalidCastException"> - /// when an element in the list and the searched element cannot - /// be compared to each other using the comparer.</exception> + /// <exception cref="ArgumentNullException"><paramref name="list"/> is <c>null</c>.</exception> public static int BinarySearch<T>(this IList<T> list, T item, IComparer<T> comparer) where T : IComparable<T> { if (list == null) - { throw new ArgumentNullException(nameof(list)); - } if (comparer == null) return BinarySearch(list, item); @@ -130,128 +106,6 @@ namespace Lucene.Net.Support return new SubList<T>(list, fromIndex, toIndex); } - - /// <summary> - /// If the underlying type is <see cref="List{T}"/>, - /// calls <see cref="List{T}.Sort()"/>. If not, - /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T})"/> - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - public static void Sort<T>(this IList<T> list) - { - if (list is List<T>) - { - ((List<T>)list).Sort(); - } - else - { - Util.CollectionUtil.TimSort(list); - } - } - - /// <summary> - /// If the underlying type is <see cref="List{T}"/>, - /// calls <see cref="List{T}.Sort(IComparer{T})"/>. If not, - /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T}, IComparer{T})"/> - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - /// <param name="comparer">the comparer to use for the sort</param> - public static void Sort<T>(this IList<T> list, IComparer<T> comparer) - { - if (list is List<T>) - { - ((List<T>)list).Sort(comparer); - } - else - { - Util.CollectionUtil.TimSort(list, comparer); - } - } - - /// <summary> - /// If the underlying type is <see cref="List{T}"/>, - /// calls <see cref="List{T}.Sort(IComparer{T})"/>. If not, - /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T}, IComparer{T})"/> - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - /// <param name="comparison">the comparison function to use for the sort</param> - public static void Sort<T>(this IList<T> list, Comparison<T> comparison) - { - IComparer<T> comparer = new FunctorComparer<T>(comparison); - Sort(list, comparer); - } - - /// <summary> - /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. - /// This method uses the Tim sort - /// algorithm, but falls back to binary sort for small lists. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - public static void TimSort<T>(this IList<T> list) - { - Util.CollectionUtil.TimSort(list); - } - - /// <summary> - /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. - /// This method uses the Tim sort - /// algorithm, but falls back to binary sort for small lists. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - /// <param name="comparer">The <see cref="IComparer{T}"/> to use for the sort.</param> - public static void TimSort<T>(this IList<T> list, IComparer<T> comparer) - { - Util.CollectionUtil.TimSort(list, comparer); - } - - /// <summary> - /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. - /// This method uses the intro sort - /// algorithm, but falls back to insertion sort for small lists. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - public static void IntroSort<T>(this IList<T> list) - { - Util.CollectionUtil.IntroSort(list); - } - - /// <summary> - /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. - /// This method uses the intro sort - /// algorithm, but falls back to insertion sort for small lists. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="list">this <see cref="IList{T}"/></param> - /// <param name="comparer">The <see cref="IComparer{T}"/> to use for the sort.</param> - public static void IntroSort<T>(this IList<T> list, IComparer<T> comparer) - { - Util.CollectionUtil.IntroSort(list, comparer); - } - - #region Nested Type: FunctorComparer<T> - - private sealed class FunctorComparer<T> : IComparer<T> - { - private Comparison<T> comparison; - - public FunctorComparer(Comparison<T> comparison) - { - this.comparison = comparison; - } - - public int Compare(T x, T y) - { - return this.comparison(x, y); - } - } - - #endregion Nested Type: FunctorComparer<T> } #region SubList<T> @@ -271,16 +125,16 @@ namespace Lucene.Net.Support public SubList(IList<T> list, int fromIndex, int toIndex) { if (fromIndex < 0) - throw new ArgumentOutOfRangeException("fromIndex"); + throw new ArgumentOutOfRangeException(nameof(fromIndex)); if (toIndex > list.Count) - throw new ArgumentOutOfRangeException("toIndex"); + throw new ArgumentOutOfRangeException(nameof(toIndex)); if (toIndex < fromIndex) - throw new ArgumentOutOfRangeException("toIndex"); + throw new ArgumentOutOfRangeException(nameof(toIndex)); if (list == null) - throw new ArgumentNullException("list"); + throw new ArgumentNullException(nameof(list)); this.list = list; this.fromIndex = fromIndex; diff --git a/src/Lucene.Net/Support/Util/ListExtensions.cs b/src/Lucene.Net/Support/Util/ListExtensions.cs new file mode 100644 index 0000000..d15693b --- /dev/null +++ b/src/Lucene.Net/Support/Util/ListExtensions.cs @@ -0,0 +1,160 @@ +using System; +using System.Collections.Generic; + +namespace Lucene.Net.Util +{ + /// <summary> + /// Extensions to <see cref="IList{T}"/>. + /// </summary> + public static class ListExtensions + { + /// <summary> + /// Adds the elements of the specified collection to the end of the <see cref="IList{T}"/>. + /// </summary> + /// <typeparam name="T">The element type.</typeparam> + /// <param name="list">The list to add to.</param> + /// <param name="collection">The collection whose elements should be added to the end of the <see cref="IList{T}"/>. + /// The collection itself cannot be <c>null</c>, but it can contain elements that are <c>null</c>, if type + /// <typeparamref name="T"/> is a reference type.</param> + /// <exception cref="ArgumentNullException"><paramref name="list"/> or <paramref name="collection"/> is <c>null</c>.</exception> + public static void AddRange<T>(this IList<T> list, IEnumerable<T> collection) + { + if (list == null) + throw new ArgumentNullException(nameof(list)); + if (collection == null) + throw new ArgumentNullException(nameof(collection)); + + if (list is List<T> thisList) + thisList.AddRange(collection); + else + { + foreach (var item in collection) + { + list.Add(item); + } + } + } + + /// <summary> + /// If the underlying type is <see cref="List{T}"/>, + /// calls <see cref="List{T}.Sort()"/>. If not, + /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T})"/> + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + public static void Sort<T>(this IList<T> list) + { + if (list is List<T>) + { + ((List<T>)list).Sort(); + } + else + { + CollectionUtil.TimSort(list); + } + } + + /// <summary> + /// If the underlying type is <see cref="List{T}"/>, + /// calls <see cref="List{T}.Sort(IComparer{T})"/>. If not, + /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T}, IComparer{T})"/> + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + /// <param name="comparer">the comparer to use for the sort</param> + public static void Sort<T>(this IList<T> list, IComparer<T> comparer) + { + if (list is List<T>) + { + ((List<T>)list).Sort(comparer); + } + else + { + CollectionUtil.TimSort(list, comparer); + } + } + + /// <summary> + /// If the underlying type is <see cref="List{T}"/>, + /// calls <see cref="List{T}.Sort(IComparer{T})"/>. If not, + /// uses <see cref="Util.CollectionUtil.TimSort{T}(IList{T}, IComparer{T})"/> + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + /// <param name="comparison">the comparison function to use for the sort</param> + public static void Sort<T>(this IList<T> list, Comparison<T> comparison) + { + IComparer<T> comparer = new FunctorComparer<T>(comparison); + Sort(list, comparer); + } + + /// <summary> + /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. + /// This method uses the Tim sort + /// algorithm, but falls back to binary sort for small lists. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + public static void TimSort<T>(this IList<T> list) + { + CollectionUtil.TimSort(list); + } + + /// <summary> + /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. + /// This method uses the Tim sort + /// algorithm, but falls back to binary sort for small lists. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + /// <param name="comparer">The <see cref="IComparer{T}"/> to use for the sort.</param> + public static void TimSort<T>(this IList<T> list, IComparer<T> comparer) + { + CollectionUtil.TimSort(list, comparer); + } + + /// <summary> + /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. + /// This method uses the intro sort + /// algorithm, but falls back to insertion sort for small lists. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + public static void IntroSort<T>(this IList<T> list) + { + CollectionUtil.IntroSort(list); + } + + /// <summary> + /// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>. + /// This method uses the intro sort + /// algorithm, but falls back to insertion sort for small lists. + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="list">this <see cref="IList{T}"/></param> + /// <param name="comparer">The <see cref="IComparer{T}"/> to use for the sort.</param> + public static void IntroSort<T>(this IList<T> list, IComparer<T> comparer) + { + CollectionUtil.IntroSort(list, comparer); + } + + #region Nested Type: FunctorComparer<T> + + private sealed class FunctorComparer<T> : IComparer<T> + { + private Comparison<T> comparison; + + public FunctorComparer(Comparison<T> comparison) + { + this.comparison = comparison; + } + + public int Compare(T x, T y) + { + return this.comparison(x, y); + } + } + + #endregion Nested Type: FunctorComparer<T> + } +}
