diff --git a/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs b/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs index d70eca2743..d590b22395 100644 --- a/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs +++ b/src/OmniSharp.Roslyn.CSharp/Services/Types/TypeLookup.cs @@ -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; @@ -15,6 +17,10 @@ public class TypeLookupService : RequestHandler 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; } } diff --git a/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs b/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs index e06be7ffb6..e0f1011676 100644 --- a/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs +++ b/tests/OmniSharp.Roslyn.CSharp.Tests/TypeLookupFacts.cs @@ -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> SomeDict { get; } + + public void Compute(int index = 2) { } + } + } + + namespace Bar2 { + class Foo2 { + } + } + "; + + private static async Task 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>", 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> Foo.SomeDict", response.Type); + } } }