Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 0 additions & 31 deletions src/Compilers/Core/Portable/InternalUtilities/EmptyComparer.cs

This file was deleted.

63 changes: 63 additions & 0 deletions src/Dependencies/Contracts/EqualityComparerExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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.

#nullable enable

#if !NET8_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif

namespace System.Collections.Generic;

internal static class RoslynEqualityComparerExtensions
{
#if NET8_0_OR_GREATER

// for binary compatibility
public static EqualityComparer<T> Create<T>(Func<T?, T?, bool> equals, Func<T, int>? getHashCode = null)
=> EqualityComparer<T>.Create(equals, getHashCode);

#else
// Implementation based on https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.cs

extension<T>(EqualityComparer<T>)
{
/// <summary>
/// Creates an <see cref="EqualityComparer{T}"/> by using the specified delegates as the implementation of the comparer's
/// <see cref="EqualityComparer{T}.Equals"/> and <see cref="EqualityComparer{T}.GetHashCode"/> methods.
/// </summary>
/// <param name="equals">The delegate to use to implement the <see cref="EqualityComparer{T}.Equals"/> method.</param>
/// <param name="getHashCode">
/// The delegate to use to implement the <see cref="EqualityComparer{T}.GetHashCode"/> method.
/// If no delegate is supplied, calls to the resulting comparer's <see cref="EqualityComparer{T}.GetHashCode"/>
/// will throw <see cref="NotSupportedException"/>.
/// </param>
/// <returns>The new comparer.</returns>
public static EqualityComparer<T> Create(Func<T?, T?, bool> equals, Func<T, int>? getHashCode = null)
{
getHashCode ??= _ => throw new NotSupportedException();
return new DelegateEqualityComparer<T>(equals, getHashCode);
}
}

private sealed class DelegateEqualityComparer<T>(Func<T?, T?, bool> equals, Func<T, int> getHashCode) : EqualityComparer<T>
{
private readonly Func<T?, T?, bool> _equals = equals;
private readonly Func<T, int> _getHashCode = getHashCode;

public override bool Equals(T? x, T? y) =>
_equals(x, y);

public override int GetHashCode(T obj) =>
_getHashCode(obj);

public override bool Equals(object? obj)
=> obj is DelegateEqualityComparer<T> other && _equals == other._equals && _getHashCode == other._getHashCode;

public override int GetHashCode()
=> unchecked(_equals.GetHashCode() * (int)0xA5555529 + _getHashCode.GetHashCode());
}
#endif
}

Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<Compile Include="$(MSBuildThisFileDirectory)RequiredMemberAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SetsRequiredMembersAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ExceptionUtilities.cs" />
<Compile Include="$(MSBuildThisFileDirectory)EqualityComparerExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ReferenceEqualityComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Index.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Range.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ErrorReporting\FatalError.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@

using System.Runtime.CompilerServices;

#if NET5_0_OR_GREATER
#nullable enable

#if NET

#pragma warning disable RS0016 // Add public types and members to the declared API (this is a supporting forwarder for an internal polyfill API)
[assembly: TypeForwardedTo(typeof(System.Collections.Generic.ReferenceEqualityComparer))]
Expand Down
13 changes: 3 additions & 10 deletions src/EditorFeatures/Test/Collections/Immutable/Maps/MapTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,9 @@ public void TestRemove()
[Fact]
public void TestPathology()
{
var map = ImmutableDictionary.Create<string, int>(new PathologicalComparer<string>())
var comparer = EqualityComparer<string>.Create(EqualityComparer<string>.Default.Equals, _ => 0);

var map = ImmutableDictionary.Create<string, int>(comparer)
.Add("1", 1)
.Add("2", 2)
.Add("3", 3)
Expand Down Expand Up @@ -118,13 +120,4 @@ public void TestPathology()
map = map.Remove("5");
Assert.Empty(map);
}

private sealed class PathologicalComparer<T> : IEqualityComparer<T>
{
public bool Equals(T x, T y)
=> EqualityComparer<T>.Default.Equals(x, y);

public int GetHashCode(T obj)
=> 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ namespace Microsoft.CodeAnalysis.Completion.Providers;
internal abstract partial class AbstractKeywordCompletionProvider<TContext> : LSPCompletionProvider
where TContext : SyntaxContext
{
private static readonly Comparer s_comparer = new();
private static readonly EqualityComparer<CompletionItem> s_comparer = EqualityComparer<CompletionItem>.Create(
static (x, y) => x?.DisplayText == y?.DisplayText,
static x => x.DisplayText.GetHashCode());

private readonly ImmutableArray<IKeywordRecommender<TContext>> _keywordRecommenders;

Expand Down Expand Up @@ -72,13 +74,4 @@ private async Task<ImmutableArray<RecommendedKeyword>> RecommendKeywordsAsync(

public sealed override Task<TextChange?> GetTextChangeAsync(Document document, CompletionItem item, char? ch, CancellationToken cancellationToken)
=> Task.FromResult((TextChange?)new TextChange(item.Span, item.DisplayText));

private sealed class Comparer : IEqualityComparer<CompletionItem>
{
public bool Equals(CompletionItem? x, CompletionItem? y)
=> x?.DisplayText == y?.DisplayText;

public int GetHashCode(CompletionItem obj)
=> Hash.Combine(obj.DisplayText.GetHashCode(), obj.DisplayText.GetHashCode());
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
Expand All @@ -19,7 +19,6 @@
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\RoslynExperiments.cs" Link="InternalUtilities\RoslynExperiments.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\InterlockedOperations.cs" Link="InternalUtilities\InterlockedOperations.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\ReadOnlyMemoryOfCharComparer.cs" Link="InternalUtilities\ReadOnlyMemoryOfCharComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\ReferenceEqualityComparer.cs" Link="InternalUtilities\ReferenceEqualityComparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\SingleInitNullable.cs" Link="InternalUtilities\SingleInitNullable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\SharedStopwatch.cs" Link="InternalUtilities\SharedStopwatch.cs" />
<Compile Include="$(MSBuildThisFileDirectory)..\..\..\..\Compilers\Core\Portable\InternalUtilities\ValueTaskFactory.cs" Link="InternalUtilities\ValueTaskFactory.cs" />
Expand Down
Loading