<commit_before>﻿// 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.

////#define TRACKDEPTH

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Shared.Utilities
{
    internal partial class SymbolEquivalenceComparer
    {
        private class EquivalenceVisitor
        {
            private readonly bool _compareMethodTypeParametersByIndex;
            private readonly bool _objectAndDynamicCompareEqually;
            private readonly SymbolEquivalenceComparer _symbolEquivalenceComparer;

            public EquivalenceVisitor(
                SymbolEquivalenceComparer symbolEquivalenceComparer,
                bool compareMethodTypeParametersByIndex,
                bool objectAndDynamicCompareEqually)
            {
                _symbolEquivalenceComparer = symbolEquivalenceComparer;
                _compareMethodTypeParametersByIndex = compareMethodTypeParametersByIndex;
                _objectAndDynamicCompareEqually = objectAndDynamicCompareEqually;
            }

#if TRACKDEPTH
            private int depth = 0;
#endif
            public bool AreEquivalent(ISymbol x, ISymbol y, Dictionary<INamedTypeSymbol, INamedTypeSymbol> equivalentTypesWithDifferingAssemblies)
            {
#if TRACKDEPTH
                try
                { 
                this.depth++;
                if (depth > 100)
                {
                    throw new InvalidOperationException("Stack too deep.");
                }
#endif

                if (x is ITypeSymbol xType && y is ITypeSymbol yType)
                {
                    // Nullability is not considered a distinguishing factor between symbols in this component.  Strip
                    // nullability from these symbols.  This also ensures we can do reference-equality checks later as
                    // stripping nullability returns the underlying symbol and does not produce new symbols with the
                    // updated nullability value.
                    x = xType.WithNullableAnnotation(NullableAnnotation.None);
                    y = yType.WithNullableAnnotation(NullableAnnotation.None);
                }

                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (x == null || y == null)
                {
                    return false;
                }

                var xKind = GetKindAndUnwrapAlias(ref x);
                var yKind = GetKindAndUnwrapAlias(ref y);

                // Normally, if they're different types, then they're not the same.
                if (xKind != yKind)
                {
                    // Special case.  If we're comparing signatures then we want to compare 'object'
                    // and 'dynamic' as the same.  However, since they're different types, we don't
                    // want to bail out using the above check.
                    return _objectAndDynamicCompareEqually &&
                           ((yKind == SymbolKind.DynamicType && xKind == SymbolKind.NamedType && ((ITypeSymbol)x).SpecialType == SpecialType.System_Object) ||
                            (xKind == SymbolKind.DynamicType && yKind == SymbolKind.NamedType && ((ITypeSymbol)y).SpecialType == SpecialType.System_Object));
                }

                return AreEquivalentWorker(x, y, xKind, equivalentTypesWithDifferingAssemblies);<commit_msg>Tweak to followup underlying pattern compiler uses<commit_after>﻿// 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.

////#define TRACKDEPTH

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Shared.Utilities
{
    internal partial class SymbolEquivalenceComparer
    {
        private class EquivalenceVisitor
        {
            private readonly bool _compareMethodTypeParametersByIndex;
            private readonly bool _objectAndDynamicCompareEqually;
            private readonly SymbolEquivalenceComparer _symbolEquivalenceComparer;

            public EquivalenceVisitor(
                SymbolEquivalenceComparer symbolEquivalenceComparer,
                bool compareMethodTypeParametersByIndex,
                bool objectAndDynamicCompareEqually)
            {
                _symbolEquivalenceComparer = symbolEquivalenceComparer;
                _compareMethodTypeParametersByIndex = compareMethodTypeParametersByIndex;
                _objectAndDynamicCompareEqually = objectAndDynamicCompareEqually;
            }

#if TRACKDEPTH
            private int depth = 0;
#endif
            public bool AreEquivalent(ISymbol x, ISymbol y, Dictionary<INamedTypeSymbol, INamedTypeSymbol> equivalentTypesWithDifferingAssemblies)
            {
#if TRACKDEPTH
                try
                { 
                this.depth++;
                if (depth > 100)
                {
                    throw new InvalidOperationException("Stack too deep.");
                }
#endif

                if (x is ITypeSymbol xType && y is ITypeSymbol yType)
                {
                    // Nullability is not considered a distinguishing factor between symbols in this component.  Strip
                    // nullability from these symbols.  This also ensures we can do reference-equality checks later as
                    // stripping nullability returns the underlying symbol and does not produce new symbols with the
                    // updated nullability value.

                    x = xType.WithNullableAnnotation(xType.IsValueType ? NullableAnnotation.NotAnnotated : NullableAnnotation.None);
                    y = yType.WithNullableAnnotation(yType.IsValueType ? NullableAnnotation.NotAnnotated : NullableAnnotation.None);
                }

                if (ReferenceEquals(x, y))
                {
                    return true;
                }

                if (x == null || y == null)
                {
                    return false;
                }

                var xKind = GetKindAndUnwrapAlias(ref x);
                var yKind = GetKindAndUnwrapAlias(ref y);

                // Normally, if they're different types, then they're not the same.
                if (xKind != yKind)
                {
                    // Special case.  If we're comparing signatures then we want to compare 'object'
                    // and 'dynamic' as the same.  However, since they're different types, we don't
                    // want to bail out using the above check.
                    return _objectAndDynamicCompareEqually &&
                           ((yKind == SymbolKind.DynamicType && xKind == SymbolKind.NamedType && ((ITypeSymbol)x).SpecialType == SpecialType.System_Object) ||
                            (xKind == SymbolKind.DynamicType && yKind == SymbolKind.NamedType && ((ITypeSymbol)y).SpecialType == SpecialType.System_Object));
                }

                return AreEquivalentWorker(x, y, xKind, equivalentTypesWithDifferingAssemblies);
{'fraction_non_alphanumeric': 0.061734965407131456, 'fraction_numerical': 0.0010643959552953698, 'mean_word_length': 1.9090557275541795, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2776270', 'n_tokens_mistral': 1788, 'n_tokens_neox': 1646, 'n_words': 515}