/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using dnlib.DotNet;
namespace dnSpy.Contracts.Decompiler {
///
/// Member comparer base class
///
///
public abstract class MemberRefComparer : IComparer where T : class, IMemberRef {
///
/// Compares two instances
///
/// First instance to compare
/// Second instance to compare
///
public int Compare([AllowNull] T x, [AllowNull] T y) {
if ((object?)x == y)
return 0;
if (x is null)
return -1;
if (y is null)
return 1;
int c = StringComparer.OrdinalIgnoreCase.Compare(x.Name, y.Name);
if (c != 0) return c;
c = x.MDToken.Raw.CompareTo(y.MDToken.Raw);
if (c != 0) return c;
return x.GetHashCode().CompareTo(y.GetHashCode());
}
}
///
/// comparer
///
public sealed class TypeDefComparer : MemberRefComparer {
///
/// Gets the instance
///
public static readonly TypeDefComparer Instance = new TypeDefComparer();
}
///
/// comparer
///
public sealed class MemberRefComparer : MemberRefComparer {
///
/// Gets the instance
///
public static readonly MemberRefComparer Instance = new MemberRefComparer();
}
///
/// comparer
///
public sealed class FieldDefComparer : MemberRefComparer {
///
/// Gets the instance
///
public static readonly FieldDefComparer Instance = new FieldDefComparer();
}
///
/// comparer
///
public sealed class EventDefComparer : MemberRefComparer {
///
/// Gets the instance
///
public static readonly EventDefComparer Instance = new EventDefComparer();
}
///
/// comparer
///
public sealed class PropertyDefComparer : MemberRefComparer {
///
/// Gets the instance
///
public static readonly PropertyDefComparer Instance = new PropertyDefComparer();
}
///
/// comparer
///
public sealed class MethodDefComparer : IComparer {
///
/// Gets the instance
///
public static readonly MethodDefComparer Instance = new MethodDefComparer();
///
/// Compares two instances
///
/// First instance to compare
/// Second instance to compare
///
public int Compare([AllowNull] MethodDef x, [AllowNull] MethodDef y) => MethodRefComparer.Instance.Compare(x, y);
}
///
/// Method reference comparer
///
public sealed class MethodRefComparer : IComparer {
///
/// Gets the instance
///
public static readonly MethodRefComparer Instance = new MethodRefComparer();
///
/// Compares two instances
///
/// First instance to compare
/// Second instance to compare
///
public int Compare([AllowNull] IMethod x, [AllowNull] IMethod y) {
if ((object?)x == y)
return 0;
if (x is null)
return -1;
if (y is null)
return 1;
int c = StringComparer.OrdinalIgnoreCase.Compare(x.Name, y.Name);
if (c != 0)
return c;
return CompareNoName(x, y);
}
internal static int CompareNoName(IMethod x, IMethod y) {
int c = x.MethodSig.GetParamCount().CompareTo(y.MethodSig.GetParamCount());
if (c != 0) return c;
c = x.MethodSig.GetGenParamCount().CompareTo(y.MethodSig.GetGenParamCount());
if (c != 0) return c;
c = x.MDToken.Raw.CompareTo(y.MDToken.Raw);
if (c != 0) return c;
return x.GetHashCode().CompareTo(y.GetHashCode());
}
}
///
/// Property reference comparer
///
public sealed class PropertyRefComparer : IComparer {
///
/// Gets the instance
///
public static readonly PropertyRefComparer Instance = new PropertyRefComparer();
static int GetAccessor(string name, out string propName) {
if (name.StartsWith("get_")) {
propName = name.Substring(4);
return 0;
}
if (name.StartsWith("set_")) {
propName = name.Substring(4);
return 1;
}
propName = name;
return int.MaxValue;
}
///
/// Compares two instances
///
/// First instance to compare
/// Second instance to compare
///
public int Compare([AllowNull] IMethod x, [AllowNull] IMethod y) {
if ((object?)x == y)
return 0;
if (x is null)
return -1;
if (y is null)
return 1;
string xn = x.Name;
string yn = y.Name;
int xacc = GetAccessor(xn, out var xPropName);
int yacc = GetAccessor(yn, out var yPropName);
int c = StringComparer.OrdinalIgnoreCase.Compare(xPropName, yPropName);
if (c != 0) return c;
c = xacc - yacc;
if (c != 0) return c;
return MethodRefComparer.CompareNoName(x, y);
}
}
///
/// Event reference comparer
///
public sealed class EventRefComparer : IComparer {
///
/// Gets the instance
///
public static readonly EventRefComparer Instance = new EventRefComparer();
static int GetAccessor(string name, out string propName) {
if (name.StartsWith("add_")) {
propName = name.Substring(4);
return 0;
}
if (name.StartsWith("remove_")) {
propName = name.Substring(7);
return 1;
}
if (name.StartsWith("raise_")) {
propName = name.Substring(6);
return 2;
}
propName = name;
return int.MaxValue;
}
///
/// Compares two instances
///
/// First instance to compare
/// Second instance to compare
///
public int Compare([AllowNull] IMethod x, [AllowNull] IMethod y) {
if ((object?)x == y)
return 0;
if (x is null)
return -1;
if (y is null)
return 1;
string xn = x.Name;
string yn = y.Name;
int xacc = GetAccessor(xn, out var xPropName);
int yacc = GetAccessor(yn, out var yPropName);
int c = StringComparer.OrdinalIgnoreCase.Compare(xPropName, yPropName);
if (c != 0) return c;
c = xacc - yacc;
if (c != 0) return c;
return MethodRefComparer.CompareNoName(x, y);
}
}
}