Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Search Manager #1832

Draft
wants to merge 4 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Flow.Launcher.Plugin/SharedCommands/FilesFolders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public static string ReturnPreviousDirectoryIfIncompleteString(string path)
/// <param name="subPath">Sub path</param>
/// <param name="allowEqual">If <see langword="true"/>, when <paramref name="parentPath"/> and <paramref name="subPath"/> are equal, returns <see langword="true"/></param>
/// <returns></returns>
public static bool PathContains(string parentPath, string subPath, bool allowEqual = false)
public static bool PathContains(this string parentPath, string subPath, bool allowEqual = false)
{
var rel = Path.GetRelativePath(parentPath.EnsureTrailingSlash(), subPath);
return (rel != "." || allowEqual)
Expand Down
120 changes: 75 additions & 45 deletions Flow.Launcher.Test/Plugins/ExplorerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ public void GivenWindowsIndexSearch_WhenProvidedFolderPath_ThenQueryWhereRestric
var result = QueryConstructor.TopLevelDirectoryConstraint(folderPath);

// Then
Assert.IsTrue(result == expectedString,
Assert.AreEqual(result,
expectedString,
$"Expected QueryWhereRestrictions string: {expectedString}{Environment.NewLine} " +
$"Actual: {result}{Environment.NewLine}");
}
Expand All @@ -74,18 +75,23 @@ public void GivenWindowsIndexSearch_WhenSearchTypeIsTopLevelDirectorySearch_Then
var queryString = queryConstructor.Directory(folderPath);

// Then
Assert.IsTrue(queryString.Replace(" ", " ") == expectedString.Replace(" ", " "),
Assert.AreEqual(queryString.Replace(" ", " "),
expectedString.Replace(" ", " "),
$"Expected string: {expectedString}{Environment.NewLine} " +
$"Actual string was: {queryString}{Environment.NewLine}");
}

[SupportedOSPlatform("windows7.0")]
[TestCase("C:\\SomeFolder", "flow.launcher.sln", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType" +
" FROM SystemIndex WHERE directory='file:C:\\SomeFolder'" +
" AND (System.FileName LIKE 'flow.launcher.sln%' OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"'))" +
" ORDER BY System.FileName")]
[TestCase("C:\\SomeFolder",
"flow.launcher.sln",
"SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType" +
" FROM SystemIndex WHERE directory='file:C:\\SomeFolder'" +
" AND (System.FileName LIKE 'flow.launcher.sln%' OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"'))" +
" ORDER BY System.FileName")]
public void GivenWindowsIndexSearchTopLevelDirectory_WhenSearchingForSpecificItem_ThenQueryShouldUseExpectedString(
string folderPath, string userSearchString, string expectedString)
string folderPath,
string userSearchString,
string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
Expand All @@ -109,12 +115,14 @@ public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryWhereR
}

[SupportedOSPlatform("windows7.0")]
[TestCase("flow.launcher.sln", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" " +
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:' ORDER BY System.FileName")]
[TestCase("flow.launcher.sln",
"SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" " +
"FROM \"SystemIndex\" WHERE (System.FileName LIKE 'flow.launcher.sln%' " +
"OR CONTAINS(System.FileName,'\"flow.launcher.sln*\"',1033)) AND scope='file:' ORDER BY System.FileName")]
[TestCase("", "SELECT TOP 100 \"System.FileName\", \"System.ItemUrl\", \"System.ItemType\" FROM \"SystemIndex\" WHERE WorkId IS NOT NULL AND scope='file:' ORDER BY System.FileName")]
public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShouldUseExpectedString(
string userSearchString, string expectedString)
string userSearchString,
string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
Expand All @@ -135,7 +143,8 @@ public void GivenWindowsIndexSearch_WhenSearchAllFoldersAndFiles_ThenQueryShould
[SupportedOSPlatform("windows7.0")]
[TestCase(@"some words", @"FREETEXT('some words')")]
public void GivenWindowsIndexSearch_WhenQueryWhereRestrictionsIsForFileContentSearch_ThenShouldReturnFreeTextString(
string querySearchString, string expectedString)
string querySearchString,
string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
Expand All @@ -144,16 +153,19 @@ public void GivenWindowsIndexSearch_WhenQueryWhereRestrictionsIsForFileContentSe
var resultString = QueryConstructor.RestrictionsForFileContentSearch(querySearchString);

// Then
Assert.IsTrue(resultString == expectedString,
Assert.AreEqual(resultString,
expectedString,
$"Expected QueryWhereRestrictions string: {expectedString}{Environment.NewLine} " +
$"Actual string was: {resultString}{Environment.NewLine}");
}

[SupportedOSPlatform("windows7.0")]
[TestCase("some words", "SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
"FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:' ORDER BY System.FileName")]
[TestCase("some words",
"SELECT TOP 100 System.FileName, System.ItemUrl, System.ItemType " +
"FROM SystemIndex WHERE FREETEXT('some words') AND scope='file:' ORDER BY System.FileName")]
public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseExpectedString(
string userSearchString, string expectedString)
string userSearchString,
string expectedString)
{
// Given
var queryConstructor = new QueryConstructor(new Settings());
Expand All @@ -162,7 +174,8 @@ public void GivenWindowsIndexSearch_WhenSearchForFileContent_ThenQueryShouldUseE
var resultString = queryConstructor.FileContent(userSearchString);

// Then
Assert.IsTrue(resultString == expectedString,
Assert.AreEqual(resultString,
expectedString,
$"Expected query string: {expectedString}{Environment.NewLine} " +
$"Actual string was: {resultString}{Environment.NewLine}");
}
Expand Down Expand Up @@ -202,7 +215,8 @@ public void WhenGivenQuerySearchString_ThenShouldIndicateIfIsLocationPathString(
var result = FilesFolders.IsLocationPathString(querySearchString);

//Then
Assert.IsTrue(result == expectedResult,
Assert.AreEqual(result,
expectedResult,
$"Expected query search string check result is: {expectedResult} {Environment.NewLine} " +
$"Actual check result is {result} {Environment.NewLine}");

Expand All @@ -212,10 +226,13 @@ public void WhenGivenQuerySearchString_ThenShouldIndicateIfIsLocationPathString(
[TestCase(@"C:\SomeFolder\SomeApp\SomeFile", true, @"C:\SomeFolder\SomeApp\")]
[TestCase(@"C:\NonExistentFolder\SomeApp", false, "")]
public void GivenAPartialPath_WhenPreviousLevelDirectoryExists_ThenShouldReturnThePreviousDirectoryPathString(
string path, bool previousDirectoryExists, string expectedString)
string path,
bool previousDirectoryExists,
string expectedString)
{
// When
Func<string, bool> previousLocationExists = null;

if (previousDirectoryExists)
{
previousLocationExists = PreviousLocationExistsReturnsTrue;
Expand All @@ -229,20 +246,23 @@ public void GivenAPartialPath_WhenPreviousLevelDirectoryExists_ThenShouldReturnT
var previousDirectoryPath = FilesFolders.GetPreviousExistingDirectory(previousLocationExists, path);

//Then
Assert.IsTrue(previousDirectoryPath == expectedString,
Assert.AreEqual(previousDirectoryPath,
expectedString,
$"Expected path string: {expectedString} {Environment.NewLine} " +
$"Actual path string is {previousDirectoryPath} {Environment.NewLine}");
}

[TestCase(@"C:\NonExistentFolder\SomeApp", @"C:\NonExistentFolder\")]
[TestCase(@"C:\NonExistentFolder\SomeApp\", @"C:\NonExistentFolder\SomeApp\")]
public void WhenGivenAPath_ThenShouldReturnThePreviousDirectoryPathIfIncompleteOrOriginalString(
string path, string expectedString)
string path,
string expectedString)
{
var returnedPath = FilesFolders.ReturnPreviousDirectoryIfIncompleteString(path);

//Then
Assert.IsTrue(returnedPath == expectedString,
Assert.AreEqual(returnedPath,
expectedString,
$"Expected path string: {expectedString} {Environment.NewLine} " +
$"Actual path string is {returnedPath} {Environment.NewLine}");
}
Expand Down Expand Up @@ -280,23 +300,24 @@ public void GivenDirectoryInfoSearch_WhenSearchPatternHotKeyIsSearchAll_ThenSear
[TestCase("c:\\somefolder\\someotherfolder", ResultType.Folder, "p", true, false, "p c:\\somefolder\\someotherfolder\\")]
[TestCase("c:\\somefolder\\someotherfolder", ResultType.Folder, "", true, true, "c:\\somefolder\\someotherfolder\\")]
public void GivenFolderResult_WhenGetPath_ThenPathShouldBeExpectedString(
string path,
ResultType type,
string path,
ResultType type,
string actionKeyword,
bool pathSearchKeywordEnabled,
bool pathSearchKeywordEnabled,
bool searchActionKeywordEnabled,
string expectedResult)
{
// Given
var settings = new Settings()
var settings = new Settings
{
PathSearchKeywordEnabled = pathSearchKeywordEnabled,
PathSearchActionKeyword = "p",
SearchActionKeywordEnabled = searchActionKeywordEnabled,
SearchActionKeyword = Query.GlobalPluginWildcardSign
};

ResultManager.Init(new PluginInitContext(), settings);

// When
var result = ResultManager.GetPathWithActionKeyword(path, type, actionKeyword);

Expand All @@ -317,13 +338,14 @@ public void GivenFileResult_WhenGetPath_ThenPathShouldBeExpectedString(
string expectedResult)
{
// Given
var settings = new Settings()
var settings = new Settings
{
PathSearchKeywordEnabled = pathSearchKeywordEnabled,
PathSearchActionKeyword = "p",
SearchActionKeywordEnabled = searchActionKeywordEnabled,
SearchActionKeyword = "e"
};

ResultManager.Init(new PluginInitContext(), settings);

// When
Expand All @@ -346,8 +368,12 @@ public void GivenQueryWithFolderTypeResult_WhenGetAutoComplete_ThenResultShouldB
string expectedResult)
{
// Given
var query = new Query() { ActionKeyword = actionKeyword };
var settings = new Settings()
var query = new Query
{
ActionKeyword = actionKeyword
};

var settings = new Settings
{
PathSearchKeywordEnabled = pathSearchKeywordEnabled,
PathSearchActionKeyword = "p",
Expand All @@ -356,6 +382,7 @@ public void GivenQueryWithFolderTypeResult_WhenGetAutoComplete_ThenResultShouldB
QuickAccessActionKeyword = "q",
IndexSearchActionKeyword = "i"
};

ResultManager.Init(new PluginInitContext(), settings);

// When
Expand All @@ -378,8 +405,12 @@ public void GivenQueryWithFileTypeResult_WhenGetAutoComplete_ThenResultShouldBeE
string expectedResult)
{
// Given
var query = new Query() { ActionKeyword = actionKeyword };
var settings = new Settings()
var query = new Query
{
ActionKeyword = actionKeyword
};

var settings = new Settings
{
QuickAccessActionKeyword = "q",
IndexSearchActionKeyword = "i",
Expand All @@ -388,6 +419,7 @@ public void GivenQueryWithFileTypeResult_WhenGetAutoComplete_ThenResultShouldBeE
SearchActionKeywordEnabled = searchActionKeywordEnabled,
SearchActionKeyword = Query.GlobalPluginWildcardSign
};

ResultManager.Init(new PluginInitContext(), settings);

// When
Expand All @@ -404,15 +436,14 @@ public void GivenTwoPaths_WhenCompared_ThenShouldBeExpectedSameOrDifferent(strin
{
// Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
var result1 = new SearchResult
{
Title = Path.GetFileName(path1),
SubTitle = path1
FullPath = path1
};
var result2 = new Result

var result2 = new SearchResult
{
Title = Path.GetFileName(path2),
SubTitle = path2
FullPath = path2
};

// When, Then
Expand All @@ -425,22 +456,21 @@ public void GivenTwoPaths_WhenComparedHasCode_ThenShouldBeSame(string path1, str
{
// Given
var comparator = PathEqualityComparator.Instance;
var result1 = new Result
var result1 = new SearchResult
{
Title = Path.GetFileName(path1),
SubTitle = path1
FullPath = path1
};
var result2 = new Result

var result2 = new SearchResult
{
Title = Path.GetFileName(path2),
SubTitle = path2
FullPath = path2
};

var hash1 = comparator.GetHashCode(result1);
var hash2 = comparator.GetHashCode(result2);

// When, Then
Assert.IsTrue(hash1 == hash2);
Assert.AreEqual(hash1, hash2);
}

[TestCase(@"%appdata%", true)]
Expand Down
15 changes: 11 additions & 4 deletions Plugins/Flow.Launcher.Plugin.Explorer/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
Expand Down Expand Up @@ -42,11 +43,13 @@ public Task InitAsync(PluginInitContext context)
contextMenu = new ContextMenu(Context, Settings, viewModel);
searchManager = new SearchManager(Settings, Context);
ResultManager.Init(Context, Settings);

SortOptionTranslationHelper.API = context.API;

EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory, "EverythingSDK",
EverythingApiDllImport.Load(Path.Combine(Context.CurrentPluginMetadata.PluginDirectory,
"EverythingSDK",
Environment.Is64BitProcess ? "x64" : "x86"));

return Task.CompletedTask;
}

Expand All @@ -59,7 +62,10 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
{
try
{
return await searchManager.SearchAsync(query, token);
// null means cancelled
return (await searchManager.SearchAsync(query, token))?
.Select(r => ResultManager.CreateResult(query, r))
.ToList();
}
catch (Exception e) when (e is SearchException or EngineNotAvailableException)
{
Expand All @@ -75,11 +81,12 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
IcoPath = e is EngineNotAvailableException { ErrorIcon: { } iconPath }
? iconPath
: Constants.GeneralSearchErrorImagePath,
AsyncAction = e is EngineNotAvailableException {Action: { } action}
AsyncAction = e is EngineNotAvailableException { Action: { } action }
? action
: _ =>
{
Clipboard.SetDataObject(e.ToString());

return new ValueTask<bool>(true);
}
}
Expand Down
Loading
Loading