|
// 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.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
using Roslyn.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.DocumentOutline;
/// <summary>
/// Sorts immutable collections of <see cref="DocumentSymbolDataViewModel"/>s
/// </summary>
internal sealed class DocumentSymbolDataViewModelSorter : MarkupExtension, IMultiValueConverter
{
public static DocumentSymbolDataViewModelSorter Instance { get; } = new();
public object Convert(object[] values, Type targetType, object? parameter, CultureInfo culture)
{
if (values[0] is ImmutableArray<DocumentSymbolDataViewModel> children &&
values[1] is SortOption sortOption)
{
return children.Sort(GetComparer(sortOption));
}
return values[0];
}
public static IComparer<DocumentSymbolDataViewModel> GetComparer(SortOption sortOption)
=> sortOption switch
{
SortOption.Name => NameComparer.Instance,
SortOption.Type => TypeComparer.Instance,
SortOption.Location => LocationComparer.Instance,
_ => throw ExceptionUtilities.UnexpectedValue(sortOption)
};
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
=> throw new NotImplementedException();
public override object ProvideValue(IServiceProvider serviceProvider)
=> Instance;
private sealed class NameComparer : IComparer<DocumentSymbolDataViewModel>
{
public static NameComparer Instance { get; } = new();
public int Compare(DocumentSymbolDataViewModel x, DocumentSymbolDataViewModel y)
=> StringComparer.OrdinalIgnoreCase.Compare(x.Data.Name, y.Data.Name);
}
private sealed class LocationComparer : IComparer<DocumentSymbolDataViewModel>
{
public static LocationComparer Instance { get; } = new();
public int Compare(DocumentSymbolDataViewModel x, DocumentSymbolDataViewModel y)
=> x.Data.RangeSpan.Start - y.Data.RangeSpan.Start;
}
private sealed class TypeComparer : IComparer<DocumentSymbolDataViewModel>
{
public static TypeComparer Instance { get; } = new();
public int Compare(DocumentSymbolDataViewModel x, DocumentSymbolDataViewModel y)
=> x.Data.SymbolKind == y.Data.SymbolKind
? NameComparer.Instance.Compare(x, y)
: x.Data.SymbolKind - y.Data.SymbolKind;
}
}
|