/*
Copyright (C) 2011 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 Mono.Cecil;
namespace de4dot.renamer {
abstract class TypeNames {
protected Dictionary typeNames = new Dictionary(StringComparer.Ordinal);
protected NameCreator genericParamNameCreator = new NameCreator("gparam_");
public string create(TypeReference typeRef) {
if (typeRef.IsGenericInstance) {
var git = (GenericInstanceType)typeRef;
if (git.ElementType.FullName == "System.Nullable`1" &&
git.GenericArguments.Count == 1 && git.GenericArguments[0] != null) {
typeRef = git.GenericArguments[0];
}
}
string prefix = getPrefix(typeRef);
var elementType = typeRef.GetElementType();
if (elementType is GenericParameter)
return genericParamNameCreator.create();
NameCreator nc;
var typeFullName = typeRef.FullName;
if (typeNames.TryGetValue(typeFullName, out nc))
return nc.create();
var name = elementType.FullName;
var parts = name.Replace('/', '.').Split(new char[] { '.' });
var newName = parts[parts.Length - 1];
int tickIndex = newName.LastIndexOf('`');
if (tickIndex > 0)
newName = newName.Substring(0, tickIndex);
return addTypeName(typeFullName, newName, prefix).create();
}
static string getPrefix(TypeReference typeRef) {
string prefix = "";
while (typeRef is PointerType) {
typeRef = ((PointerType)typeRef).ElementType;
prefix += "p";
}
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) {
foreach (var pair in other.typeNames) {
if (typeNames.ContainsKey(pair.Key))
typeNames[pair.Key].merge(pair.Value);
else
typeNames[pair.Key] = pair.Value.clone();
}
genericParamNameCreator.merge(other.genericParamNameCreator);
return this;
}
protected static string upperFirst(string s) {
return s.Substring(0, 1).ToUpperInvariant() + s.Substring(1);
}
}
class VariableNameCreator : TypeNames {
public VariableNameCreator() {
initTypeName("System.Boolean", "bool");
initTypeName("System.Byte", "byte");
initTypeName("System.Char", "char");
initTypeName("System.Double", "double");
initTypeName("System.Int16", "short");
initTypeName("System.Int32", "int");
initTypeName("System.Int64", "long");
initTypeName("System.IntPtr", "intptr", "IntPtr");
initTypeName("System.SByte", "sbyte", "SByte");
initTypeName("System.Single", "float");
initTypeName("System.String", "string");
initTypeName("System.UInt16", "ushort", "UShort");
initTypeName("System.UInt32", "uint", "UInt");
initTypeName("System.UInt64", "ulong", "ULong");
initTypeName("System.UIntPtr", "uintptr", "UIntPtr");
initTypeName("System.Decimal", "decimal");
}
void initTypeName(string fullName, string newName, string ptrName = null) {
if (ptrName == null)
ptrName = upperFirst(newName);
initTypeName2(fullName, "", newName);
initTypeName2(fullName + "[]", "", newName);
initTypeName2(fullName + "[][]", "", newName);
initTypeName2(fullName + "[][][]", "", newName);
initTypeName2(fullName + "[0...,0...]", "", newName);
initTypeName2(fullName + "*", "p", ptrName);
initTypeName2(fullName + "**", "pp", ptrName);
}
void initTypeName2(string fullName, string prefix, string newName) {
addTypeName(fullName, newName, prefix);
addTypeName(fullName + "&", newName, prefix);
}
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);
}
}
class PropertyNameCreator : TypeNames {
protected override string fixName(string prefix, string name) {
return prefix.ToUpperInvariant() + upperFirst(name);
}
}
}