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

Fixed a regression that broke FindSymbols for CSX #1321

Merged
merged 3 commits into from
Oct 31, 2018
Merged
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
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;
}
}
}