From ca1e5d111aabbfbc043c4a1d9ad41adb221188dc Mon Sep 17 00:00:00 2001 From: Avneet Kaur <72103212+avneet-kr@users.noreply.github.com> Date: Mon, 26 Oct 2020 15:14:33 -0700 Subject: [PATCH] [fxcop] Fixes for Wox.Plugin (1of3) (#7457) * Added CultureInfo (CA1307: Specify StringComparison for clarity / CA1304: Specify CultureInfo) * Check arguments and throw ArgumentNullException (CA1062: Validate arguments of public methods) * Changed url parameter from string to System.Uri and added null checks (CA1054: URI parameters should not be strings) * Rethrow exception without specifying the exception explicitly (CA2200: Rethrow to preserve stack details) * Changed from Collection property to methods for PluginMetadata::ActionKeywords (CA2227: Collection properties should be read only) * Changed from Collection property to methods for Result::GetTitleHighlightData (CA2227: Collection properties should be read only) * Made Collection property read-only and added parameter in constructor for Result::SubTitleHighlightData (CA2227: Collection properties should be read only) * Made Collection property read only and added parameter in constructor for ResultUpdatedEventArgs::Results (CA2227: Collection properties should be read only) * CA1507: Use nameof in place of string * Removed initialization for ThemeManager::_disposed (CA1805: Do not initialize unnecessarily) * Changed Query::Terms array property to ReadOnlyCollection and added private set (CA1819: Properties should not return arrays) * CA1060: Move P/Invokes to NativeMethods class * CA1806: Do not ignore method results * CA2101: Specify marshaling for P/Invoke string arguments * Removed unnecessary empty interface IFeatures (CA1040: Avoid empty interfaces) - Removed IFeatures interface and references - Renamed IFeatures.cs to IContextMenu.cs according to guidelines * Added comments for CultureInfo (CA1307: Specify StringComparison for clarity / CA1304: Specify CultureInfo) * Added localization for Wox.Plugin and localized strings in FilesFolders.cs --- .../Sources/Result/FileItemResult.cs | 3 +- .../Sources/Result/FolderItemResult.cs | 3 +- .../UserFolderResult.cs | 3 +- .../ProgramArgumentParserTests.cs | 3 +- .../DoubleDashProgramArgumentParser.cs | 4 +- .../InferedProgramArgumentParser.cs | 4 +- .../Programs/UWPApplication.cs | 2 +- .../Programs/Win32Program.cs | 2 +- .../launcher/Wox.Core/Plugin/PluginConfig.cs | 4 +- .../launcher/Wox.Core/Plugin/PluginManager.cs | 11 +- .../launcher/Wox.Core/Plugin/QueryBuilder.cs | 5 +- .../UserSettings/PluginSettings.cs | 4 +- .../launcher/Wox.Plugin/AllowedLanguage.cs | 13 +- .../{IFeatures.cs => IContextMenu.cs} | 10 +- .../Wox.Plugin/IDelayedExecutionPlugin.cs | 2 +- .../launcher/Wox.Plugin/LocProject.json | 14 ++ .../launcher/Wox.Plugin/PluginMetadata.cs | 17 ++- src/modules/launcher/Wox.Plugin/PluginPair.cs | 8 +- .../Properties/Resources.Designer.cs | 90 ++++++++++++ .../Wox.Plugin/Properties/Resources.resx | 132 ++++++++++++++++++ src/modules/launcher/Wox.Plugin/Query.cs | 7 +- src/modules/launcher/Wox.Plugin/Result.cs | 56 +++++--- .../Wox.Plugin/ResultUpdatedEventArgs.cs | 7 +- .../Wox.Plugin/SharedCommands/FilesFolders.cs | 19 ++- .../SharedCommands/NativeMethods.cs | 23 +++ .../Wox.Plugin/SharedCommands/SearchWeb.cs | 24 +++- .../Wox.Plugin/SharedCommands/ShellCommand.cs | 21 ++- .../launcher/Wox.Plugin/ThemeManager.cs | 2 +- .../launcher/Wox.Plugin/ToolTipData.cs | 2 +- .../launcher/Wox.Plugin/Wox.Plugin.csproj | 13 ++ .../launcher/Wox.Test/QueryBuilderTest.cs | 17 +-- 31 files changed, 430 insertions(+), 95 deletions(-) rename src/modules/launcher/Wox.Plugin/{IFeatures.cs => IContextMenu.cs} (79%) create mode 100644 src/modules/launcher/Wox.Plugin/LocProject.json create mode 100644 src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs create mode 100644 src/modules/launcher/Wox.Plugin/Properties/Resources.resx create mode 100644 src/modules/launcher/Wox.Plugin/SharedCommands/NativeMethods.cs diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FileItemResult.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FileItemResult.cs index 67ce72680875..785ce63ccadc 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FileItemResult.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FileItemResult.cs @@ -21,12 +21,11 @@ public class FileItemResult : IItemResult public Wox.Plugin.Result Create(IPublicAPI contextApi) { - var result = new Wox.Plugin.Result + var result = new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData) { Title = Title, SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_file_result_subtitle, FilePath), IcoPath = FilePath, - TitleHighlightData = StringMatcher.FuzzySearch(Search, Path.GetFileName(FilePath)).MatchData, Action = c => ShellAction.Execute(FilePath, contextApi), ContextData = new SearchResult { Type = ResultType.File, FullPath = FilePath }, }; diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FolderItemResult.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FolderItemResult.cs index dd295f941307..45ee48ee5018 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FolderItemResult.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/Result/FolderItemResult.cs @@ -33,13 +33,12 @@ public FolderItemResult(DisplayFileInfo fileSystemInfo) public Wox.Plugin.Result Create(IPublicAPI contextApi) { - return new Wox.Plugin.Result + return new Wox.Plugin.Result(StringMatcher.FuzzySearch(Search, Title).MatchData) { Title = Title, IcoPath = Path, SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle), QueryTextDisplay = Path, - TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData, ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path }, Action = c => ShellAction.Execute(Path, contextApi), }; diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/UserFolderResult.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/UserFolderResult.cs index f8bb9ce1eb4d..5c63f5a53e0f 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/UserFolderResult.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Folder/UserFolderResult.cs @@ -24,13 +24,12 @@ public class UserFolderResult : IItemResult public Result Create(IPublicAPI contextApi) { - return new Result + return new Result(StringMatcher.FuzzySearch(Search, Title).MatchData) { Title = Title, IcoPath = Path, SubTitle = string.Format(CultureInfo.CurrentCulture, Properties.Resources.wox_plugin_folder_select_folder_result_subtitle, Subtitle), QueryTextDisplay = Path, - TitleHighlightData = StringMatcher.FuzzySearch(Search, Title).MatchData, ContextData = new SearchResult { Type = ResultType.Folder, FullPath = Path }, Action = c => _shellAction.Execute(Path, contextApi), }; diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/ProgramArgumentParser/ProgramArgumentParserTests.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/ProgramArgumentParser/ProgramArgumentParserTests.cs index c233217f48f9..06179a493b0f 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/ProgramArgumentParser/ProgramArgumentParserTests.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/ProgramArgumentParser/ProgramArgumentParserTests.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.Plugin.Program.ProgramArgumentParser; +using Mono.Collections.Generic; using NUnit.Framework; using Wox.Plugin; @@ -34,7 +35,7 @@ public void ProgramArgumentParserTestsCanParseQuery(string inputQuery, string ex // basic version of the Quey parser which can be found at Wox.Core.Plugin.QueryBuilder but did not want to create a project reference var splittedSearchString = inputQuery?.Split(Query.TermSeparator, System.StringSplitOptions.RemoveEmptyEntries); var cleanQuery = string.Join(Query.TermSeparator, splittedSearchString); - var query = new Query(cleanQuery, cleanQuery, splittedSearchString, string.Empty); + var query = new Query(cleanQuery, cleanQuery, new ReadOnlyCollection(splittedSearchString), string.Empty); // Act string program = null, programArguments = null; diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/DoubleDashProgramArgumentParser.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/DoubleDashProgramArgumentParser.cs index 7b3728623c30..d9c3cab952ef 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/DoubleDashProgramArgumentParser.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/DoubleDashProgramArgumentParser.cs @@ -19,9 +19,9 @@ public bool TryParse(Query query, out string program, out string programArgument if (!string.IsNullOrEmpty(query?.Search)) { // First Argument is always (part of) the program, 2nd term is possibly a Program Argument - if (query.Terms.Length > 1) + if (query.Terms.Count > 1) { - for (var i = 1; i < query.Terms.Length; i++) + for (var i = 1; i < query.Terms.Count; i++) { if (!string.Equals(query.Terms[i], DoubleDash, StringComparison.Ordinal)) { diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/InferedProgramArgumentParser.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/InferedProgramArgumentParser.cs index 884a4771c455..b3aa16eb6fb8 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/InferedProgramArgumentParser.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/InferedProgramArgumentParser.cs @@ -19,9 +19,9 @@ public bool TryParse(Query query, out string program, out string programArgument if (!string.IsNullOrEmpty(query?.Search)) { // First Argument is always (part of) the program, 2nd term is possibly a Program Argument - if (query.Terms.Length > 1) + if (query.Terms.Count > 1) { - for (var i = 1; i < query.Terms.Length; i++) + for (var i = 1; i < query.Terms.Count; i++) { if (!ArgumentPrefixRegex.IsMatch(query.Terms[i])) { diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/UWPApplication.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/UWPApplication.cs index a148854ea4af..9ac90bfc641e 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/UWPApplication.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/UWPApplication.cs @@ -109,7 +109,7 @@ public Result Result(string query, string queryArguments, IPublicAPI api) // To set the title to always be the displayname of the packaged application result.Title = DisplayName; - result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData; + result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData); var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title); var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, Package.Location); diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs index ca984da76229..6c5c49fb55ab 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs @@ -233,7 +233,7 @@ public Result Result(string query, string queryArguments, IPublicAPI api) // To set the title for the result to always be the name of the application result.Title = Name; - result.TitleHighlightData = StringMatcher.FuzzySearch(query, Name).MatchData; + result.SetTitleHighlightData(StringMatcher.FuzzySearch(query, Name).MatchData); var toolTipTitle = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_name, result.Title); var toolTipText = string.Format(CultureInfo.CurrentCulture, "{0}: {1}", Properties.Resources.powertoys_run_plugin_program_file_path, FullPath); diff --git a/src/modules/launcher/Wox.Core/Plugin/PluginConfig.cs b/src/modules/launcher/Wox.Core/Plugin/PluginConfig.cs index 4c677ed9ec30..ba2b284bb73c 100644 --- a/src/modules/launcher/Wox.Core/Plugin/PluginConfig.cs +++ b/src/modules/launcher/Wox.Core/Plugin/PluginConfig.cs @@ -78,10 +78,10 @@ private static PluginMetadata GetPluginMetadata(string pluginDirectory) metadata.PluginDirectory = pluginDirectory; // for plugins which doesn't has ActionKeywords key - metadata.ActionKeywords = metadata.ActionKeywords ?? new List { metadata.ActionKeyword }; + metadata.SetActionKeywords(metadata.GetActionKeywords() ?? new List { metadata.ActionKeyword }); // for plugin still use old ActionKeyword - metadata.ActionKeyword = metadata.ActionKeywords?[0]; + metadata.ActionKeyword = metadata.GetActionKeywords()?[0]; } catch (Exception e) { diff --git a/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs b/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs index 687f5460f514..6da5acb8e132 100644 --- a/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs +++ b/src/modules/launcher/Wox.Core/Plugin/PluginManager.cs @@ -125,7 +125,7 @@ public static void InitializePlugins(IPublicAPI api) } // Plugins may have multiple ActionKeywords, eg. WebSearch - plugin.Metadata.ActionKeywords.Where(x => x != Query.GlobalPluginWildcardSign) + plugin.Metadata.GetActionKeywords().Where(x => x != Query.GlobalPluginWildcardSign) .ToList() .ForEach(x => NonGlobalPlugins[x] = plugin); } @@ -244,7 +244,7 @@ public static void UpdatePluginMetadata(List results, PluginMetadata met private static bool IsGlobalPlugin(PluginMetadata metadata) { - return metadata.ActionKeywords.Contains(Query.GlobalPluginWildcardSign); + return metadata.GetActionKeywords().Contains(Query.GlobalPluginWildcardSign); } /// @@ -258,7 +258,6 @@ public static PluginPair GetPluginForId(string id) } public static IEnumerable GetPluginsForInterface() - where T : IFeatures { return AllPlugins.Where(p => p.Plugin is T); } @@ -320,7 +319,7 @@ public static void AddActionKeyword(string id, string newActionKeyword) NonGlobalPlugins[newActionKeyword] = plugin; } - plugin.Metadata.ActionKeywords.Add(newActionKeyword); + plugin.Metadata.GetActionKeywords().Add(newActionKeyword); } /// @@ -332,7 +331,7 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) var plugin = GetPluginForId(id); if (oldActionkeyword == Query.GlobalPluginWildcardSign && // Plugins may have multiple ActionKeywords that are global, eg. WebSearch - plugin.Metadata.ActionKeywords + plugin.Metadata.GetActionKeywords() .Where(x => x == Query.GlobalPluginWildcardSign) .ToList() .Count == 1) @@ -345,7 +344,7 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword) NonGlobalPlugins.Remove(oldActionkeyword); } - plugin.Metadata.ActionKeywords.Remove(oldActionkeyword); + plugin.Metadata.GetActionKeywords().Remove(oldActionkeyword); } public static void ReplaceActionKeyword(string id, string oldActionKeyword, string newActionKeyword) diff --git a/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs b/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs index 6db5def1c5a3..90e86f67b91b 100644 --- a/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs +++ b/src/modules/launcher/Wox.Core/Plugin/QueryBuilder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Mono.Collections.Generic; using Wox.Plugin; namespace Wox.Core.Plugin @@ -63,7 +64,7 @@ public static Dictionary Build(ref string text, Dictionary(terms), pluginActionKeyword); pluginQueryPair.TryAdd(pluginPair, query); } @@ -80,7 +81,7 @@ public static Dictionary Build(ref string text, Dictionary(terms), string.Empty); pluginQueryPair.Add(globalPlugin, query); } } diff --git a/src/modules/launcher/Wox.Infrastructure/UserSettings/PluginSettings.cs b/src/modules/launcher/Wox.Infrastructure/UserSettings/PluginSettings.cs index d975aa6f79bb..196af9ff493b 100644 --- a/src/modules/launcher/Wox.Infrastructure/UserSettings/PluginSettings.cs +++ b/src/modules/launcher/Wox.Infrastructure/UserSettings/PluginSettings.cs @@ -20,7 +20,7 @@ public void UpdatePluginSettings(List metadatas) var settings = Plugins[metadata.ID]; if (settings.ActionKeywords?.Count > 0) { - metadata.ActionKeywords = settings.ActionKeywords; + metadata.SetActionKeywords(settings.ActionKeywords); metadata.ActionKeyword = settings.ActionKeywords[0]; } @@ -32,7 +32,7 @@ public void UpdatePluginSettings(List metadatas) { ID = metadata.ID, Name = metadata.Name, - ActionKeywords = metadata.ActionKeywords, + ActionKeywords = metadata.GetActionKeywords(), Disabled = metadata.Disabled, }; } diff --git a/src/modules/launcher/Wox.Plugin/AllowedLanguage.cs b/src/modules/launcher/Wox.Plugin/AllowedLanguage.cs index fcd9d4430327..8922b89064d5 100644 --- a/src/modules/launcher/Wox.Plugin/AllowedLanguage.cs +++ b/src/modules/launcher/Wox.Plugin/AllowedLanguage.cs @@ -2,6 +2,9 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Globalization; + namespace Wox.Plugin { public static class AllowedLanguage @@ -18,8 +21,14 @@ public static string Executable public static bool IsAllowed(string language) { - return language.ToUpper() == CSharp.ToUpper() - || language.ToUpper() == Executable.ToUpper(); + if (language == null) + { + throw new ArgumentNullException(nameof(language)); + } + + // Using InvariantCulture since this is a command line arg + return language.ToUpper(CultureInfo.InvariantCulture) == CSharp.ToUpper(CultureInfo.InvariantCulture) + || language.ToUpper(CultureInfo.InvariantCulture) == Executable.ToUpper(CultureInfo.InvariantCulture); } } } diff --git a/src/modules/launcher/Wox.Plugin/IFeatures.cs b/src/modules/launcher/Wox.Plugin/IContextMenu.cs similarity index 79% rename from src/modules/launcher/Wox.Plugin/IFeatures.cs rename to src/modules/launcher/Wox.Plugin/IContextMenu.cs index d4b5b66cdcaa..78ccead1d25b 100644 --- a/src/modules/launcher/Wox.Plugin/IFeatures.cs +++ b/src/modules/launcher/Wox.Plugin/IContextMenu.cs @@ -6,11 +6,7 @@ namespace Wox.Plugin { - public interface IFeatures - { - } - - public interface IContextMenu : IFeatures + public interface IContextMenu { List LoadContextMenus(Result selectedResult); } @@ -18,14 +14,14 @@ public interface IContextMenu : IFeatures /// /// Represent plugins that support internationalization /// - public interface IPluginI18n : IFeatures + public interface IPluginI18n { string GetTranslatedPluginTitle(); string GetTranslatedPluginDescription(); } - public interface IResultUpdated : IFeatures + public interface IResultUpdated { event ResultUpdatedEventHandler ResultsUpdated; } diff --git a/src/modules/launcher/Wox.Plugin/IDelayedExecutionPlugin.cs b/src/modules/launcher/Wox.Plugin/IDelayedExecutionPlugin.cs index 207525886315..5254643f24c2 100644 --- a/src/modules/launcher/Wox.Plugin/IDelayedExecutionPlugin.cs +++ b/src/modules/launcher/Wox.Plugin/IDelayedExecutionPlugin.cs @@ -6,7 +6,7 @@ namespace Wox.Plugin { - public interface IDelayedExecutionPlugin : IFeatures + public interface IDelayedExecutionPlugin { List Query(Query query, bool delayedExecution); } diff --git a/src/modules/launcher/Wox.Plugin/LocProject.json b/src/modules/launcher/Wox.Plugin/LocProject.json new file mode 100644 index 000000000000..1c5684f6f316 --- /dev/null +++ b/src/modules/launcher/Wox.Plugin/LocProject.json @@ -0,0 +1,14 @@ +{ + "Projects": [ + { + "LanguageSet": "Azure_Languages", + "LocItems": [ + { + "SourceFile": "src\\modules\\launcher\\Wox.Plugin\\Properties\\Resources.resx", + "CopyOption": "LangIDOnName", + "OutputPath": "src\\modules\\launcher\\Wox.Plugin\\Properties" + } + ] + } + ] +} \ No newline at end of file diff --git a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs index 5f805c1426eb..657dfe26ba09 100644 --- a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs +++ b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs @@ -14,6 +14,13 @@ public class PluginMetadata : BaseModel { private string _pluginDirectory; + private List _actionKeywords; + + public PluginMetadata(List actionKeywords = null) + { + _actionKeywords = actionKeywords; + } + public string ID { get; set; } public string Name { get; set; } @@ -51,7 +58,15 @@ internal set public string ActionKeyword { get; set; } - public List ActionKeywords { get; set; } + public List GetActionKeywords() + { + return _actionKeywords; + } + + public void SetActionKeywords(List value) + { + _actionKeywords = value; + } public string IcoPath { get; set; } diff --git a/src/modules/launcher/Wox.Plugin/PluginPair.cs b/src/modules/launcher/Wox.Plugin/PluginPair.cs index c853ecc1f6b9..6bb94815b005 100644 --- a/src/modules/launcher/Wox.Plugin/PluginPair.cs +++ b/src/modules/launcher/Wox.Plugin/PluginPair.cs @@ -2,6 +2,8 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; + namespace Wox.Plugin { public class PluginPair @@ -19,7 +21,8 @@ public override bool Equals(object obj) { if (obj is PluginPair r) { - return string.Equals(r.Metadata.ID, Metadata.ID); + // Using Ordinal since this is used internally + return string.Equals(r.Metadata.ID, Metadata.ID, StringComparison.Ordinal); } else { @@ -29,7 +32,8 @@ public override bool Equals(object obj) public override int GetHashCode() { - var hashcode = Metadata.ID?.GetHashCode() ?? 0; + // Using Ordinal since this is used internally + var hashcode = Metadata.ID?.GetHashCode(StringComparison.Ordinal) ?? 0; return hashcode; } } diff --git a/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs b/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs new file mode 100644 index 000000000000..ca18b9aee7fa --- /dev/null +++ b/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Wox.Plugin.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Wox.Plugin.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Copying path {0} has failed, it will now be deleted for consistency. + /// + public static string filesfolder_copy_failed { + get { + return ResourceManager.GetString("filesfolder_copy_failed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Not able to delete folder {0}, please go to the location and manually delete it. + /// + public static string filesfolder_removefolder_failed { + get { + return ResourceManager.GetString("filesfolder_removefolder_failed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to verify folders and files between {0} and {1}. + /// + public static string filesfolder_verifybothfolderfilesequal_failed { + get { + return ResourceManager.GetString("filesfolder_verifybothfolderfilesequal_failed", resourceCulture); + } + } + } +} diff --git a/src/modules/launcher/Wox.Plugin/Properties/Resources.resx b/src/modules/launcher/Wox.Plugin/Properties/Resources.resx new file mode 100644 index 000000000000..c5d21a23d553 --- /dev/null +++ b/src/modules/launcher/Wox.Plugin/Properties/Resources.resx @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Copying path {0} has failed, it will now be deleted for consistency + parameter: targetPath + + + Not able to delete folder {0}, please go to the location and manually delete it + parameter: path + + + Unable to verify folders and files between {0} and {1} + paramaters: fromPath, toPath + + \ No newline at end of file diff --git a/src/modules/launcher/Wox.Plugin/Query.cs b/src/modules/launcher/Wox.Plugin/Query.cs index af6adb8e1368..dc7f4e860632 100644 --- a/src/modules/launcher/Wox.Plugin/Query.cs +++ b/src/modules/launcher/Wox.Plugin/Query.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.Linq; +using Mono.Collections.Generic; namespace Wox.Plugin { @@ -18,7 +19,7 @@ internal Query() /// Initializes a new instance of the class. /// to allow unit tests for plug ins /// - public Query(string rawQuery, string search, string[] terms, string actionKeyword = "") + public Query(string rawQuery, string search, ReadOnlyCollection terms, string actionKeyword = "") { Search = search; RawQuery = rawQuery; @@ -41,9 +42,9 @@ public Query(string rawQuery, string search, string[] terms, string actionKeywor public string Search { get; internal set; } /// - /// Gets or sets the raw query splited into a string array. + /// Gets the raw query splited into a string array. /// - public string[] Terms { get; set; } + public ReadOnlyCollection Terms { get; private set; } /// /// Query can be splited into multiple terms by whitespace diff --git a/src/modules/launcher/Wox.Plugin/Result.cs b/src/modules/launcher/Wox.Plugin/Result.cs index 6e4ecd06b2a2..2bcae0d53dba 100644 --- a/src/modules/launcher/Wox.Plugin/Result.cs +++ b/src/modules/launcher/Wox.Plugin/Result.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Windows; using System.Windows.Media; @@ -16,6 +17,7 @@ public class Result private ToolTipData _toolTipData; private string _pluginDirectory; private string _icoPath; + private IList _titleHighlightData; public string Title { @@ -26,7 +28,13 @@ public string Title set { - _title = value.Replace("\n", " "); + if (value == null) + { + throw new ArgumentNullException(nameof(value)); + } + + // Using Ordinal since this is used internally + _title = value.Replace("\n", " ", StringComparison.Ordinal); } } @@ -90,15 +98,32 @@ public string IcoPath public int Score { get; set; } + public Result(IList titleHighlightData = null, IList subTitleHighlightData = null) + { + _titleHighlightData = titleHighlightData; + SubTitleHighlightData = subTitleHighlightData; + } + + /// + /// Gets a list of indexes for the characters to be highlighted in Title + /// + public IList GetTitleHighlightData() + { + return _titleHighlightData; + } + /// - /// Gets or sets a list of indexes for the characters to be highlighted in Title + /// Sets a list of indexes for the characters to be highlighted in Title /// - public IList TitleHighlightData { get; set; } + public void SetTitleHighlightData(IList value) + { + _titleHighlightData = value; + } /// - /// Gets or sets a list of indexes for the characters to be highlighted in SubTitle + /// Gets a list of indexes for the characters to be highlighted in SubTitle /// - public IList SubTitleHighlightData { get; set; } + public IList SubTitleHighlightData { get; private set; } /// /// Gets or sets only results that originQuery match with current query will be displayed in the panel @@ -129,10 +154,11 @@ public override bool Equals(object obj) { var r = obj as Result; - var equality = string.Equals(r?.Title, Title) && - string.Equals(r?.SubTitle, SubTitle) && - string.Equals(r?.IcoPath, IcoPath) && - TitleHighlightData == r.TitleHighlightData && + // Using Ordinal since this is used internally + var equality = string.Equals(r?.Title, Title, StringComparison.Ordinal) && + string.Equals(r?.SubTitle, SubTitle, StringComparison.Ordinal) && + string.Equals(r?.IcoPath, IcoPath, StringComparison.Ordinal) && + GetTitleHighlightData() == r.GetTitleHighlightData() && SubTitleHighlightData == r.SubTitleHighlightData; return equality; @@ -140,18 +166,16 @@ public override bool Equals(object obj) public override int GetHashCode() { - var hashcode = (Title?.GetHashCode() ?? 0) ^ - (SubTitle?.GetHashCode() ?? 0); + // Using Ordinal since this is used internally + var hashcode = (Title?.GetHashCode(StringComparison.Ordinal) ?? 0) ^ + (SubTitle?.GetHashCode(StringComparison.Ordinal) ?? 0); return hashcode; } public override string ToString() { - return string.Format("{0} : {1}", Title, SubTitle); - } - - public Result() - { + // Using CurrentCulture since this is user facing + return string.Format(CultureInfo.CurrentCulture, "{0} : {1}", Title, SubTitle); } /// diff --git a/src/modules/launcher/Wox.Plugin/ResultUpdatedEventArgs.cs b/src/modules/launcher/Wox.Plugin/ResultUpdatedEventArgs.cs index 3afd2ffcbc46..ec663220327c 100644 --- a/src/modules/launcher/Wox.Plugin/ResultUpdatedEventArgs.cs +++ b/src/modules/launcher/Wox.Plugin/ResultUpdatedEventArgs.cs @@ -9,7 +9,12 @@ namespace Wox.Plugin { public class ResultUpdatedEventArgs : EventArgs { - public List Results { get; set; } + public List Results { get; private set; } + + public ResultUpdatedEventArgs(List results = null) + { + Results = results; + } public Query Query { get; set; } } diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs index 5e59093b8ca4..82158e8b1035 100644 --- a/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs +++ b/src/modules/launcher/Wox.Plugin/SharedCommands/FilesFolders.cs @@ -3,9 +3,11 @@ // See the LICENSE file in the project root for more information. using System; +using System.Globalization; using System.IO; using System.Reflection; using Wox.Plugin.Logger; +using Wox.Plugin.Properties; namespace Wox.Plugin.SharedCommands { @@ -56,9 +58,10 @@ public static void Copy(this string sourcePath, string targetPath) string error = $"Copying path {targetPath} has failed"; Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType); #if DEBUG - throw e; + throw; #else - System.Windows.MessageBox.Show(string.Format("Copying path {0} has failed, it will now be deleted for consistency", targetPath)); + // Using CurrentCulture since this is user facing + System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_copy_failed, targetPath)); RemoveFolder(targetPath); #endif } @@ -91,9 +94,10 @@ public static bool VerifyBothFolderFilesEqual(this string fromPath, string toPat string error = $"Unable to verify folders and files between {fromPath} and {toPath}"; Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType); #if DEBUG - throw e; + throw; #else - System.Windows.MessageBox.Show(string.Format(error)); + // Using CurrentCulture since this is user facing + System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_verifybothfolderfilesequal_failed, fromPath, toPath)); return false; #endif } @@ -113,12 +117,13 @@ public static void RemoveFolder(this string path) catch (Exception e) #pragma warning restore CS0168 // Variable is declared but never used { - string error = $"Not able to delete folder {path}, please go to the location and manually delete it"; + string error = $"Not able to delete folder {path}"; Log.Exception(error, e, MethodBase.GetCurrentMethod().DeclaringType); #if DEBUG - throw e; + throw; #else - System.Windows.MessageBox.Show(string.Format(error)); + // Using CurrentCulture since this is user facing + System.Windows.MessageBox.Show(string.Format(CultureInfo.CurrentCulture, Resources.filesfolder_removefolder_failed, path)); #endif } } diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/NativeMethods.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/NativeMethods.cs new file mode 100644 index 000000000000..d03f1cc25202 --- /dev/null +++ b/src/modules/launcher/Wox.Plugin/SharedCommands/NativeMethods.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Text; +using static Wox.Plugin.SharedCommands.ShellCommand; + +namespace Wox.Plugin.SharedCommands +{ + internal static class NativeMethods + { + [DllImport("user32.dll")] + public static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount); + + [DllImport("user32.dll")] + public static extern int GetWindowTextLength(IntPtr hwnd); + } +} diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs index 6ecd1c57b0f6..224c7a830d33 100644 --- a/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs +++ b/src/modules/launcher/Wox.Plugin/SharedCommands/SearchWeb.cs @@ -15,8 +15,13 @@ public static class SearchWeb /// Opens search in a new browser. If no browser path is passed in then Chrome is used. /// Leave browser path blank to use Chrome. /// - public static void NewBrowserWindow(this string url, string browserPath) + public static void NewBrowserWindow(this Uri url, string browserPath) { + if (url == null) + { + throw new ArgumentNullException(nameof(url)); + } + var browserExecutableName = browserPath? .Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None) .Last(); @@ -24,7 +29,7 @@ public static void NewBrowserWindow(this string url, string browserPath) var browser = string.IsNullOrEmpty(browserExecutableName) ? "chrome" : browserPath; // Internet Explorer will open url in new browser window, and does not take the --new-window parameter - var browserArguments = browserExecutableName == "iexplore.exe" ? url : "--new-window " + url; + var browserArguments = browserExecutableName == "iexplore.exe" ? url.AbsoluteUri : "--new-window " + url.AbsoluteUri; try { @@ -34,7 +39,7 @@ public static void NewBrowserWindow(this string url, string browserPath) { var psi = new ProcessStartInfo { - FileName = url, + FileName = url.AbsoluteUri, UseShellExecute = true, }; Process.Start(psi); @@ -44,24 +49,29 @@ public static void NewBrowserWindow(this string url, string browserPath) /// /// Opens search as a tab in the default browser chosen in Windows settings. /// - public static void NewTabInBrowser(this string url, string browserPath) + public static void NewTabInBrowser(this Uri url, string browserPath) { + if (url == null) + { + throw new ArgumentNullException(nameof(url)); + } + try { if (!string.IsNullOrEmpty(browserPath)) { - Process.Start(browserPath, url); + Process.Start(browserPath, url.AbsoluteUri); } else { - Process.Start(url); + Process.Start(url.AbsoluteUri); } } // This error may be thrown for Process.Start(browserPath, url) catch (System.ComponentModel.Win32Exception) { - Process.Start(url); + Process.Start(url.AbsoluteUri); } } } diff --git a/src/modules/launcher/Wox.Plugin/SharedCommands/ShellCommand.cs b/src/modules/launcher/Wox.Plugin/SharedCommands/ShellCommand.cs index 8d9574181225..97414b90368b 100644 --- a/src/modules/launcher/Wox.Plugin/SharedCommands/ShellCommand.cs +++ b/src/modules/launcher/Wox.Plugin/SharedCommands/ShellCommand.cs @@ -4,7 +4,6 @@ using System; using System.Diagnostics; -using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -14,19 +13,15 @@ public static class ShellCommand { public delegate bool EnumThreadDelegate(IntPtr hwnd, IntPtr lParam); - [DllImport("user32.dll")] - private static extern bool EnumThreadWindows(uint threadId, EnumThreadDelegate lpfn, IntPtr lParam); - - [DllImport("user32.dll")] - private static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int nMaxCount); - - [DllImport("user32.dll")] - private static extern int GetWindowTextLength(IntPtr hwnd); - private static bool containsSecurityWindow; public static Process RunAsDifferentUser(ProcessStartInfo processStartInfo) { + if (processStartInfo == null) + { + throw new ArgumentNullException(nameof(processStartInfo)); + } + processStartInfo.Verb = "RunAsUser"; var process = Process.Start(processStartInfo); @@ -55,7 +50,7 @@ private static void CheckSecurityWindow() ProcessThreadCollection ptc = Process.GetCurrentProcess().Threads; for (int i = 0; i < ptc.Count; i++) { - EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero); + NativeMethods.EnumThreadWindows((uint)ptc[i].Id, CheckSecurityThread, IntPtr.Zero); } } @@ -71,8 +66,8 @@ private static bool CheckSecurityThread(IntPtr hwnd, IntPtr lParam) private static string GetWindowTitle(IntPtr hwnd) { - StringBuilder sb = new StringBuilder(GetWindowTextLength(hwnd) + 1); - GetWindowText(hwnd, sb, sb.Capacity); + StringBuilder sb = new StringBuilder(NativeMethods.GetWindowTextLength(hwnd) + 1); + _ = NativeMethods.GetWindowText(hwnd, sb, sb.Capacity); return sb.ToString(); } diff --git a/src/modules/launcher/Wox.Plugin/ThemeManager.cs b/src/modules/launcher/Wox.Plugin/ThemeManager.cs index ee45ae06d9ee..55b3cdcc063a 100644 --- a/src/modules/launcher/Wox.Plugin/ThemeManager.cs +++ b/src/modules/launcher/Wox.Plugin/ThemeManager.cs @@ -22,7 +22,7 @@ public class ThemeManager : IDisposable private const string HighContrastWhiteTheme = "HighContrast.Accent5"; private Theme currentTheme; - private bool _disposed = false; + private bool _disposed; public event ThemeChangedHandler ThemeChanged; diff --git a/src/modules/launcher/Wox.Plugin/ToolTipData.cs b/src/modules/launcher/Wox.Plugin/ToolTipData.cs index 9224f5adbbfe..c55861368633 100644 --- a/src/modules/launcher/Wox.Plugin/ToolTipData.cs +++ b/src/modules/launcher/Wox.Plugin/ToolTipData.cs @@ -16,7 +16,7 @@ public ToolTipData(string title, string text) { if (string.IsNullOrEmpty(title)) { - throw new ArgumentException("title cannot be null or empty", "title"); + throw new ArgumentException("title cannot be null or empty", nameof(title)); } Title = title; diff --git a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj index 94c616503cfe..6a6be6bf91fc 100644 --- a/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj +++ b/src/modules/launcher/Wox.Plugin/Wox.Plugin.csproj @@ -96,4 +96,17 @@ all + + + True + True + Resources.resx + + + + + PublicResXFileCodeGenerator + Resources.Designer.cs + + \ No newline at end of file diff --git a/src/modules/launcher/Wox.Test/QueryBuilderTest.cs b/src/modules/launcher/Wox.Test/QueryBuilderTest.cs index f7cbae3ed71a..2b99aea2bd29 100644 --- a/src/modules/launcher/Wox.Test/QueryBuilderTest.cs +++ b/src/modules/launcher/Wox.Test/QueryBuilderTest.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; +using Mono.Collections.Generic; using NUnit.Framework; using Wox.Core.Plugin; using Wox.Plugin; @@ -26,7 +27,7 @@ public void QueryBuilderShouldRemoveExtraSpacesForNonGlobalPlugin() // Arrange var nonGlobalPlugins = new Dictionary { - { ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List { ">" } } } }, + { ">", new PluginPair { Metadata = new PluginMetadata(new List { ">" } ) } }, }; string searchQuery = "> file.txt file2 file3"; @@ -43,7 +44,7 @@ public void QueryBuilderShouldRemoveExtraSpacesForDisabledNonGlobalPlugin() // Arrange var nonGlobalPlugins = new Dictionary { - { ">", new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List { ">" }, Disabled = true } } }, + { ">", new PluginPair { Metadata = new PluginMetadata(new List { ">" }) { Disabled = true } } }, }; string searchQuery = "> file.txt file2 file3"; @@ -72,7 +73,7 @@ public void QueryBuilderShouldGenerateSameQueryIfEitherActionKeywordOrActionKeyw { // Arrange string searchQuery = "> query"; - var firstPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List { ">" } } }; + var firstPlugin = new PluginPair { Metadata = new PluginMetadata(new List { ">" } ) }; var secondPlugin = new PluginPair { Metadata = new PluginMetadata { ActionKeyword = ">" } }; var nonGlobalPluginWithActionKeywords = new Dictionary @@ -85,7 +86,7 @@ public void QueryBuilderShouldGenerateSameQueryIfEitherActionKeywordOrActionKeyw { ">", secondPlugin }, }; string[] terms = { ">", "query" }; - Query expectedQuery = new Query("> query", "query", terms, ">"); + Query expectedQuery = new Query("> query", "query", new ReadOnlyCollection(terms), ">"); // Act var queriesForPluginsWithActionKeywords = QueryBuilder.Build(ref searchQuery, nonGlobalPluginWithActionKeywords); @@ -103,7 +104,7 @@ public void QueryBuilderShouldGenerateSameQueryIfEitherActionKeywordOrActionKeyw public void QueryBuilderShouldGenerateCorrectQueriesForPluginsWithMultipleActionKeywords() { // Arrange - var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List { "a", "b" } } }; + var plugin = new PluginPair { Metadata = new PluginMetadata(new List { "a", "b" } ) }; var nonGlobalPlugins = new Dictionary { { "a", plugin }, @@ -129,7 +130,7 @@ public void QueryBuilderShouldGenerateCorrectQueriesForPluginsWithMultipleAction public void QueryBuildShouldGenerateSameSearchQueryWithOrWithoutSpaceAfterActionKeyword() { // Arrange - var plugin = new PluginPair { Metadata = new PluginMetadata { ActionKeywords = new List { "a" } } }; + var plugin = new PluginPair { Metadata = new PluginMetadata(new List { "a" } ) }; var nonGlobalPlugins = new Dictionary { { "a", plugin }, @@ -198,8 +199,8 @@ public void QueryBuilderShouldSetTermsCorrentlyWhenCalled() // Assert // Using Ordinal since this is used internally - Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Length == 2); - Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Length == 1); + Assert.IsTrue(firstQuery.Terms[0].Equals("cd", StringComparison.Ordinal) && firstQuery.Terms[1].Equals("efgh", StringComparison.Ordinal) && firstQuery.Terms.Count == 2); + Assert.IsTrue(secondQuery.Terms[0].Equals("efgh", StringComparison.Ordinal) && secondQuery.Terms.Count == 1); } } }