/* Copyright (C) 2011-2015 de4dot@gmail.com This file is part of de4dot. de4dot 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. de4dot 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 de4dot. If not, see . */ using System; using System.Collections.Generic; using dnlib.DotNet; namespace de4dot.code.renamer { public abstract class TypeNames { protected Dictionary typeNames = new Dictionary(StringComparer.Ordinal); protected NameCreator genericParamNameCreator = new NameCreator("gparam_"); protected NameCreator fnPtrNameCreator = new NameCreator("fnptr_"); protected NameCreator unknownNameCreator = new NameCreator("unknown_"); protected Dictionary fullNameToShortName; protected Dictionary fullNameToShortNamePrefix; public string Create(TypeSig typeRef) { typeRef = typeRef.RemovePinnedAndModifiers(); if (typeRef == null) return unknownNameCreator.Create(); var gis = typeRef as GenericInstSig; if (gis != null) { if (gis.FullName == "System.Nullable`1" && gis.GenericArguments.Count == 1 && gis.GenericArguments[0] != null) { typeRef = gis.GenericArguments[0]; } } string prefix = GetPrefix(typeRef); var elementType = Renamer.GetScopeType(typeRef); if (elementType == null && IsFnPtrSig(typeRef)) return fnPtrNameCreator.Create(); if (IsGenericParam(elementType)) return genericParamNameCreator.Create(); NameCreator nc; var typeFullName = typeRef.FullName; if (typeNames.TryGetValue(typeFullName, out nc)) return nc.Create(); var fullName = elementType == null ? typeRef.FullName : elementType.FullName; string shortName; var dict = prefix == "" ? fullNameToShortName : fullNameToShortNamePrefix; if (!dict.TryGetValue(fullName, out shortName)) { fullName = fullName.Replace('/', '.'); int index = fullName.LastIndexOf('.'); shortName = index > 0 ? fullName.Substring(index + 1) : fullName; index = shortName.LastIndexOf('`'); if (index > 0) shortName = shortName.Substring(0, index); } return AddTypeName(typeFullName, shortName, prefix).Create(); } bool IsFnPtrSig(TypeSig sig) { while (sig != null) { if (sig is FnPtrSig) return true; sig = sig.Next; } return false; } bool IsGenericParam(ITypeDefOrRef tdr) { var ts = tdr as TypeSpec; if (ts == null) return false; var sig = ts.TypeSig.RemovePinnedAndModifiers(); return sig is GenericSig; } static string GetPrefix(TypeSig typeRef) { string prefix = ""; while (typeRef != null) { if (typeRef.IsPointer) prefix += "p"; typeRef = typeRef.Next; } return prefix; } protected INameCreator AddTypeName(string fullName, string newName, string prefix) { newName = FixName(prefix, newName); var name2 = " " + newName; NameCreator nc; if (!typeNames.TryGetValue(name2, out nc)) typeNames[name2] = nc = new NameCreator(newName + "_"); typeNames[fullName] = nc; return nc; } protected abstract string FixName(string prefix, string name); public virtual TypeNames Merge(TypeNames other) { if (this == other) return this; foreach (var pair in other.typeNames) { NameCreator nc; if (typeNames.TryGetValue(pair.Key, out nc)) nc.Merge(pair.Value); else typeNames[pair.Key] = pair.Value.Clone(); } genericParamNameCreator.Merge(other.genericParamNameCreator); fnPtrNameCreator.Merge(other.fnPtrNameCreator); unknownNameCreator.Merge(other.unknownNameCreator); return this; } protected static string UpperFirst(string s) { if (string.IsNullOrEmpty(s)) return string.Empty; return s.Substring(0, 1).ToUpperInvariant() + s.Substring(1); } } public class VariableNameCreator : TypeNames { static Dictionary ourFullNameToShortName; static Dictionary ourFullNameToShortNamePrefix; static VariableNameCreator() { ourFullNameToShortName = new Dictionary(StringComparer.Ordinal) { { "System.Boolean", "bool" }, { "System.Byte", "byte" }, { "System.Char", "char" }, { "System.Double", "double" }, { "System.Int16", "short" }, { "System.Int32", "int" }, { "System.Int64", "long" }, { "System.IntPtr", "intptr" }, { "System.SByte", "sbyte" }, { "System.Single", "float" }, { "System.String", "string" }, { "System.UInt16", "ushort" }, { "System.UInt32", "uint" }, { "System.UInt64", "ulong" }, { "System.UIntPtr", "uintptr" }, { "System.Decimal", "decimal" }, }; ourFullNameToShortNamePrefix = new Dictionary(StringComparer.Ordinal) { { "System.Boolean", "Bool" }, { "System.Byte", "Byte" }, { "System.Char", "Char" }, { "System.Double", "Double" }, { "System.Int16", "Short" }, { "System.Int32", "Int" }, { "System.Int64", "Long" }, { "System.IntPtr", "IntPtr" }, { "System.SByte", "SByte" }, { "System.Single", "Float" }, { "System.String", "String" }, { "System.UInt16", "UShort" }, { "System.UInt32", "UInt" }, { "System.UInt64", "ULong" }, { "System.UIntPtr", "UIntPtr" }, { "System.Decimal", "Decimal" }, }; } public VariableNameCreator() { fullNameToShortName = ourFullNameToShortName; fullNameToShortNamePrefix = ourFullNameToShortNamePrefix; } static string LowerLeadingChars(string name) { var s = ""; for (int i = 0; i < name.Length; i++) { char c = char.ToLowerInvariant(name[i]); if (c == name[i]) return s + name.Substring(i); s += c; } return s; } protected override string FixName(string prefix, string name) { name = LowerLeadingChars(name); if (prefix == "") return name; return prefix + UpperFirst(name); } } public class PropertyNameCreator : TypeNames { static Dictionary ourFullNameToShortName = new Dictionary(StringComparer.Ordinal); static Dictionary ourFullNameToShortNamePrefix = new Dictionary(StringComparer.Ordinal); public PropertyNameCreator() { fullNameToShortName = ourFullNameToShortName; fullNameToShortNamePrefix = ourFullNameToShortNamePrefix; } protected override string FixName(string prefix, string name) { return prefix.ToUpperInvariant() + UpperFirst(name); } } }