提交 9409266d 编写于 作者: C Charles Stoner

Implement Equals for Diagnostic arguments

上级 dc0c3fa6
......@@ -606,19 +606,16 @@ public bool GenerateSummaryErrors(DiagnosticBag diagnostics)
// two errors; we can for example simply take the one that is lower in alphabetical
// order when converted to a string.
var equalityComparer = new CommonDiagnosticComparer();
Func<Diagnostic, Diagnostic, int> canonicalComparer = CanonicallyCompareDiagnostics;
FirstAmongEqualsSet<Diagnostic> intersection = null;
var convBags = from boundLambda in _bindingCache.Values select boundLambda.Diagnostics;
var retBags = from boundLambda in _returnInferenceCache.Values select boundLambda.Diagnostics;
var allBags = convBags.Concat(retBags);
FirstAmongEqualsSet<Diagnostic> intersection = null;
foreach (ImmutableArray<Diagnostic> bag in allBags)
{
if (intersection == null)
{
intersection = new FirstAmongEqualsSet<Diagnostic>(bag, equalityComparer, canonicalComparer);
intersection = CreateFirstAmongEqualsSet(bag);
}
else
{
......@@ -628,13 +625,10 @@ public bool GenerateSummaryErrors(DiagnosticBag diagnostics)
if (intersection != null)
{
foreach (var diagnostic in intersection)
if (PreventsSuccessfulDelegateConversion(intersection))
{
if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code))
{
diagnostics.AddRange(intersection);
return true;
}
diagnostics.AddRange(intersection);
return true;
}
}
......@@ -644,7 +638,7 @@ public bool GenerateSummaryErrors(DiagnosticBag diagnostics)
{
if (union == null)
{
union = new FirstAmongEqualsSet<Diagnostic>(bag, equalityComparer, canonicalComparer);
union = CreateFirstAmongEqualsSet(bag);
}
else
{
......@@ -654,19 +648,40 @@ public bool GenerateSummaryErrors(DiagnosticBag diagnostics)
if (union != null)
{
foreach (var diagnostic in union)
if (PreventsSuccessfulDelegateConversion(union))
{
if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code))
{
diagnostics.AddRange(union);
return true;
}
diagnostics.AddRange(union);
return true;
}
}
return false;
}
private static bool PreventsSuccessfulDelegateConversion(FirstAmongEqualsSet<Diagnostic> set)
{
foreach (var diagnostic in set)
{
if (ErrorFacts.PreventsSuccessfulDelegateConversion((ErrorCode)diagnostic.Code))
{
return true;
}
}
return false;
}
private static FirstAmongEqualsSet<Diagnostic> CreateFirstAmongEqualsSet(ImmutableArray<Diagnostic> bag)
{
// For the purposes of lambda error reporting we wish to compare
// diagnostics for equality only considering their code and location,
// but not other factors such as the values supplied for the
// parameters of the diagnostic.
return new FirstAmongEqualsSet<Diagnostic>(
bag,
CommonDiagnosticComparer.Instance,
CanonicallyCompareDiagnostics);
}
/// <summary>
/// What we need to do is find a *repeatable* arbitrary way to choose between
/// two errors; we can for example simply take the one that is lower in alphabetical
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
......@@ -87,5 +83,31 @@ public override bool IsImplicitlyDeclared
internal override ModuleSymbol ContainingModule { get { throw ExceptionUtilities.Unreachable; } }
#endregion Not used by MethodSignatureComparer
public override bool Equals(object obj)
{
if ((object)this == obj)
{
return true;
}
var other = obj as SignatureOnlyParameterSymbol;
return (object)other != null &&
_type == other._type &&
_customModifiers.Equals(other._customModifiers) &&
_isParams == other._isParams &&
_refKind == other._refKind;
}
public override int GetHashCode()
{
return Hash.Combine(
_type.GetHashCode(),
Hash.Combine(
Hash.CombineValues(_customModifiers),
Hash.Combine(
_isParams.GetHashCode(),
_refKind.GetHashCode())));
}
}
}
......@@ -4,7 +4,6 @@
using Roslyn.Utilities;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
namespace Microsoft.CodeAnalysis.CSharp
{
......@@ -152,7 +151,6 @@ private static Symbol UnwrapSymbol(Symbol symbol)
}
}
private static string GetLocationString(Compilation compilation, Symbol unwrappedSymbol)
{
Debug.Assert((object)unwrappedSymbol == UnwrapSymbol(unwrappedSymbol));
......@@ -198,7 +196,7 @@ private string GetDescription(int index)
return _lazyDescriptions[index];
}
private class Description : IMessageSerializable
private sealed class Description : IMessageSerializable
{
private readonly SymbolDistinguisher _distinguisher;
private readonly int _index;
......@@ -209,6 +207,26 @@ public Description(SymbolDistinguisher distinguisher, int index)
_index = index;
}
private Symbol GetSymbol()
{
return (_index == 0) ? _distinguisher._symbol0 : _distinguisher._symbol1;
}
public override bool Equals(object obj)
{
var other = obj as Description;
return other != null &&
_distinguisher._compilation == other._distinguisher._compilation &&
GetSymbol() == other.GetSymbol();
}
public override int GetHashCode()
{
return Hash.Combine(
_distinguisher._compilation.GetHashCode(),
GetSymbol().GetHashCode());
}
public override string ToString()
{
return _distinguisher.GetDescription(_index);
......
......@@ -4435,5 +4435,36 @@ .maxstack 8
Assert.Equal("E1", e1.Name);
Assert.Equal("E1", e1.ToDisplayString(format));
}
[WorkItem(6262)]
[Fact]
public void FormattedSymbolEquality()
{
var source =
@"class A { }
class B { }
class C<T> { }";
var compilation = CreateCompilationWithMscorlib(source);
var sA = compilation.GetMember<NamedTypeSymbol>("A");
var sB = compilation.GetMember<NamedTypeSymbol>("B");
var sC = compilation.GetMember<NamedTypeSymbol>("C");
var f1 = new SymbolDisplayFormat();
var f2 = new SymbolDisplayFormat(memberOptions: SymbolDisplayMemberOptions.IncludeParameters);
Assert.False(new FormattedSymbol(sA, f1).Equals((object)sA));
Assert.False(new FormattedSymbol(sA, f1).Equals(null));
Assert.True(new FormattedSymbol(sA, f1).Equals(new FormattedSymbol(sA, f1)));
Assert.False(new FormattedSymbol(sA, f1).Equals(new FormattedSymbol(sA, f2)));
Assert.False(new FormattedSymbol(sA, f1).Equals(new FormattedSymbol(sB, f1)));
Assert.False(new FormattedSymbol(sA, f1).Equals(new FormattedSymbol(sB, f2)));
Assert.False(new FormattedSymbol(sC, f1).Equals(new FormattedSymbol(sC.Construct(sA), f1)));
Assert.True(new FormattedSymbol(sC.Construct(sA), f1).Equals(new FormattedSymbol(sC.Construct(sA), f1)));
Assert.False(new FormattedSymbol(sA, new SymbolDisplayFormat()).Equals(new FormattedSymbol(sA, new SymbolDisplayFormat())));
Assert.True(new FormattedSymbol(sA, f1).GetHashCode().Equals(new FormattedSymbol(sA, f1).GetHashCode()));
}
}
}
......@@ -4,6 +4,7 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols
......@@ -680,5 +681,27 @@ public static void Main()
// Lib.M<C>();
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "Lib.M<C>").WithArguments("Lib.M<T>()", "C [Metadata, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]", "T", "C [file.cs(2)]").WithLocation(8, 9));
}
[WorkItem(6262)]
[Fact]
public void SymbolDistinguisherEquality()
{
var source =
@"class A { }
class B { }
class C { }";
var compilation = CreateCompilationWithMscorlib(source);
var sA = compilation.GetMember<NamedTypeSymbol>("A");
var sB = compilation.GetMember<NamedTypeSymbol>("B");
var sC = compilation.GetMember<NamedTypeSymbol>("C");
Assert.True(AreEqual(new SymbolDistinguisher(compilation, sA, sB), new SymbolDistinguisher(compilation, sA, sB)));
Assert.False(AreEqual(new SymbolDistinguisher(compilation, sA, sB), new SymbolDistinguisher(compilation, sA, sC)));
Assert.False(AreEqual(new SymbolDistinguisher(compilation, sA, sB), new SymbolDistinguisher(compilation, sC, sB)));
}
private static bool AreEqual(SymbolDistinguisher a, SymbolDistinguisher b)
{
return a.First.Equals(b.First) && a.Second.Equals(b.Second);
}
}
}
......@@ -5,13 +5,14 @@
namespace Microsoft.CodeAnalysis
{
// For the purposes of lambda error reporting we wish to compare
// diagnostics for equality only considering their code and location,
// but not other factors such as the values supplied for the
// parameters of the diagnostic.
internal sealed class CommonDiagnosticComparer : IEqualityComparer<Diagnostic>
{
internal static readonly CommonDiagnosticComparer Instance = new CommonDiagnosticComparer();
private CommonDiagnosticComparer()
{
}
public bool Equals(Diagnostic x, Diagnostic y)
{
if (object.ReferenceEquals(x, y))
......
......@@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis
/// provide access to additional information about the error, such as what symbols were involved in the ambiguity.
/// </remarks>
[DebuggerDisplay("{GetDebuggerDisplay(), nq}")]
internal partial class DiagnosticInfo : IFormattable, IObjectWritable, IObjectReadable, IMessageSerializable
internal class DiagnosticInfo : IFormattable, IObjectWritable, IObjectReadable, IMessageSerializable
{
private readonly CommonMessageProvider _messageProvider;
private readonly int _errorCode;
......@@ -404,7 +404,7 @@ string IFormattable.ToString(string format, IFormatProvider formatProvider)
this.GetMessage(formatProvider));
}
public override int GetHashCode()
public sealed override int GetHashCode()
{
int hashCode = _errorCode;
if (_arguments != null)
......@@ -418,7 +418,7 @@ public override int GetHashCode()
return hashCode;
}
public override bool Equals(object obj)
public sealed override bool Equals(object obj)
{
DiagnosticInfo other = obj as DiagnosticInfo;
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Roslyn.Utilities;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis
......@@ -27,5 +28,20 @@ public override string ToString()
{
return _symbol.ToDisplayString(_symbolDisplayFormat);
}
public override bool Equals(object obj)
{
var other = obj as FormattedSymbol;
return other != null &&
_symbol.Equals(other._symbol) &&
_symbolDisplayFormat == other._symbolDisplayFormat;
}
public override int GetHashCode()
{
return Hash.Combine(
_symbol.GetHashCode(),
_symbolDisplayFormat.GetHashCode());
}
}
}
......@@ -5619,6 +5619,16 @@ BC30456: 'GetWordsAsync' is not a member of 'Line'.
BC30451: 'WordsKey' is not declared. It may be inaccessible due to its protection level.
If imax <= WordsKey Then Return
~~~~~~~~
BC30518: Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
Await Task.WhenAll(WordTasks.ToArray())
~~~~~~~
BC30518: Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
Await Task.WhenAll(SentenceTasks.ToArray())
~~~~~~~
]]></expected>)
End Sub
......@@ -5732,6 +5742,16 @@ BC30456: 'GetDeliveryWindowVendor9Async' is not a member of 'DeliveryWindowDepar
BC30451: 'Vendor9Key' is not declared. It may be inaccessible due to its protection level.
If MaxDepth <= Vendor9Key Then
~~~~~~~~~~
BC30518: Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
Await Task.WhenAll(Vendor9Tasks.ToArray())
~~~~~~~
BC30518: Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
Await Task.WhenAll(DepartmentTasks.ToArray())
~~~~~~~
BC30518: Overload resolution failed because no accessible 'WhenAll' can be called with these arguments:
'Public Shared Overloads Function WhenAll(Of TResult)(tasks As IEnumerable(Of Task(Of TResult))) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
'Public Shared Overloads Function WhenAll(Of TResult)(ParamArray tasks As Task(Of TResult)()) As Task(Of TResult())': Type parameter 'TResult' cannot be inferred.
......
......@@ -138,7 +138,9 @@ public void DiagnosticEquivalence()
// (5,22): error CS1503: Argument 1: cannot convert from '<anonymous type: int A>' to 'string'
// static int y = F(new { A = 1 });
Diagnostic(1503, "new { A = 1 }").WithArguments("1", "<anonymous type: int A>", "string").WithLocation(5, 22));
Assert.NotEqual(diagnostics1, diagnostics2);
Assert.NotSame(diagnostics1[0], diagnostics2[0]);
Assert.NotSame(diagnostics1[1], diagnostics2[1]);
Assert.Equal(diagnostics1, diagnostics2);
Assert.True(DiagnosticIncrementalAnalyzer.AreEquivalent(diagnostics1, diagnostics2));
// Verify that not all collections are treated as equivalent.
diagnostics1 = new[] { diagnostics1[0] };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册