Skip to content

Commit

Permalink
Merge pull request #1321 from filipw/bugfix/csx-findsymbols
Browse files Browse the repository at this point in the history
Fixed a regression that broke FindSymbols for CSX
  • Loading branch information
filipw authored Oct 31, 2018
2 parents bc9e22c + 71195e4 commit 323b738
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 79 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All changes to the project will be documented in this file.
## [1.32.7] - not yet released
* It's now possible to override the default location of OmniSharp's global folder (%USERPROFILE%\.omnisharp or ~/.omnisharp.) with an OMNISHARPHOME environment variable (PR: [#1317](https://github.com/OmniSharp/omnisharp-roslyn/pull/1317))
* OmniSharp no longer searches for `config.json` in its source directory to load configuration (PR: [#1319](https://github.com/OmniSharp/omnisharp-roslyn/pull/1319))
* Fixed a regression introduced in 1.32.4, that prevented find symbol endpoint from working for CSX projects (PR: [#1321](https://github.com/OmniSharp/omnisharp-roslyn/pull/1321))

## [1.32.6] - 2018-10-02
* Fixed a bug where virtual C# documents would not get promoted to be a part of a project. (PR: [#1306](https://github.com/OmniSharp/omnisharp-roslyn/pull/1306)).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ public async Task<QuickFixResponse> Handle(FindSymbolsRequest request = null)
int maxItemsToReturn = (request?.MaxItemsToReturn).GetValueOrDefault();
var csprojSymbols = await _workspace.CurrentSolution.FindSymbols(request?.Filter, ".csproj", maxItemsToReturn);
var projectJsonSymbols = await _workspace.CurrentSolution.FindSymbols(request?.Filter, ".json", maxItemsToReturn);
var csxSymbols = await _workspace.CurrentSolution.FindSymbols(request?.Filter, ".csx", maxItemsToReturn);
return new QuickFixResponse()
{
QuickFixes = csprojSymbols.QuickFixes.Concat(projectJsonSymbols.QuickFixes)
QuickFixes = csprojSymbols.QuickFixes.Concat(projectJsonSymbols.QuickFixes).Concat(csxSymbols.QuickFixes)
};
}
}
Expand Down
182 changes: 104 additions & 78 deletions tests/OmniSharp.Roslyn.CSharp.Tests/FindSymbolsFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ public FindSymbolsFacts(ITestOutputHelper output, SharedOmniSharpHostFixture sha

protected override string EndpointName => OmniSharpEndpoints.FindSymbols;

[Fact]
public async Task Can_find_symbols()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Can_find_symbols(string filename)
{
const string code = @"
namespace Some.Long.Namespace
{
string code = @"
public class Foo
{
private string _field = 0;
Expand All @@ -41,10 +41,10 @@ private class Nested
{
private string NestedMethod() {}
}
}
}";
}";

var usages = await FindSymbolsAsync(code);
code = WrapInNamespaceIfNeeded(code, filename);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Select(q => q.Text);

var expected = new[]
Expand All @@ -62,16 +62,18 @@ private string NestedMethod() {}
Assert.Equal(expected, symbols);
}

[Fact]
public async Task Does_not_return_event_keyword()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Does_not_return_event_keyword(string filename)
{
const string code = @"
public static class Game
{
public static event GameEvent GameResumed;
}";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Select(q => q.Text);

var expected = new[]
Expand All @@ -83,12 +85,12 @@ public static class Game
Assert.Equal(expected, symbols);
}

[Fact]
public async Task Can_find_symbols_kinds()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Can_find_symbols_kinds(string filename)
{
const string code = @"
namespace Some.Long.Namespace
{
string code = @"
public class Foo
{
private string _field = 0;
Expand All @@ -105,10 +107,10 @@ private class Nested
{
private string NestedMethod() {}
}
}
}";
}";

var usages = await FindSymbolsAsync(code);
code = WrapInNamespaceIfNeeded(code, filename);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Cast<SymbolLocation>().Select(q => q.Kind);

var expected = new[]
Expand All @@ -126,48 +128,58 @@ private string NestedMethod() {}
Assert.Equal(expected, symbols);
}

[Fact]
public async Task Returns_interface_kind()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Returns_interface_kind(string filename)
{
const string code = @"public interface Foo {}";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Cast<SymbolLocation>().Select(q => q.Kind);
Assert.Equal("Interface", symbols.First());
}

[Fact]
public async Task Returns_enum_kind()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Returns_enum_kind(string filename)
{
const string code = @"public enum Foo {}";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Cast<SymbolLocation>().Select(q => q.Kind);
Assert.Equal("Enum", symbols.First());
}

[Fact]
public async Task Returns_struct_kind()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Returns_struct_kind(string filename)
{
const string code = @"public struct Foo {}";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Cast<SymbolLocation>().Select(q => q.Kind);
Assert.Equal("Struct", symbols.First());
}

[Fact]
public async Task Returns_delegate_kind()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Returns_delegate_kind(string filename)
{
const string code = @"public delegate void Foo();";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var symbols = usages.QuickFixes.Cast<SymbolLocation>().Select(q => q.Kind);
Assert.Equal("Delegate", symbols.First());
}

[Fact]
public async Task Finds_partial_method_with_body()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Finds_partial_method_with_body(string filename)
{
const string code = @"
public partial class MyClass
Expand All @@ -183,19 +195,19 @@ partial void Method()
}
}";

var usages = await FindSymbolsAsync(code);
var usages = await FindSymbolsAsync(code, filename);
var methodSymbol = usages.QuickFixes.Cast<SymbolLocation>().First(x => x.Kind == SymbolKind.Method.ToString());

// should find the occurrance with body
Assert.Equal(8, methodSymbol.Line);
}

[Fact]
public async Task Can_find_symbols_using_filter()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Can_find_symbols_using_filter(string filename)
{
const string code = @"
namespace Some.Long.Namespace
{
string code = @"
public class Foo
{
private string _field = 0;
Expand All @@ -212,10 +224,10 @@ private class Nested
{
private string NestedMethod() {}
}
}
}";
}";

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

var expected = new[]
Expand All @@ -228,19 +240,19 @@ private string NestedMethod() {}
Assert.Equal(expected, symbols);
}

[Fact]
public async Task Can_find_symbols_using_filter_with_subset_match()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task Can_find_symbols_using_filter_with_subset_match(string filename)
{
const string code = @"
namespace Some.Long.Namespace
{
string code = @"
public class Options {}
public class Opossum {}
public interface IConfigurationOptions { }
public class ConfigurationOptions : IConfigurationOptions { }
}";
public class ConfigurationOptions : IConfigurationOptions { }";

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

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

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

var usages = await FindSymbolsWithFilterAsync(code, "op", minFilterLength: 3, maxItemsToReturn: 0);
code = WrapInNamespaceIfNeeded(code, filename);
var usages = await FindSymbolsWithFilterAsync(code, filename, "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()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task limit_number_of_returned_symbols(string filename)
{
const string code = @"
namespace Some.Namespace
{
string code = @"
public class Options1 {}
public class Options2 {}
public class Options3 {}
}";
public class Options3 {}";

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

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

[Fact]
public async Task fuzzy_search()
[Theory]
[InlineData("dummy.cs")]
[InlineData("dummy.csx")]
public async Task fuzzy_search(string filename)
{
const string code = @"
namespace Some.Namespace
{
string code = @"
public class ProjectManager {}
public class CoolProjectManager {}
public class ProbabilityManager {}
}";
public class ProbabilityManager {}";

var usages = await FindSymbolsWithFilterAsync(code, "ProjMana", minFilterLength: 0, maxItemsToReturn: 0);
code = WrapInNamespaceIfNeeded(code, filename);
var usages = await FindSymbolsWithFilterAsync(code, filename, "ProjMana", minFilterLength: 0, maxItemsToReturn: 0);
var symbols = usages.QuickFixes.Select(q => q.Text);
Assert.Contains("ProjectManager", symbols);
Assert.Contains("CoolProjectManager", symbols);
Assert.DoesNotContain("ProbabilityManager", symbols);
}

private async Task<QuickFixResponse> FindSymbolsAsync(string code)
private async Task<QuickFixResponse> FindSymbolsAsync(string code, string filename)
{
var testFile = new TestFile("dummy.cs", code);
var testFile = new TestFile(filename, code);
SharedOmniSharpTestHost.AddFilesToWorkspace(testFile);
var requestHandler = GetRequestHandler(SharedOmniSharpTestHost);

return await requestHandler.Handle(null);
}

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

Expand All @@ -324,5 +336,19 @@ private async Task<QuickFixResponse> FindSymbolsWithFilterAsync(string code, str
MaxItemsToReturn = maxItemsToReturn
});
}

private string WrapInNamespaceIfNeeded(string code, string filename)
{
if (filename.EndsWith(".cs"))
{
code = @"
namespace Some.Long.Namespace
{
" + code + @"
}";
}

return code;
}
}
}

0 comments on commit 323b738

Please sign in to comment.