Skip to content

Commit

Permalink
Introduce configuration for "Go to Symbol in Workspace" (#1284)
Browse files Browse the repository at this point in the history
* Added to IOmniSharpEnvironment

* Revert "Added to IOmniSharpEnvironment"

This reverts commit e4a962a.

* Plugged in Find Symbols Options

* Ignore FindSymbolsOptions.MaxItemsToReturn <=0

* resolved merge conflict

* Fix build break

* Per CR feedback moved new configuration parameters to FindSymbolsRequest

* Switch MinFilterLength and MaxItemsToReturn in FindSymbolsRequest to be int?

* Use named args for nulls and consts in test as per PR feedback
  • Loading branch information
dmgonch authored and akshita31 committed Sep 20, 2018
1 parent d9aa8d2 commit 54d9230
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ public class FindSymbolsRequest : IRequest
{
public string Language { get; set; }
public string Filter { get; set; }
public int? MinFilterLength { get; set; }
public int? MaxItemsToReturn { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,18 @@ public FindSymbolsHandler(OmniSharpWorkspace workspace)

public override Task<QuickFixResponse> Handle(FindSymbolsRequest request)
{
if (request?.Filter?.Length < request?.MinFilterLength.GetValueOrDefault())
{
return Task.FromResult(new QuickFixResponse { QuickFixes = Array.Empty<QuickFix>() });
}

Func<string, bool> isMatch =
candidate => request != null
? candidate.IsValidCompletionFor(request.Filter)
: true;

return Workspace.CurrentSolution.FindSymbols(isMatch, LanguageNames.Cake);
int maxItemsToReturn = (request?.MaxItemsToReturn).GetValueOrDefault();
return Workspace.CurrentSolution.FindSymbols(isMatch, LanguageNames.Cake, maxItemsToReturn);
}

protected override Task<QuickFixResponse> TranslateResponse(QuickFixResponse response, FindSymbolsRequest request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,19 @@ public FindSymbolsService(OmniSharpWorkspace workspace)

public async Task<QuickFixResponse> Handle(FindSymbolsRequest request = null)
{
if (request?.Filter?.Length < request?.MinFilterLength.GetValueOrDefault())
{
return new QuickFixResponse { QuickFixes = Array.Empty<QuickFix>() };
}

Func<string, bool> isMatch =
candidate => request != null
? candidate.IsValidCompletionFor(request.Filter)
: true;

var csprojSymbols = await _workspace.CurrentSolution.FindSymbols(isMatch, ".csproj");
var projectJsonSymbols = await _workspace.CurrentSolution.FindSymbols(isMatch, ".json");
int maxItemsToReturn = (request?.MaxItemsToReturn).GetValueOrDefault();
var csprojSymbols = await _workspace.CurrentSolution.FindSymbols(isMatch, ".csproj", maxItemsToReturn);
var projectJsonSymbols = await _workspace.CurrentSolution.FindSymbols(isMatch, ".json", maxItemsToReturn);
return new QuickFixResponse()
{
QuickFixes = csprojSymbols.QuickFixes.Concat(projectJsonSymbols.QuickFixes)
Expand Down
18 changes: 17 additions & 1 deletion src/OmniSharp.Roslyn/Extensions/SolutionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public static class SolutionExtensions
{
public static async Task<QuickFixResponse> FindSymbols(this Solution solution,
Func<string, bool> predicate,
string projectFileExtension)
string projectFileExtension,
int maxItemsToReturn)
{
var projects = solution.Projects.Where(p =>
(p.FilePath?.EndsWith(projectFileExtension, StringComparison.OrdinalIgnoreCase) ?? false) ||
Expand All @@ -37,12 +38,27 @@ public static async Task<QuickFixResponse> FindSymbols(this Solution solution,
{
symbolLocations.Add(ConvertSymbol(solution, symbol, location));
}

if (ShouldStopSearching(maxItemsToReturn, symbolLocations))
{
break;
}
}

if (ShouldStopSearching(maxItemsToReturn, symbolLocations))
{
break;
}
}

return new QuickFixResponse(symbolLocations.Distinct().ToList());
}

private static bool ShouldStopSearching(int maxItemsToReturn, List<QuickFix> symbolLocations)
{
return maxItemsToReturn > 0 && symbolLocations.Count >= maxItemsToReturn;
}

private static QuickFix ConvertSymbol(Solution solution, ISymbol symbol, Location location)
{
var lineSpan = location.GetLineSpan();
Expand Down
27 changes: 22 additions & 5 deletions tests/OmniSharp.Cake.Tests/FindSymbolsFacts.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Threading.Tasks;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using OmniSharp.Cake.Services.RequestHandlers.Navigation;
using OmniSharp.Models;
Expand All @@ -23,25 +24,41 @@ public FindSymbolsFacts(ITestOutputHelper testOutput) : base(testOutput)
[Fact]
public async Task ShouldFindSymbolsInCakeProjects()
{
var symbols = await FindSymbols("CakeProject");
var symbols = await FindSymbols("CakeProject", minFilterLength: null, maxItemsToReturn: null);
Assert.NotEmpty(symbols.QuickFixes);
}

[Fact]
public async Task ShouldNotFindSymbolsInCakeProjectsDueToEmptyFilter()
{
var symbols = await FindSymbols("CakeProject", minFilterLength: 1, maxItemsToReturn: 0);
Assert.Empty(symbols.QuickFixes);
}

[Fact]
public async Task ShouldFindLimitedNumberOfSymbolsInCakeProjects()
{
var symbols = await FindSymbols("CakeProject", minFilterLength: 0, maxItemsToReturn: 100);
Assert.Equal(100, symbols.QuickFixes.Count());
}

[Fact]
public async Task ShouldNotFindSymbolsInCSharpProjects()
{
var symbols = await FindSymbols("ProjectAndSolution");
var symbols = await FindSymbols("ProjectAndSolution", minFilterLength: 0, maxItemsToReturn: 0);
Assert.Empty(symbols.QuickFixes);
}

private async Task<QuickFixResponse> FindSymbols(string projectName)
private async Task<QuickFixResponse> FindSymbols(string projectName, int? minFilterLength, int? maxItemsToReturn)
{
using (var testProject = await TestAssets.Instance.GetTestProjectAsync(projectName, shadowCopy : false))
using (var host = CreateOmniSharpHost(testProject.Directory))
{
var request = new FindSymbolsRequest
{
Filter = ""
Filter = "",
MinFilterLength = minFilterLength,
MaxItemsToReturn = maxItemsToReturn
};

var requestHandler = GetRequestHandler(host);
Expand Down
43 changes: 39 additions & 4 deletions tests/OmniSharp.Roslyn.CSharp.Tests/FindSymbolsFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ private string NestedMethod() {}
}
}";

var usages = await FindSymbolsWithFilterAsync(code, "meth");
var usages = await FindSymbolsWithFilterAsync(code, "meth", minFilterLength: null, maxItemsToReturn: null);
var symbols = usages.QuickFixes.Select(q => q.Text);

var expected = new[]
Expand All @@ -240,7 +240,7 @@ public interface IConfigurationOptions { }
public class ConfigurationOptions : IConfigurationOptions { }
}";

var usages = await FindSymbolsWithFilterAsync(code, "opti");
var usages = await FindSymbolsWithFilterAsync(code, "opti", minFilterLength: 0, maxItemsToReturn: 0);
var symbols = usages.QuickFixes.Select(q => q.Text);

var expected = new[]
Expand All @@ -253,6 +253,37 @@ public class ConfigurationOptions : IConfigurationOptions { }
Assert.Equal(expected, symbols);
}

[Fact]
public async Task no_symbols_returned_when_filter_too_short()
{
const string code = @"
namespace Some.Namespace
{
public class Options {}
}";

var usages = await FindSymbolsWithFilterAsync(code, "op", minFilterLength: 3, maxItemsToReturn: 0);
var symbols = usages.QuickFixes.Select(q => q.Text);

Assert.Empty(symbols);
}

[Fact]
public async Task limit_number_of_returned_symbols()
{
const string code = @"
namespace Some.Namespace
{
public class Options1 {}
public class Options2 {}
public class Options3 {}
}";

var usages = await FindSymbolsWithFilterAsync(code, "op", minFilterLength: 0, maxItemsToReturn: 2);
var symbols = usages.QuickFixes.Select(q => q.Text);

Assert.Equal(2, symbols.Count());
}

private async Task<QuickFixResponse> FindSymbolsAsync(string code)
{
Expand All @@ -263,13 +294,17 @@ private async Task<QuickFixResponse> FindSymbolsAsync(string code)
return await requestHandler.Handle(null);
}

private async Task<QuickFixResponse> FindSymbolsWithFilterAsync(string code, string filter)
private async Task<QuickFixResponse> FindSymbolsWithFilterAsync(string code, string filter, int? minFilterLength, int? maxItemsToReturn)
{
var testFile = new TestFile("dummy.cs", code);
SharedOmniSharpTestHost.AddFilesToWorkspace(testFile);
var requestHandler = GetRequestHandler(SharedOmniSharpTestHost);

return await requestHandler.Handle(new FindSymbolsRequest { Filter = filter });
return await requestHandler.Handle(new FindSymbolsRequest {
Filter = filter,
MinFilterLength = minFilterLength,
MaxItemsToReturn = maxItemsToReturn
});
}
}
}

0 comments on commit 54d9230

Please sign in to comment.