DocumentSymbolsTests.cs 5.3 KB
Newer Older
J
Jonathon Marolf 已提交
1 2 3
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
4 5 6 7 8

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
D
David Barbet 已提交
9
using Roslyn.Test.Utilities;
10 11 12 13 14
using Xunit;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.CodeAnalysis.LanguageServer.UnitTests.Symbols
{
D
tests.  
David Barbet 已提交
15
    public class DocumentSymbolsTests : AbstractLanguageServerProtocolTests
16 17 18 19 20
    {
        [Fact]
        public async Task TestGetDocumentSymbolsAsync()
        {
            var markup =
D
David Barbet 已提交
21
@"{|class:class {|classSelection:A|}
22
{
D
David Barbet 已提交
23
    {|method:void {|methodSelection:M|}()
24 25 26
    {
    }|}
}|}";
27
            using var workspace = CreateTestWorkspace(markup, out var locations);
28 29
            var expected = new LSP.DocumentSymbol[]
            {
D
David Barbet 已提交
30
                CreateDocumentSymbol(LSP.SymbolKind.Class, "A", "A", locations["class"].Single(), locations["classSelection"].Single())
31
            };
D
David Barbet 已提交
32
            CreateDocumentSymbol(LSP.SymbolKind.Method, "M", "M()", locations["method"].Single(), locations["methodSelection"].Single(), expected.First());
33

34
            var results = await RunGetDocumentSymbolsAsync(workspace.CurrentSolution, true);
D
David Barbet 已提交
35
            AssertJsonEquals(expected, results);
36 37 38 39 40 41 42 43 44 45 46 47
        }

        [Fact]
        public async Task TestGetDocumentSymbolsAsync__WithoutHierarchicalSupport()
        {
            var markup =
@"class {|class:A|}
{
    void {|method:M|}()
    {
    }
}";
48
            using var workspace = CreateTestWorkspace(markup, out var locations);
49 50
            var expected = new LSP.SymbolInformation[]
            {
D
David Barbet 已提交
51 52
                CreateSymbolInformation(LSP.SymbolKind.Class, "A", locations["class"].Single()),
                CreateSymbolInformation(LSP.SymbolKind.Method, "M()", locations["method"].Single(), "A")
53 54
            };

55
            var results = await RunGetDocumentSymbolsAsync(workspace.CurrentSolution, false);
D
David Barbet 已提交
56
            AssertJsonEquals(expected, results);
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        }

        [Fact(Skip = "GetDocumentSymbolsAsync does not yet support locals.")]
        // TODO - Remove skip & modify once GetDocumentSymbolsAsync is updated to support more than 2 levels.
        // https://github.com/dotnet/roslyn/projects/45#card-20033869
        public async Task TestGetDocumentSymbolsAsync__WithLocals()
        {
            var markup =
@"class A
{
    void Method()
    {
        int i = 1;
    }
}";
72 73
            using var workspace = CreateTestWorkspace(markup, out var _);
            var results = await RunGetDocumentSymbolsAsync(workspace.CurrentSolution, false).ConfigureAwait(false);
J
Jared Parsons 已提交
74
            Assert.Equal(3, results.Length);
75 76 77 78 79
        }

        [Fact]
        public async Task TestGetDocumentSymbolsAsync__NoSymbols()
        {
80
            using var workspace = CreateTestWorkspace(string.Empty, out var _);
81

82
            var results = await RunGetDocumentSymbolsAsync(workspace.CurrentSolution, true);
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
            Assert.Empty(results);
        }

        private static async Task<object[]> RunGetDocumentSymbolsAsync(Solution solution, bool hierarchicalSupport)
        {
            var document = solution.Projects.First().Documents.First();
            var request = new LSP.DocumentSymbolParams
            {
                TextDocument = CreateTextDocumentIdentifier(new Uri(document.FilePath))
            };

            var clientCapabilities = new LSP.ClientCapabilities()
            {
                TextDocument = new LSP.TextDocumentClientCapabilities()
                {
                    DocumentSymbol = new LSP.DocumentSymbolSetting()
                    {
                        HierarchicalDocumentSymbolSupport = hierarchicalSupport
                    }
                }
            };

D
David Barbet 已提交
105
            return await GetLanguageServer(solution).ExecuteRequestAsync<LSP.DocumentSymbolParams, object[]>(LSP.Methods.TextDocumentDocumentSymbolName,
106
                request, clientCapabilities, null, CancellationToken.None);
107 108 109 110 111 112 113 114 115 116 117 118 119 120
        }

        private static void AssertDocumentSymbolEquals(LSP.DocumentSymbol expected, LSP.DocumentSymbol actual)
        {
            Assert.Equal(expected.Kind, actual.Kind);
            Assert.Equal(expected.Name, actual.Name);
            Assert.Equal(expected.Range, actual.Range);
            Assert.Equal(expected.Children.Length, actual.Children.Length);
            for (var i = 0; i < actual.Children.Length; i++)
            {
                AssertDocumentSymbolEquals(expected.Children[i], actual.Children[i]);
            }
        }

D
David Barbet 已提交
121 122
        private static LSP.DocumentSymbol CreateDocumentSymbol(LSP.SymbolKind kind, string name, string detail,
            LSP.Location location, LSP.Location selection, LSP.DocumentSymbol parent = null)
123 124 125 126 127 128
        {
            var documentSymbol = new LSP.DocumentSymbol()
            {
                Kind = kind,
                Name = name,
                Range = location.Range,
D
David Barbet 已提交
129 130 131 132
                Children = new LSP.DocumentSymbol[0],
                Detail = detail,
                Deprecated = false,
                SelectionRange = selection.Range
133 134 135 136 137 138 139 140 141 142 143 144 145
            };

            if (parent != null)
            {
                var children = parent.Children.ToList();
                children.Add(documentSymbol);
                parent.Children = children.ToArray();
            }

            return documentSymbol;
        }
    }
}