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

Introduce configuration for "Go to Symbol in Workspace" #1284

Merged
merged 14 commits into from
Sep 20, 2018
Merged
Show file tree
Hide file tree
Changes from 11 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
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; }
dmgonch marked this conversation as resolved.
Show resolved Hide resolved
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 != null && request.Filter != null && request.Filter.Length < request.MinFilterLength)
dmgonch marked this conversation as resolved.
Show resolved Hide resolved
{
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 == null ? 0 : request.MaxItemsToReturn;
dmgonch marked this conversation as resolved.
Show resolved Hide resolved
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 != null && request.Filter != null && request.Filter.Length < request.MinFilterLength)
{
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 == null ? 0 : request.MaxItemsToReturn;
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", 0, 0);
Assert.NotEmpty(symbols.QuickFixes);
}

[Fact]
public async Task ShouldNotFindSymbolsInCakeProjectsDueToEmptyFilter()
{
var symbols = await FindSymbols("CakeProject", 1, 0);
dmgonch marked this conversation as resolved.
Show resolved Hide resolved
Assert.Empty(symbols.QuickFixes);
}

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

[Fact]
public async Task ShouldNotFindSymbolsInCSharpProjects()
{
var symbols = await FindSymbols("ProjectAndSolution");
var symbols = await FindSymbols("ProjectAndSolution", 0, 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", 0, 0);
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", 0, 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", 3, 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", 0, 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
});
}
}
}