|
// 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;
namespace Microsoft.CodeAnalysis;
internal partial struct SymbolKey
{
private sealed class SymbolKeyComparer : IEqualityComparer<SymbolKey>
{
private readonly ComparisonOptions _options;
private SymbolKeyComparer(ComparisonOptions options)
=> _options = options;
public bool Equals(SymbolKey x, SymbolKey y)
{
if (!_options.IgnoreAssemblyKey)
{
// Easiest case. We can directly compare the raw contents of the keys.
return x.Equals(y, _options.IgnoreCase);
}
else
{
// This is harder. To compare these we need to remove the entries related to assemblies.
//
// Note: this will remove the language-string as well, so we don't have to worry about that here.
var data1 = RemoveAssemblyKeys(x._symbolKeyData);
var data2 = RemoveAssemblyKeys(y._symbolKeyData);
var comparer = _options.IgnoreCase
? StringComparer.OrdinalIgnoreCase
: StringComparer.Ordinal;
return comparer.Equals(data1, data2);
}
}
private static string RemoveAssemblyKeys(string data)
{
var reader = new RemoveAssemblySymbolKeysReader();
reader.Initialize(data);
return reader.RemoveAssemblySymbolKeys();
}
public int GetHashCode(SymbolKey obj)
=> obj.GetHashCode();
public static IEqualityComparer<SymbolKey> GetComparer(bool ignoreCase, bool ignoreAssemblyKey)
=> GetComparer(new ComparisonOptions(ignoreCase, ignoreAssemblyKey));
private static readonly SymbolKeyComparer[] s_cachedComparers = new SymbolKeyComparer[4];
private static SymbolKeyComparer EnsureInitialized(ref SymbolKeyComparer location, ComparisonOptions options)
{
// This doesn't need to be interlocked since comparers store no state
return location ??= new SymbolKeyComparer(options);
}
public static IEqualityComparer<SymbolKey> GetComparer(ComparisonOptions options)
=> EnsureInitialized(ref s_cachedComparers[options.FlagsValue], options);
}
}
|