File: TypeSyntaxComparer.cs
Web Access
Project: ..\..\..\src\Workspaces\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Workspaces.csproj (Microsoft.CodeAnalysis.CSharp.Workspaces)
// 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.Collections.Generic;
using Microsoft.CodeAnalysis.CSharp.Syntax;
 
namespace Microsoft.CodeAnalysis.CSharp.Utilities
{
    internal class TypeSyntaxComparer : IComparer<TypeSyntax?>
    {
        private readonly IComparer<SyntaxToken> _tokenComparer;
        internal readonly IComparer<NameSyntax?> NameComparer;
 
        internal TypeSyntaxComparer(IComparer<SyntaxToken> tokenComparer, IComparer<NameSyntax?> nameComparer)
        {
            _tokenComparer = tokenComparer;
            NameComparer = nameComparer;
        }
 
        public int Compare(TypeSyntax? x, TypeSyntax? y)
        {
            if (x is null)
                return y is null ? 0 : -1;
            else if (y is null)
                return 1;
 
            if (x == y)
            {
                return 0;
            }
 
            x = UnwrapType(x);
            y = UnwrapType(y);
 
            if (x is NameSyntax && y is NameSyntax)
            {
                return NameComparer.Compare((NameSyntax)x, (NameSyntax)y);
            }
 
            // we have two predefined types, or a predefined type and a normal C# name.  We only need
            // to compare the first tokens here.
            return _tokenComparer.Compare(x.GetFirstToken(includeSkipped: true), y.GetFirstToken());
        }
 
        private static TypeSyntax UnwrapType(TypeSyntax type)
        {
            while (true)
            {
                switch (type.Kind())
                {
                    case SyntaxKind.ArrayType:
                        type = ((ArrayTypeSyntax)type).ElementType;
                        break;
                    case SyntaxKind.PointerType:
                        type = ((PointerTypeSyntax)type).ElementType;
                        break;
                    case SyntaxKind.NullableType:
                        type = ((NullableTypeSyntax)type).ElementType;
                        break;
                    default:
                        return type;
                }
            }
        }
    }
}