Skip to content

Commit

Permalink
Merge pull request #665 from filipw/bugfix/fullname
Browse files Browse the repository at this point in the history
use SymbolDisplayFormat in TypeLookup
  • Loading branch information
DustinCampbell authored Nov 22, 2016
2 parents 7b61348 + 61c004e commit 5a3223d
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 14 deletions.
29 changes: 15 additions & 14 deletions src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Composition;
using System;
using System.Collections.Generic;
using System.Composition;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.FindSymbols;
Expand All @@ -15,6 +17,10 @@ public class TypeLookupService : RequestHandler<TypeLookupRequest, TypeLookupRes
{
private readonly FormattingOptions _formattingOptions;
private readonly OmnisharpWorkspace _workspace;
private static readonly SymbolDisplayFormat DefaultFormat = SymbolDisplayFormat.FullyQualifiedFormat.
WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted).
WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.None).
WithMiscellaneousOptions(SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers);

[ImportingConstructor]
public TypeLookupService(OmnisharpWorkspace workspace, FormattingOptions formattingOptions)
Expand All @@ -35,22 +41,17 @@ public async Task<TypeLookupResponse> Handle(TypeLookupRequest request)
var symbol = await SymbolFinder.FindSymbolAtPositionAsync(semanticModel, position, _workspace);
if (symbol != null)
{
//non regular C# code semantics (interactive, script) don't allow namespaces
if(document.SourceCodeKind == SourceCodeKind.Regular && symbol.Kind == SymbolKind.NamedType && !symbol.ContainingNamespace.IsGlobalNamespace)
{
response.Type = $"{symbol.ContainingNamespace.ToDisplayString()}.{symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat)}";
}
else
{
response.Type = symbol.ToDisplayString(SymbolDisplayFormat.MinimallyQualifiedFormat);
}
response.Type = symbol.Kind == SymbolKind.NamedType ?
symbol.ToDisplayString(DefaultFormat) :
symbol.ToMinimalDisplayString(semanticModel, position);
}

if (request.IncludeDocumentation)
{
response.Documentation = DocumentationConverter.ConvertDocumentation(symbol.GetDocumentationCommentXml(), _formattingOptions.NewLine);
}
if (request.IncludeDocumentation)
{
response.Documentation = DocumentationConverter.ConvertDocumentation(symbol.GetDocumentationCommentXml(), _formattingOptions.NewLine);
}
}

return response;
}
}
Expand Down
160 changes: 160 additions & 0 deletions tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,165 @@ class Foo {}

Assert.Equal("Bar.Foo", response.Type);
}

[Fact]
public async Task IncludesContainingTypeFoNestedTypesForRegularCSharpSyntax()
{
var source1 = @"namespace Bar {
class Foo {
class Xyz {}
}
}";

var workspace = await TestHelpers.CreateSimpleWorkspace(source1);

var controller = new TypeLookupService(workspace, new FormattingOptions());
var response = await controller.Handle(new TypeLookupRequest { FileName = "dummy.cs", Line = 2, Column = 27 });

Assert.Equal("Bar.Foo.Xyz", response.Type);
}

[Fact]
public async Task IncludesContainingTypeFoNestedTypesForNonRegularCSharpSyntax()
{
var source1 = @"class Foo {
class Bar {}
}";

var workspace = TestHelpers.CreateCsxWorkspace(source1);

var controller = new TypeLookupService(workspace, new FormattingOptions());
var response = await controller.Handle(new TypeLookupRequest { FileName = "dummy.csx", Line = 1, Column = 23 });

Assert.Equal("Foo.Bar", response.Type);
}

private static string testFile = @"using System;
using Bar2;
using System.Collections.Generic;
namespace Bar {
class Foo {
public Foo() {
Console.WriteLine(""abc"");
}
public void MyMethod(string name, Foo foo, Foo2 foo2) { };
private Foo2 _someField = new Foo2();
public Foo2 SomeProperty { get; }
public IDictionary<string, IEnumerable<int>> SomeDict { get; }
public void Compute(int index = 2) { }
}
}
namespace Bar2 {
class Foo2 {
}
}
";

private static async Task<TypeLookupResponse> GetTypeLookUpResponse(int line, int column)
{
var workspace = await TestHelpers.CreateSimpleWorkspace(testFile);

var controller = new TypeLookupService(workspace, new FormattingOptions());
var response = await controller.Handle(new TypeLookupRequest { FileName = "dummy.cs", Line = line, Column = column });

return response;
}

[Fact]
public async Task DisplayFormatForMethodSymbol_Invocation()
{
var response = await GetTypeLookUpResponse(line: 6, column: 35);
Assert.Equal("void Console.WriteLine(string s)", response.Type);
}

[Fact]
public async Task DisplayFormatForMethodSymbol_Declaration()
{
var response = await GetTypeLookUpResponse(line: 9, column: 35);
Assert.Equal("void Foo.MyMethod(string name, Foo foo, Foo2 foo2)", response.Type);
}

[Fact]
public async Task DisplayFormatFor_TypeSymbol_Primitive()
{
var response = await GetTypeLookUpResponse(line: 9, column: 46);
Assert.Equal("System.String", response.Type);
}

[Fact]
public async Task DisplayFormatFor_TypeSymbol_ComplexType_SameNamespace()
{
var response = await GetTypeLookUpResponse(line: 9, column: 56);
Assert.Equal("Bar.Foo", response.Type);
}

[Fact]
public async Task DisplayFormatFor_TypeSymbol_ComplexType_DifferentNamespace()
{
var response = await GetTypeLookUpResponse(line: 9, column: 67);
Assert.Equal("Bar2.Foo2", response.Type);
}

[Fact]
public async Task DisplayFormatFor_TypeSymbol_WithGenerics()
{
var response = await GetTypeLookUpResponse(line: 15, column: 36);
Assert.Equal("System.Collections.Generic.IDictionary<System.String, System.Collections.Generic.IEnumerable<System.Int32>>", response.Type);
}

[Fact]
public async Task DisplayFormatForParameterSymbol_Name_Primitive()
{
var response = await GetTypeLookUpResponse(line: 9, column: 51);
Assert.Equal("string name", response.Type);
}

[Fact]
public async Task DisplayFormatFor_ParameterSymbol_ComplexType_SameNamespace()
{
var response = await GetTypeLookUpResponse(line: 9, column: 60);
Assert.Equal("Foo foo", response.Type);
}

[Fact]
public async Task DisplayFormatFor_ParameterSymbol_Name_ComplexType_DifferentNamespace()
{
var response = await GetTypeLookUpResponse(line: 9, column: 71);
Assert.Equal("Foo2 foo2", response.Type);
}

[Fact]
public async Task DisplayFormatFor_ParameterSymbol_Name_WithDefaultValue()
{
var response = await GetTypeLookUpResponse(line: 17, column: 48);
Assert.Equal("int index = 2", response.Type);
}

[Fact]
public async Task DisplayFormatFor_FieldSymbol()
{
var response = await GetTypeLookUpResponse(line: 11, column: 38);
Assert.Equal("Foo2 Foo._someField", response.Type);
}

[Fact]
public async Task DisplayFormatFor_PropertySymbol()
{
var response = await GetTypeLookUpResponse(line: 13, column: 38);
Assert.Equal("Foo2 Foo.SomeProperty", response.Type);
}

[Fact]
public async Task DisplayFormatFor_PropertySymbol_WithGenerics()
{
var response = await GetTypeLookUpResponse(line: 15, column: 70);
Assert.Equal("IDictionary<string, IEnumerable<int>> Foo.SomeDict", response.Type);
}
}
}

0 comments on commit 5a3223d

Please sign in to comment.