From 40cadf0191369be1c5ef3a4f6cb57be1c19da995 Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sun, 15 Apr 2018 02:00:13 -0700 Subject: [PATCH 1/6] Feature Request: Search by abbreviated qualified name when not performing a full name search --- ILSpy/SearchStrategies.cs | 194 +++++++++++++++++++++----------------- 1 file changed, 110 insertions(+), 84 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index 43884bc18..46c485d67 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -17,6 +17,7 @@ namespace ICSharpCode.ILSpy protected string[] searchTerm; protected Regex regex; protected bool fullNameSearch; + protected bool allowNonContiguousMatch; protected AbstractSearchStrategy(params string[] terms) { @@ -114,10 +115,35 @@ namespace ICSharpCode.ILSpy } break; default: - if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0) - return false; + if (!fullNameSearch && allowNonContiguousMatch) { + if (!IsNonContiguousMatch(text.ToLower(), term.ToLower())) + return false; + } else { + if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0) + return false; + } + break; + } + } + return true; + } + + private bool IsNonContiguousMatch(string text, string searchTerm) + { + if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchTerm)) { + return false; + } + var index = 0; + foreach (char c in searchTerm) { + while (index != text.Length) { + if (text[index] == c) { + index++; break; + } + index++; } + if (index == text.Length) + return false; } return true; } @@ -227,23 +253,23 @@ namespace ICSharpCode.ILSpy if (value != null && value.LiteralValue != null) { TypeCode valueType = Type.GetTypeCode(value.LiteralValue.GetType()); switch (valueType) { - case TypeCode.Byte: - case TypeCode.SByte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - searchTermLiteralType = TypeCode.Int64; - searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, value.LiteralValue, false); - break; - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.String: - searchTermLiteralType = valueType; - searchTermLiteralValue = value.LiteralValue; - break; + case TypeCode.Byte: + case TypeCode.SByte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + searchTermLiteralType = TypeCode.Int64; + searchTermLiteralValue = CSharpPrimitiveCast.Cast(TypeCode.Int64, value.LiteralValue, false); + break; + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.String: + searchTermLiteralType = valueType; + searchTermLiteralValue = value.LiteralValue; + break; } } } @@ -301,74 +327,74 @@ namespace ICSharpCode.ILSpy long val = (long)searchTermLiteralValue; foreach (var inst in body.Instructions) { switch (inst.OpCode.Code) { - case Code.Ldc_I8: - if (val == (long)inst.Operand) - return true; - break; - case Code.Ldc_I4: - if (val == (int)inst.Operand) - return true; - break; - case Code.Ldc_I4_S: - if (val == (sbyte)inst.Operand) - return true; - break; - case Code.Ldc_I4_M1: - if (val == -1) - return true; - break; - case Code.Ldc_I4_0: - if (val == 0) - return true; - break; - case Code.Ldc_I4_1: - if (val == 1) - return true; - break; - case Code.Ldc_I4_2: - if (val == 2) - return true; - break; - case Code.Ldc_I4_3: - if (val == 3) - return true; - break; - case Code.Ldc_I4_4: - if (val == 4) - return true; - break; - case Code.Ldc_I4_5: - if (val == 5) - return true; - break; - case Code.Ldc_I4_6: - if (val == 6) - return true; - break; - case Code.Ldc_I4_7: - if (val == 7) - return true; - break; - case Code.Ldc_I4_8: - if (val == 8) - return true; - break; + case Code.Ldc_I8: + if (val == (long)inst.Operand) + return true; + break; + case Code.Ldc_I4: + if (val == (int)inst.Operand) + return true; + break; + case Code.Ldc_I4_S: + if (val == (sbyte)inst.Operand) + return true; + break; + case Code.Ldc_I4_M1: + if (val == -1) + return true; + break; + case Code.Ldc_I4_0: + if (val == 0) + return true; + break; + case Code.Ldc_I4_1: + if (val == 1) + return true; + break; + case Code.Ldc_I4_2: + if (val == 2) + return true; + break; + case Code.Ldc_I4_3: + if (val == 3) + return true; + break; + case Code.Ldc_I4_4: + if (val == 4) + return true; + break; + case Code.Ldc_I4_5: + if (val == 5) + return true; + break; + case Code.Ldc_I4_6: + if (val == 6) + return true; + break; + case Code.Ldc_I4_7: + if (val == 7) + return true; + break; + case Code.Ldc_I4_8: + if (val == 8) + return true; + break; } } } else if (searchTermLiteralType != TypeCode.Empty) { Code expectedCode; switch (searchTermLiteralType) { - case TypeCode.Single: - expectedCode = Code.Ldc_R4; - break; - case TypeCode.Double: - expectedCode = Code.Ldc_R8; - break; - case TypeCode.String: - expectedCode = Code.Ldstr; - break; - default: - throw new InvalidOperationException(); + case TypeCode.Single: + expectedCode = Code.Ldc_R4; + break; + case TypeCode.Double: + expectedCode = Code.Ldc_R8; + break; + case TypeCode.String: + expectedCode = Code.Ldstr; + break; + default: + throw new InvalidOperationException(); } foreach (var inst in body.Instructions) { if (inst.OpCode.Code == expectedCode && searchTermLiteralValue.Equals(inst.Operand)) @@ -465,10 +491,10 @@ namespace ICSharpCode.ILSpy public override void Search(TypeDefinition type, Language language, Action addResult) { - if (MatchName(type, language)) + if (MatchName(type, language)) { string name = language.TypeToString(type, includeNamespace: false); - addResult(new SearchResult + addResult(new SearchResult { Member = type, Image = TypeTreeNode.GetIcon(type), From d61a1096326cd310bfd7b3091caf5ea524fa09ef Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sun, 15 Apr 2018 02:08:45 -0700 Subject: [PATCH 2/6] Remove extra spaces --- ILSpy/SearchStrategies.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index 46c485d67..f74ee64e6 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -491,10 +491,10 @@ namespace ICSharpCode.ILSpy public override void Search(TypeDefinition type, Language language, Action addResult) { - if (MatchName(type, language)) + if (MatchName(type, language)) { string name = language.TypeToString(type, includeNamespace: false); - addResult(new SearchResult + addResult(new SearchResult { Member = type, Image = TypeTreeNode.GetIcon(type), From 0f6953667379216bfc042878e2886fc4d339f35a Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sat, 12 May 2018 20:15:46 -0700 Subject: [PATCH 3/6] Enable search by abbreviated qualified name by prefixing search string with "s:" --- ILSpy/SearchStrategies.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index f74ee64e6..e4c7ffa19 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -14,10 +14,11 @@ namespace ICSharpCode.ILSpy { abstract class AbstractSearchStrategy { + private const string NoncontiguousSearchPrefix = "s:"; + protected string[] searchTerm; protected Regex regex; protected bool fullNameSearch; - protected bool allowNonContiguousMatch; protected AbstractSearchStrategy(params string[] terms) { @@ -115,8 +116,8 @@ namespace ICSharpCode.ILSpy } break; default: - if (!fullNameSearch && allowNonContiguousMatch) { - if (!IsNonContiguousMatch(text.ToLower(), term.ToLower())) + if (term.Length > 2 && term.StartsWith(NoncontiguousSearchPrefix, StringComparison.OrdinalIgnoreCase)) { + if (!IsNoncontiguousMatch(text.ToLower(), term.Substring(2).ToLower())) return false; } else { if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0) @@ -128,7 +129,7 @@ namespace ICSharpCode.ILSpy return true; } - private bool IsNonContiguousMatch(string text, string searchTerm) + private bool IsNoncontiguousMatch(string text, string searchTerm) { if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchTerm)) { return false; From 87c33cc34590f584473192a3dbf3f43ed35d3773 Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sat, 12 May 2018 20:31:59 -0700 Subject: [PATCH 4/6] Refactor and add comment for clarity --- ILSpy/SearchStrategies.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index e4c7ffa19..f9e3cfe01 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -129,21 +129,26 @@ namespace ICSharpCode.ILSpy return true; } - private bool IsNoncontiguousMatch(string text, string searchTerm) + bool IsNoncontiguousMatch(string text, string searchTerm) { if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(searchTerm)) { return false; } + var textLength = text.Length; + if (searchTerm.Length > textLength) { + return false; + } var index = 0; foreach (char c in searchTerm) { - while (index != text.Length) { + while (index != textLength) { if (text[index] == c) { index++; break; } index++; - } - if (index == text.Length) + } + // Check if we reached end of text without matching the full search string + if (index == textLength) return false; } return true; From bd1d81d22eb170f27cfcc5640e89255e8584e842 Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sun, 17 Jun 2018 12:04:05 -0700 Subject: [PATCH 5/6] Change '~' to be the 'In-string Search' Activator Prefix and Fix Search Not Matching Last Character Bug --- ILSpy/SearchStrategies.cs | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index f9e3cfe01..1a560a37d 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -115,14 +115,13 @@ namespace ICSharpCode.ILSpy return false; } break; + case '~': + if (term.Length > 1 && !IsNoncontiguousMatch(text.ToLower(), term.Substring(1).ToLower())) + return false; + break; default: - if (term.Length > 2 && term.StartsWith(NoncontiguousSearchPrefix, StringComparison.OrdinalIgnoreCase)) { - if (!IsNoncontiguousMatch(text.ToLower(), term.Substring(2).ToLower())) - return false; - } else { - if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0) - return false; - } + if (text.IndexOf(term, StringComparison.OrdinalIgnoreCase) < 0) + return false; break; } } @@ -138,20 +137,22 @@ namespace ICSharpCode.ILSpy if (searchTerm.Length > textLength) { return false; } - var index = 0; - foreach (char c in searchTerm) { - while (index != textLength) { - if (text[index] == c) { - index++; + var i = 0; + for (int searchIndex = 0; searchIndex < searchTerm.Length;) { + while (i != textLength) { + if (text[i] == searchTerm[searchIndex]) { + // Check if all characters in searchTerm have been matched + if (searchTerm.Length == ++searchIndex) + return true; + i++; break; } - index++; - } - // Check if we reached end of text without matching the full search string - if (index == textLength) + i++; + } + if (i == textLength) return false; } - return true; + return false; } string GetLanguageSpecificName(Language language, IMemberDefinition member, bool fullName = false) From 3c7a0070b5e93fde856ae2f8020a3797f05af50a Mon Sep 17 00:00:00 2001 From: Rafaat Mir Date: Sun, 17 Jun 2018 12:06:03 -0700 Subject: [PATCH 6/6] Remove unused variable --- ILSpy/SearchStrategies.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index 1a560a37d..307eff93d 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -14,8 +14,6 @@ namespace ICSharpCode.ILSpy { abstract class AbstractSearchStrategy { - private const string NoncontiguousSearchPrefix = "s:"; - protected string[] searchTerm; protected Regex regex; protected bool fullNameSearch;