/*
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.Collections.Generic;
using Mono.Cecil;
using de4dot.blocks;
namespace de4dot.code.renamer {
interface INameCreator {
string create();
}
class OneNameCreator : INameCreator {
string name;
public OneNameCreator(string name) {
this.name = name;
}
public string create() {
return name;
}
}
abstract class NameCreatorCounter : INameCreator {
protected int num;
public abstract string create();
public NameCreatorCounter merge(NameCreatorCounter other) {
if (num < other.num)
num = other.num;
return this;
}
}
class GenericParamNameCreator : NameCreatorCounter {
static string[] names = new string[] { "T", "U", "V", "W", "X", "Y", "Z" };
public override string create() {
if (num < names.Length)
return names[num++];
return string.Format("T{0}", num++);
}
}
class NameCreator : NameCreatorCounter {
string prefix;
public NameCreator(string prefix, int num = 0) {
this.prefix = prefix;
this.num = num;
}
public NameCreator clone() {
return new NameCreator(prefix, num);
}
public override string create() {
return prefix + num++;
}
}
// Like NameCreator but don't add the counter the first time
class NameCreator2 : NameCreatorCounter {
string prefix;
const string separator = "_";
public NameCreator2(string prefix, int num = 0) {
this.prefix = prefix;
this.num = num;
}
public override string create() {
string rv;
if (num == 0)
rv = prefix;
else
rv = prefix + separator + num;
num++;
return rv;
}
}
interface ITypeNameCreator {
string create(TypeDefinition typeDefinition, string newBaseTypeName = null);
}
class NameInfos {
IList nameInfos = new List();
class NameInfo {
public string name;
public NameCreator nameCreator;
public NameInfo(string name, NameCreator nameCreator) {
this.name = name;
this.nameCreator = nameCreator;
}
}
public void add(string name, NameCreator nameCreator) {
nameInfos.Add(new NameInfo(name, nameCreator));
}
public NameCreator find(string typeName) {
foreach (var nameInfo in nameInfos) {
if (typeName.Contains(nameInfo.name))
return nameInfo.nameCreator;
}
return null;
}
}
class TypeNameCreator : ITypeNameCreator {
ExistingNames existingNames;
NameCreator createUnknownTypeName;
NameCreator createEnumName;
NameCreator createStructName;
NameCreator createDelegateName;
NameCreator createClassName;
NameCreator createInterfaceName;
NameInfos nameInfos = new NameInfos();
public TypeNameCreator(ExistingNames existingNames) {
this.existingNames = existingNames;
createUnknownTypeName = createNameCreator("Type");
createEnumName = createNameCreator("Enum");
createStructName = createNameCreator("Struct");
createDelegateName = createNameCreator("Delegate");
createClassName = createNameCreator("Class");
createInterfaceName = createNameCreator("Interface");
var names = new string[] {
"Exception",
"EventArgs",
"Attribute",
"Form",
"Dialog",
"Control",
"Stream",
};
foreach (var name in names)
nameInfos.add(name, createNameCreator(name));
}
protected virtual NameCreator createNameCreator(string prefix) {
return new NameCreator(prefix);
}
public string create(TypeDefinition typeDefinition, string newBaseTypeName = null) {
var nameCreator = getNameCreator(typeDefinition, newBaseTypeName);
return existingNames.getName(typeDefinition.Name, nameCreator);
}
NameCreator getNameCreator(TypeDefinition typeDefinition, string newBaseTypeName) {
var nameCreator = createUnknownTypeName;
if (typeDefinition.IsEnum)
nameCreator = createEnumName;
else if (typeDefinition.IsValueType)
nameCreator = createStructName;
else if (typeDefinition.IsClass) {
if (typeDefinition.BaseType != null) {
if (MemberReferenceHelper.verifyType(typeDefinition.BaseType, "mscorlib", "System.Delegate"))
nameCreator = createDelegateName;
else if (MemberReferenceHelper.verifyType(typeDefinition.BaseType, "mscorlib", "System.MulticastDelegate"))
nameCreator = createDelegateName;
else {
nameCreator = nameInfos.find(newBaseTypeName ?? typeDefinition.BaseType.Name);
if (nameCreator == null)
nameCreator = createClassName;
}
}
else
nameCreator = createClassName;
}
else if (typeDefinition.IsInterface)
nameCreator = createInterfaceName;
return nameCreator;
}
}
class GlobalTypeNameCreator : TypeNameCreator {
public GlobalTypeNameCreator(ExistingNames existingNames)
: base(existingNames) {
}
protected override NameCreator createNameCreator(string prefix) {
return base.createNameCreator("G" + prefix);
}
}
}