public async Task TestGetDocumentNodeToSelect() { var(mocks, model, uiItems) = await InitializeMocksAndDataModelAndUIItems(TestCode); var currentTextSnapshotLines = mocks.TextBuffer.CurrentSnapshot.Lines; // Click between 2 parent nodes (no symbol is selected) var caretPosition = currentTextSnapshotLines.ElementAt(11).End; var nodeToSelect = DocumentOutlineHelper.GetDocumentNodeToSelect(uiItems, model.OriginalSnapshot, caretPosition); Assert.Null(nodeToSelect); // Click within range of a parent symbol caretPosition = currentTextSnapshotLines.ElementAt(1).End; nodeToSelect = DocumentOutlineHelper.GetDocumentNodeToSelect(uiItems, model.OriginalSnapshot, caretPosition); Assert.Equal("MyClass", nodeToSelect?.Name); // Click within range of a child symbol caretPosition = currentTextSnapshotLines.ElementAt(5).End - 1; nodeToSelect = DocumentOutlineHelper.GetDocumentNodeToSelect(uiItems, model.OriginalSnapshot, caretPosition); Assert.Equal("Method1", nodeToSelect?.Name); // Click between 2 child symbols (caret is in range of parent) caretPosition = currentTextSnapshotLines.ElementAt(15).End; nodeToSelect = DocumentOutlineHelper.GetDocumentNodeToSelect(uiItems, model.OriginalSnapshot, caretPosition); Assert.Equal("App", nodeToSelect?.Name); }
public async Task TestSearchDocumentSymbolData() { var(_, model, _) = await InitializeMocksAndDataModelAndUIItems(TestCode); // Empty search (added for completeness, SearchDocumentSymbolData is not called on an empty search string) var searchedSymbols = DocumentOutlineHelper.SearchDocumentSymbolData(model.DocumentSymbolData, string.Empty, CancellationToken.None); Assert.Equal(0, searchedSymbols.Length); // Search for 1 parent only (no children should match) searchedSymbols = DocumentOutlineHelper.SearchDocumentSymbolData(model.DocumentSymbolData, "foo", CancellationToken.None); Assert.Equal(1, searchedSymbols.Length); Assert.Equal(0, searchedSymbols.Single(symbol => symbol.Name.Equals("foo")).Children.Length); // Search for children only (across 2 parents) searchedSymbols = DocumentOutlineHelper.SearchDocumentSymbolData(model.DocumentSymbolData, "Method", CancellationToken.None); Assert.Equal(2, searchedSymbols.Length); Assert.Equal(2, searchedSymbols.Single(symbol => symbol.Name.Equals("MyClass")).Children.Length); Assert.Equal(1, searchedSymbols.Single(symbol => symbol.Name.Equals("App")).Children.Length); // Search for a parent and a child (of aanother parent) searchedSymbols = DocumentOutlineHelper.SearchDocumentSymbolData(model.DocumentSymbolData, "app", CancellationToken.None); Assert.Equal(2, searchedSymbols.Length); Assert.Equal(0, searchedSymbols.Single(symbol => symbol.Name.Equals("App")).Children.Length); Assert.Equal(1, searchedSymbols.Single(symbol => symbol.Name.Equals("foo")).Children.Length); // No search results found searchedSymbols = DocumentOutlineHelper.SearchDocumentSymbolData(model.DocumentSymbolData, "xyz", CancellationToken.None); Assert.Equal(0, searchedSymbols.Length); }
private async Task CheckSorting(SortOption sortOption) { var(_, model, _) = await InitializeMocksAndDataModelAndUIItems(TestCode); var sortedSymbols = DocumentOutlineHelper.SortDocumentSymbolData(model.DocumentSymbolData, sortOption, CancellationToken.None); CheckSortedSymbols(sortedSymbols); void CheckSortedSymbols(ImmutableArray <DocumentSymbolData> sortedSymbols) { for (var i = 0; i < sortedSymbols.Length - 1; i++) { switch (sortOption) { case SortOption.Name: Assert.True(StringComparer.OrdinalIgnoreCase.Compare(sortedSymbols[i].Name, sortedSymbols[i + 1].Name) <= 0); break; case SortOption.Location: Assert.True(sortedSymbols[i].RangeSpan.Start < sortedSymbols[i + 1].RangeSpan.Start); break; case SortOption.Type: if (sortedSymbols[i].SymbolKind != sortedSymbols[i + 1].SymbolKind) { Assert.True(sortedSymbols[i].SymbolKind < sortedSymbols[i + 1].SymbolKind); } else { Assert.True(StringComparer.OrdinalIgnoreCase.Compare(sortedSymbols[i].Name, sortedSymbols[i + 1].Name) <= 0); } break; } } foreach (var symbol in sortedSymbols) { CheckSortedSymbols(symbol.Children); } } }
private async Task <(DocumentOutlineTestMocks mocks, DocumentSymbolDataModel model, ImmutableArray <DocumentSymbolUIItem> uiItems)> InitializeMocksAndDataModelAndUIItems(string testCode) { using var mocks = await CreateMocksAsync(testCode); var response = await DocumentOutlineHelper.DocumentSymbolsRequestAsync(mocks.TextBuffer, mocks.LanguageServiceBroker, mocks.FilePath, CancellationToken.None); AssertEx.NotNull(response.Value); var responseBody = response.Value.response?.ToObject <DocumentSymbol[]>(); AssertEx.NotNull(responseBody); var snapshot = response.Value.snapshot; AssertEx.NotNull(snapshot); var model = DocumentOutlineHelper.CreateDocumentSymbolDataModel(responseBody, snapshot); var uiItems = DocumentOutlineHelper.GetDocumentSymbolUIItems(model.DocumentSymbolData, mocks.ThreadingContext); return(mocks, model, uiItems); }
public async Task TestSetIsExpanded() { var(mocks, model, originalUIItems) = await InitializeMocksAndDataModelAndUIItems(TestCode); var updatedUIItems = DocumentOutlineHelper.GetDocumentSymbolUIItems(model.DocumentSymbolData, mocks.ThreadingContext); // Check that all updatedUIItems nodes are collapsed (originalUIItems parameter is unused) DocumentOutlineHelper.SetIsExpanded(updatedUIItems, originalUIItems, ExpansionOption.Collapse); CheckNodeExpansion(updatedUIItems, false); // Check that all updatedUIItems nodes are expanded (originalUIItems parameter is unused) DocumentOutlineHelper.SetIsExpanded(updatedUIItems, originalUIItems, ExpansionOption.Expand); CheckNodeExpansion(updatedUIItems, true); // Collapse 3 nodes in originalUIItems originalUIItems.Single(parent => parent.Name.Equals("App")).IsExpanded = false; originalUIItems.Single(parent => parent.Name.Equals("MyClass")).Children.Single(child => child.Name.Equals("Method2")).IsExpanded = false; originalUIItems.Single(parent => parent.Name.Equals("foo")).Children.Single(child => child.Name.Equals("r")).IsExpanded = false; // Apply same expansion as originalUIItems to updatedUIItems DocumentOutlineHelper.SetIsExpanded(updatedUIItems, originalUIItems, ExpansionOption.CurrentExpansion); // Confirm that matching expanded/collapsed node states have been applied CheckNodeExpansionMatches(updatedUIItems, originalUIItems);