233 lines
6.5 KiB
C#
233 lines
6.5 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Diagnostics;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
using Microsoft.CodeAnalysis.Text;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal sealed class SymbolDistinguisher
|
|
{
|
|
private sealed class Description : IFormattable
|
|
{
|
|
private readonly SymbolDistinguisher _distinguisher;
|
|
|
|
private readonly int _index;
|
|
|
|
public Description(SymbolDistinguisher distinguisher, int index)
|
|
{
|
|
_distinguisher = distinguisher;
|
|
_index = index;
|
|
}
|
|
|
|
private Symbol GetSymbol()
|
|
{
|
|
if (_index != 0)
|
|
{
|
|
return _distinguisher._symbol1;
|
|
}
|
|
return _distinguisher._symbol0;
|
|
}
|
|
|
|
public override bool Equals(object obj)
|
|
{
|
|
if (obj is Description description && _distinguisher._compilation == description._distinguisher._compilation)
|
|
{
|
|
return GetSymbol() == description.GetSymbol();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
int num = GetSymbol().GetHashCode();
|
|
CSharpCompilation compilation = _distinguisher._compilation;
|
|
if (compilation != null)
|
|
{
|
|
num = Hash.Combine(num, ((object)compilation).GetHashCode());
|
|
}
|
|
return num;
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return _distinguisher.GetDescription(_index);
|
|
}
|
|
|
|
string IFormattable.ToString(string format, IFormatProvider formatProvider)
|
|
{
|
|
return ToString();
|
|
}
|
|
}
|
|
|
|
private readonly CSharpCompilation _compilation;
|
|
|
|
private readonly Symbol _symbol0;
|
|
|
|
private readonly Symbol _symbol1;
|
|
|
|
private ImmutableArray<string> _lazyDescriptions;
|
|
|
|
public IFormattable First => new Description(this, 0);
|
|
|
|
public IFormattable Second => new Description(this, 1);
|
|
|
|
public SymbolDistinguisher(CSharpCompilation compilation, Symbol symbol0, Symbol symbol1)
|
|
{
|
|
_compilation = compilation;
|
|
_symbol0 = symbol0;
|
|
_symbol1 = symbol1;
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
private static void CheckSymbolKind(Symbol symbol)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0061: Expected I4, but got Unknown
|
|
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
|
|
SymbolKind kind = symbol.Kind;
|
|
switch ((int)kind)
|
|
{
|
|
case 1:
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 9:
|
|
case 11:
|
|
case 13:
|
|
case 14:
|
|
case 15:
|
|
case 17:
|
|
case 20:
|
|
return;
|
|
}
|
|
throw ExceptionUtilities.UnexpectedValue((object)symbol.Kind);
|
|
}
|
|
|
|
private void MakeDescriptions()
|
|
{
|
|
if (!_lazyDescriptions.IsDefault)
|
|
{
|
|
return;
|
|
}
|
|
string text = _symbol0.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageNoParameterNamesFormat);
|
|
string text2 = _symbol1.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageNoParameterNamesFormat);
|
|
if (text == text2)
|
|
{
|
|
Symbol symbol = UnwrapSymbol(_symbol0);
|
|
Symbol symbol2 = UnwrapSymbol(_symbol1);
|
|
string text3 = GetLocationString(_compilation, symbol);
|
|
string text4 = GetLocationString(_compilation, symbol2);
|
|
if (text3 == text4)
|
|
{
|
|
AssemblySymbol containingAssembly = symbol.ContainingAssembly;
|
|
AssemblySymbol containingAssembly2 = symbol2.ContainingAssembly;
|
|
if ((object)containingAssembly != null && (object)containingAssembly2 != null)
|
|
{
|
|
text3 = ((object)containingAssembly.Identity).ToString();
|
|
text4 = ((object)containingAssembly2.Identity).ToString();
|
|
}
|
|
}
|
|
if (text3 != text4)
|
|
{
|
|
if (text3 != null)
|
|
{
|
|
text = text + " [" + text3 + "]";
|
|
}
|
|
if (text4 != null)
|
|
{
|
|
text2 = text2 + " [" + text4 + "]";
|
|
}
|
|
}
|
|
}
|
|
if (_lazyDescriptions.IsDefault)
|
|
{
|
|
ImmutableInterlocked.InterlockedInitialize(ref _lazyDescriptions, ImmutableArray.Create(text, text2));
|
|
}
|
|
}
|
|
|
|
private static Symbol UnwrapSymbol(Symbol symbol)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Invalid comparison between Unknown and I4
|
|
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000e: Invalid comparison between Unknown and I4
|
|
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0013: Invalid comparison between Unknown and I4
|
|
while (true)
|
|
{
|
|
SymbolKind kind = symbol.Kind;
|
|
if ((int)kind != 1)
|
|
{
|
|
if ((int)kind != 13)
|
|
{
|
|
if ((int)kind != 14)
|
|
{
|
|
break;
|
|
}
|
|
symbol = ((PointerTypeSymbol)symbol).PointedAtType;
|
|
}
|
|
else
|
|
{
|
|
symbol = ((ParameterSymbol)symbol).Type;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
symbol = ((ArrayTypeSymbol)symbol).ElementType;
|
|
}
|
|
}
|
|
return symbol;
|
|
}
|
|
|
|
private static string GetLocationString(CSharpCompilation compilation, Symbol unwrappedSymbol)
|
|
{
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
|
|
ImmutableArray<SyntaxReference> declaringSyntaxReferences = unwrappedSymbol.DeclaringSyntaxReferences;
|
|
if (declaringSyntaxReferences.Length > 0)
|
|
{
|
|
SyntaxTree syntaxTree = declaringSyntaxReferences[0].SyntaxTree;
|
|
TextSpan span = declaringSyntaxReferences[0].Span;
|
|
string displayPath = syntaxTree.GetDisplayPath(span, (compilation != null) ? ((CompilationOptions)compilation.Options).SourceReferenceResolver : null);
|
|
if (!string.IsNullOrEmpty(displayPath))
|
|
{
|
|
return $"{displayPath}({syntaxTree.GetDisplayLineNumber(span)})";
|
|
}
|
|
}
|
|
AssemblySymbol containingAssembly = unwrappedSymbol.ContainingAssembly;
|
|
if ((object)containingAssembly != null)
|
|
{
|
|
if (compilation != null)
|
|
{
|
|
MetadataReference? metadataReference = compilation.GetMetadataReference(containingAssembly);
|
|
PortableExecutableReference val = (PortableExecutableReference)(object)((metadataReference is PortableExecutableReference) ? metadataReference : null);
|
|
if (val != null)
|
|
{
|
|
string filePath = val.FilePath;
|
|
if (!string.IsNullOrEmpty(filePath))
|
|
{
|
|
return filePath;
|
|
}
|
|
}
|
|
}
|
|
return ((object)containingAssembly.Identity).ToString();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private string GetDescription(int index)
|
|
{
|
|
MakeDescriptions();
|
|
return _lazyDescriptions[index];
|
|
}
|
|
}
|