From c97ce0b5231698ab9f303a08d1922dfadfcbca6c Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Mon, 15 Jul 2024 21:21:05 +0200 Subject: [PATCH 1/2] replace ArrayList/CaseInsensitiveComparer with a generic implementation, remove allocs --- .../System/Windows/Documents/Speller.cs | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs index 56e3b5b7255..67fe643ea34 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs @@ -53,6 +53,7 @@ internal Speller(TextEditor textEditor) _defaultCulture = InputLanguageManager.Current != null ? InputLanguageManager.Current.CurrentInputLanguage : Thread.CurrentThread.CurrentCulture; + _defaultComparer = StringComparer.Create(_defaultCulture, true); } #endregion Constructors @@ -224,17 +225,15 @@ internal IList GetSuggestionsForError(SpellingError error) // implement this as a process-wide list. internal void IgnoreAll(string word) { - if (_ignoredWordsList == null) - { - _ignoredWordsList = new ArrayList(1); - } + if (_ignoredWordsList is null) + _ignoredWordsList = new List(1); - int index = _ignoredWordsList.BinarySearch(word, new CaseInsensitiveComparer(_defaultCulture)); + int index = _ignoredWordsList.BinarySearch(word, _defaultComparer); + // If we didn't find the word, we're gonna add it to ignore list if (index < 0) { // This is a new word to ignore. - // Add it the list so we don't flag it later. _ignoredWordsList.Insert(~index, word); @@ -1438,17 +1437,7 @@ private bool ExpandToWordBreakCallback(SpellerInteropBase.ISpellerSegment textSe } // Returns true if a user has tagged the specified word with "Ignore All". - private bool IsIgnoredWord(char[] word) - { - bool isIgnoredWord = false; - - if (_ignoredWordsList != null) - { - isIgnoredWord = _ignoredWordsList.BinarySearch(new string(word), new CaseInsensitiveComparer(_defaultCulture)) >= 0; - } - - return isIgnoredWord; - } + private bool IsIgnoredWord(char[] word) => _ignoredWordsList?.BinarySearch(new string(word), _defaultComparer) >= 0; // Returns true if we have an engine capable of proofing the specified // language. @@ -2052,11 +2041,12 @@ internal object Lexicon private bool _pendingCaretMovedCallback; // List of words tagged by the user as non-errors. - private ArrayList _ignoredWordsList; + private List _ignoredWordsList; // The CultureInfo associated with this speller. // Used for ignored words comparison, and plain text controls (TextBox). private readonly CultureInfo _defaultCulture; + private readonly IComparer _defaultComparer; // Set true if the nl6 library is unavailable. private bool _failedToInit; From 701b219f292876e332d45934bdbac61b6baa0aa4 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Mon, 15 Jul 2024 21:22:03 +0200 Subject: [PATCH 2/2] remove additional array copy, IsIgnoredWord now works with string --- .../System/Windows/Documents/Speller.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs index 67fe643ea34..3aceff72a9a 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/Speller.cs @@ -943,7 +943,6 @@ private bool ScanTextSegment(SpellerInteropBase.ISpellerSegment textSegment, obj { TextMapCallbackData data = (TextMapCallbackData)o; SpellerInteropBase.ITextRange sTextRange = textSegment.TextRange; - char[] word; // Check if this segment falls outside the content range. // The region before/after the content is only for context -- @@ -962,8 +961,7 @@ private bool ScanTextSegment(SpellerInteropBase.ISpellerSegment textSegment, obj if (sTextRange.Length > 1) // Ignore single letter errors. { // Check if the segment has been marked "ignore" by the user. - word = new char[sTextRange.Length]; - Array.Copy(data.TextMap.Text, sTextRange.Start, word, 0, sTextRange.Length); + string word = new(data.TextMap.Text, sTextRange.Start, sTextRange.Length); if (!IsIgnoredWord(word)) { @@ -1437,7 +1435,7 @@ private bool ExpandToWordBreakCallback(SpellerInteropBase.ISpellerSegment textSe } // Returns true if a user has tagged the specified word with "Ignore All". - private bool IsIgnoredWord(char[] word) => _ignoredWordsList?.BinarySearch(new string(word), _defaultComparer) >= 0; + private bool IsIgnoredWord(string word) => _ignoredWordsList?.BinarySearch(word, _defaultComparer) >= 0; // Returns true if we have an engine capable of proofing the specified // language.