2011-11-18 23:55:54 +08:00
|
|
|
|
/*
|
2012-01-10 06:02:47 +08:00
|
|
|
|
Copyright (C) 2011-2012 de4dot@gmail.com
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2011-11-21 17:36:23 +08:00
|
|
|
|
using System.Text.RegularExpressions;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
using dot10.DotNet;
|
|
|
|
|
using dot10.DotNet.Emit;
|
2011-12-09 16:02:06 +08:00
|
|
|
|
using de4dot.code.renamer.asmmodules;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
using de4dot.blocks;
|
|
|
|
|
|
2011-12-09 16:02:06 +08:00
|
|
|
|
namespace de4dot.code.renamer {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
class TypeInfo : MemberInfo {
|
|
|
|
|
public string oldNamespace;
|
|
|
|
|
public string newNamespace;
|
2012-01-27 12:39:25 +08:00
|
|
|
|
public VariableNameState variableNameState = VariableNameState.create();
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public MTypeDef type;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
MemberInfos memberInfos;
|
|
|
|
|
|
2011-11-21 17:36:23 +08:00
|
|
|
|
public INameChecker NameChecker {
|
|
|
|
|
get { return type.Module.ObfuscatedFile.NameChecker; }
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public TypeInfo(MTypeDef typeDef, MemberInfos memberInfos)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
: base(typeDef) {
|
|
|
|
|
this.type = typeDef;
|
|
|
|
|
this.memberInfos = memberInfos;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
oldNamespace = typeDef.TypeDef.Namespace.String;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isWinFormsClass() {
|
|
|
|
|
return memberInfos.isWinFormsClass(type);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public PropertyInfo prop(MPropertyDef prop) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.prop(prop);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public EventInfo evt(MEventDef evt) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.evt(evt);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public FieldInfo field(MFieldDef field) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.field(field);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public MethodInfo method(MMethodDef method) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.method(method);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public GenericParamInfo gparam(MGenericParamDef gparam) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.gparam(gparam);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public ParamInfo param(MParamDef param) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return memberInfos.param(param);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TypeInfo getBase() {
|
|
|
|
|
if (type.baseType == null)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
TypeInfo baseInfo;
|
|
|
|
|
memberInfos.tryGetType(type.baseType.typeDef, out baseInfo);
|
|
|
|
|
return baseInfo;
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-09 01:46:23 +08:00
|
|
|
|
bool isModuleType() {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
return type.TypeDef.IsGlobalModuleType;
|
2012-01-09 01:46:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-18 23:55:54 +08:00
|
|
|
|
public void prepareRenameTypes(TypeRenamerState state) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
if (newNamespace == null && oldNamespace != "") {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (type.TypeDef.IsNested)
|
2011-12-26 06:03:53 +08:00
|
|
|
|
newNamespace = "";
|
|
|
|
|
else if (!checker.isValidNamespaceName(oldNamespace))
|
2012-11-02 22:57:11 +08:00
|
|
|
|
newNamespace = state.createNamespace(this.type.TypeDef, oldNamespace);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-24 17:07:55 +08:00
|
|
|
|
string origClassName = null;
|
|
|
|
|
if (isWinFormsClass())
|
|
|
|
|
origClassName = findWindowsFormsClassName(type);
|
2012-01-09 01:46:23 +08:00
|
|
|
|
if (isModuleType()) {
|
|
|
|
|
if (oldNamespace != "")
|
|
|
|
|
newNamespace = "";
|
|
|
|
|
rename("<Module>");
|
|
|
|
|
}
|
|
|
|
|
else if (!checker.isValidTypeName(oldName)) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (origClassName != null && checker.isValidTypeName(origClassName))
|
|
|
|
|
rename(state.getTypeName(oldName, origClassName));
|
|
|
|
|
else {
|
|
|
|
|
ITypeNameCreator nameCreator = type.isGlobalType() ?
|
|
|
|
|
state.globalTypeNameCreator :
|
|
|
|
|
state.internalTypeNameCreator;
|
|
|
|
|
string newBaseType = null;
|
|
|
|
|
TypeInfo baseInfo = getBase();
|
|
|
|
|
if (baseInfo != null && baseInfo.renamed)
|
|
|
|
|
newBaseType = baseInfo.newName;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
rename(nameCreator.create(type.TypeDef, newBaseType));
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prepareRenameGenericParams(type.GenericParams, checker);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-22 15:14:34 +08:00
|
|
|
|
public void mergeState() {
|
|
|
|
|
foreach (var ifaceInfo in type.interfaces)
|
|
|
|
|
mergeState(ifaceInfo.typeDef);
|
|
|
|
|
if (type.baseType != null)
|
|
|
|
|
mergeState(type.baseType.typeDef);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void mergeState(MTypeDef other) {
|
2011-11-22 15:14:34 +08:00
|
|
|
|
if (other == null)
|
|
|
|
|
return;
|
|
|
|
|
TypeInfo otherInfo;
|
|
|
|
|
if (!memberInfos.tryGetType(other, out otherInfo))
|
|
|
|
|
return;
|
|
|
|
|
variableNameState.merge(otherInfo.variableNameState);
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-18 23:55:54 +08:00
|
|
|
|
public void prepareRenameMembers() {
|
2011-11-22 15:14:34 +08:00
|
|
|
|
mergeState();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
2011-11-21 17:36:23 +08:00
|
|
|
|
foreach (var fieldDef in type.AllFields)
|
|
|
|
|
variableNameState.addFieldName(field(fieldDef).oldName);
|
|
|
|
|
foreach (var eventDef in type.AllEvents)
|
|
|
|
|
variableNameState.addEventName(evt(eventDef).oldName);
|
|
|
|
|
foreach (var propDef in type.AllProperties)
|
|
|
|
|
variableNameState.addPropertyName(prop(propDef).oldName);
|
|
|
|
|
foreach (var methodDef in type.AllMethods)
|
|
|
|
|
variableNameState.addMethodName(method(methodDef).oldName);
|
|
|
|
|
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (isWinFormsClass())
|
|
|
|
|
initializeWindowsFormsFieldsAndProps();
|
|
|
|
|
|
|
|
|
|
prepareRenameFields();
|
2011-11-23 18:34:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void prepareRenamePropsAndEvents() {
|
|
|
|
|
mergeState();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
prepareRenameProperties();
|
|
|
|
|
prepareRenameEvents();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void prepareRenameFields() {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (type.TypeDef.IsEnum) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
var instanceFields = getInstanceFields();
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (instanceFields.Count == 1)
|
|
|
|
|
field(instanceFields[0]).rename("value__");
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
|
string nameFormat = hasFlagsAttribute() ? "flag_{0}" : "const_{0}";
|
|
|
|
|
foreach (var fieldDef in type.AllFieldsSorted) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var fieldInfo = field(fieldDef);
|
|
|
|
|
if (fieldInfo.renamed)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (!fieldDef.FieldDef.IsStatic || !fieldDef.FieldDef.IsLiteral)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (!checker.isValidFieldName(fieldInfo.oldName))
|
|
|
|
|
fieldInfo.rename(string.Format(nameFormat, i));
|
2011-11-18 23:55:54 +08:00
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
foreach (var fieldDef in type.AllFieldsSorted) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var fieldInfo = field(fieldDef);
|
|
|
|
|
if (fieldInfo.renamed)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (!checker.isValidFieldName(fieldInfo.oldName))
|
2012-11-02 22:57:11 +08:00
|
|
|
|
fieldInfo.rename(fieldInfo.suggestedName ?? variableNameState.getNewFieldName(fieldDef.FieldDef));
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
List<MFieldDef> getInstanceFields() {
|
|
|
|
|
var fields = new List<MFieldDef>();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var fieldDef in type.AllFields) {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (!fieldDef.FieldDef.IsStatic)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
fields.Add(fieldDef);
|
|
|
|
|
}
|
|
|
|
|
return fields;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool hasFlagsAttribute() {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
foreach (var attr in type.TypeDef.CustomAttributes) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (attr.AttributeType.FullName == "System.FlagsAttribute")
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void prepareRenameProperties() {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
foreach (var propDef in type.AllPropertiesSorted) {
|
|
|
|
|
if (propDef.isVirtual())
|
|
|
|
|
continue;
|
|
|
|
|
prepareRenameProperty(propDef);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void prepareRenameProperty(MPropertyDef propDef) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (propDef.isVirtual())
|
|
|
|
|
throw new ApplicationException("Can't rename virtual props here");
|
|
|
|
|
var propInfo = prop(propDef);
|
|
|
|
|
if (propInfo.renamed)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
string propName = propInfo.oldName;
|
|
|
|
|
if (!NameChecker.isValidPropertyName(propName))
|
|
|
|
|
propName = propInfo.suggestedName;
|
2011-12-03 21:28:10 +08:00
|
|
|
|
if (!NameChecker.isValidPropertyName(propName)) {
|
|
|
|
|
if (propDef.isItemProperty())
|
|
|
|
|
propName = "Item";
|
|
|
|
|
else
|
2012-11-02 22:57:11 +08:00
|
|
|
|
propName = variableNameState.getNewPropertyName(propDef.PropertyDef);
|
2011-12-03 21:28:10 +08:00
|
|
|
|
}
|
2011-11-21 17:36:23 +08:00
|
|
|
|
variableNameState.addPropertyName(propName);
|
|
|
|
|
propInfo.rename(propName);
|
|
|
|
|
|
|
|
|
|
renameSpecialMethod(propDef.GetMethod, "get_" + propName);
|
|
|
|
|
renameSpecialMethod(propDef.SetMethod, "set_" + propName);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void prepareRenameEvents() {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
foreach (var eventDef in type.AllEventsSorted) {
|
|
|
|
|
if (eventDef.isVirtual())
|
|
|
|
|
continue;
|
|
|
|
|
prepareRenameEvent(eventDef);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void prepareRenameEvent(MEventDef eventDef) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (eventDef.isVirtual())
|
|
|
|
|
throw new ApplicationException("Can't rename virtual events here");
|
|
|
|
|
var eventInfo = evt(eventDef);
|
|
|
|
|
if (eventInfo.renamed)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
string eventName = eventInfo.oldName;
|
|
|
|
|
if (!NameChecker.isValidEventName(eventName))
|
|
|
|
|
eventName = eventInfo.suggestedName;
|
|
|
|
|
if (!NameChecker.isValidEventName(eventName))
|
2012-11-02 22:57:11 +08:00
|
|
|
|
eventName = variableNameState.getNewEventName(eventDef.EventDef);
|
2011-11-21 17:36:23 +08:00
|
|
|
|
variableNameState.addEventName(eventName);
|
|
|
|
|
eventInfo.rename(eventName);
|
|
|
|
|
|
|
|
|
|
renameSpecialMethod(eventDef.AddMethod, "add_" + eventName);
|
|
|
|
|
renameSpecialMethod(eventDef.RemoveMethod, "remove_" + eventName);
|
|
|
|
|
renameSpecialMethod(eventDef.RaiseMethod, "raise_" + eventName);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void renameSpecialMethod(MMethodDef methodDef, string newName) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (methodDef == null)
|
|
|
|
|
return;
|
|
|
|
|
if (methodDef.isVirtual())
|
|
|
|
|
return;
|
|
|
|
|
renameMethod(methodDef, newName);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-23 18:34:11 +08:00
|
|
|
|
public void prepareRenameMethods() {
|
|
|
|
|
mergeState();
|
2011-11-21 17:36:23 +08:00
|
|
|
|
foreach (var methodDef in type.AllMethodsSorted) {
|
|
|
|
|
if (methodDef.isVirtual())
|
|
|
|
|
continue;
|
|
|
|
|
renameMethod(methodDef);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void prepareRenameMethods2() {
|
|
|
|
|
var checker = NameChecker;
|
|
|
|
|
foreach (var methodDef in type.AllMethodsSorted) {
|
|
|
|
|
prepareRenameMethodArgs(methodDef);
|
|
|
|
|
prepareRenameGenericParams(methodDef.GenericParams, checker, methodDef.Owner == null ? null : methodDef.Owner.GenericParams);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void prepareRenameMethodArgs(MMethodDef methodDef) {
|
2012-11-04 18:45:04 +08:00
|
|
|
|
VariableNameState newVariableNameState = null;
|
|
|
|
|
ParamInfo info;
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (methodDef.VisibleParameterCount > 0) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (isEventHandler(methodDef)) {
|
2012-11-05 05:41:45 +08:00
|
|
|
|
info = param(methodDef.ParamDefs[methodDef.VisibleParameterBaseIndex]);
|
2012-01-01 19:06:40 +08:00
|
|
|
|
if (!info.gotNewName())
|
|
|
|
|
info.newName = "sender";
|
|
|
|
|
|
2012-11-05 05:41:45 +08:00
|
|
|
|
info = param(methodDef.ParamDefs[methodDef.VisibleParameterBaseIndex + 1]);
|
2012-01-01 19:06:40 +08:00
|
|
|
|
if (!info.gotNewName())
|
|
|
|
|
info.newName = "e";
|
2011-11-21 17:36:23 +08:00
|
|
|
|
}
|
|
|
|
|
else {
|
2012-11-04 18:45:04 +08:00
|
|
|
|
newVariableNameState = variableNameState.cloneParamsOnly();
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
|
|
|
|
foreach (var paramDef in methodDef.ParamDefs) {
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (paramDef.IsHiddenThisParameter)
|
|
|
|
|
continue;
|
2012-11-04 18:45:04 +08:00
|
|
|
|
info = param(paramDef);
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (info.gotNewName())
|
|
|
|
|
continue;
|
|
|
|
|
if (!checker.isValidMethodArgName(info.oldName))
|
|
|
|
|
info.newName = newVariableNameState.getNewParamName(info.oldName, paramDef.ParameterDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 18:45:04 +08:00
|
|
|
|
info = param(methodDef.ReturnParamDef);
|
|
|
|
|
if (!info.gotNewName()) {
|
|
|
|
|
if (!NameChecker.isValidMethodReturnArgName(info.oldName)) {
|
|
|
|
|
if (newVariableNameState == null)
|
|
|
|
|
newVariableNameState = variableNameState.cloneParamsOnly();
|
|
|
|
|
info.newName = newVariableNameState.getNewParamName(info.oldName, methodDef.ReturnParamDef.ParameterDefinition);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-21 18:26:02 +08:00
|
|
|
|
if ((methodDef.Property != null && methodDef == methodDef.Property.SetMethod) ||
|
|
|
|
|
(methodDef.Event != null && (methodDef == methodDef.Event.AddMethod || methodDef == methodDef.Event.RemoveMethod))) {
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (methodDef.VisibleParameterCount > 0) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var paramDef = methodDef.ParamDefs[methodDef.ParamDefs.Count - 1];
|
|
|
|
|
param(paramDef).newName = "value";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
bool canRenameMethod(MMethodDef methodDef) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var methodInfo = method(methodDef);
|
|
|
|
|
if (methodDef.isStatic()) {
|
|
|
|
|
if (methodInfo.oldName == ".cctor")
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
else if (methodDef.isVirtual()) {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (DotNetUtils.derivesFromDelegate(type.TypeDef)) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
switch (methodInfo.oldName) {
|
|
|
|
|
case "BeginInvoke":
|
|
|
|
|
case "EndInvoke":
|
|
|
|
|
case "Invoke":
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
if (methodInfo.oldName == ".ctor")
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
public void renameMethod(MMethodDef methodDef, string methodName) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (!canRenameMethod(methodDef))
|
|
|
|
|
return;
|
|
|
|
|
var methodInfo = method(methodDef);
|
|
|
|
|
variableNameState.addMethodName(methodName);
|
|
|
|
|
methodInfo.rename(methodName);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void renameMethod(MMethodDef methodDef) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (methodDef.isVirtual())
|
|
|
|
|
throw new ApplicationException("Can't rename virtual methods here");
|
|
|
|
|
if (!canRenameMethod(methodDef))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
var info = method(methodDef);
|
|
|
|
|
if (info.renamed)
|
|
|
|
|
return;
|
|
|
|
|
info.renamed = true;
|
|
|
|
|
var checker = NameChecker;
|
|
|
|
|
|
2011-12-02 20:18:22 +08:00
|
|
|
|
// PInvoke methods' EntryPoint is always valid. It has to, so always rename.
|
2012-11-16 09:15:36 +08:00
|
|
|
|
bool isValidName = NameChecker.isValidMethodName(info.oldName);
|
|
|
|
|
bool isExternPInvoke = methodDef.MethodDef.ImplMap != null && methodDef.MethodDef.RVA == 0;
|
|
|
|
|
if (!isValidName || isExternPInvoke) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
INameCreator nameCreator = null;
|
|
|
|
|
string newName = info.suggestedName;
|
2012-11-16 09:15:36 +08:00
|
|
|
|
string newName2;
|
|
|
|
|
if (methodDef.MethodDef.ImplMap != null && !string.IsNullOrEmpty(newName2 = getPinvokeName(methodDef)))
|
|
|
|
|
newName = newName2;
|
2011-11-21 17:36:23 +08:00
|
|
|
|
else if (methodDef.isStatic())
|
|
|
|
|
nameCreator = variableNameState.staticMethodNameCreator;
|
|
|
|
|
else
|
|
|
|
|
nameCreator = variableNameState.instanceMethodNameCreator;
|
2012-11-16 09:15:36 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(newName))
|
2011-11-21 17:36:23 +08:00
|
|
|
|
nameCreator = new NameCreator2(newName);
|
|
|
|
|
renameMethod(methodDef, variableNameState.getNewMethodName(info.oldName, nameCreator));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
string getPinvokeName(MMethodDef methodDef) {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var entryPoint = methodDef.MethodDef.ImplMap.Name.String;
|
2011-11-21 17:36:23 +08:00
|
|
|
|
if (Regex.IsMatch(entryPoint, @"^#\d+$"))
|
2012-11-04 07:50:24 +08:00
|
|
|
|
entryPoint = DotNetUtils.getDllName(methodDef.MethodDef.ImplMap.Scope.Name.String) + "_" + entryPoint.Substring(1);
|
2011-11-21 17:36:23 +08:00
|
|
|
|
return entryPoint;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
static bool isEventHandler(MMethodDef methodDef) {
|
2012-11-05 05:41:45 +08:00
|
|
|
|
var sig = methodDef.MethodDef.MethodSig;
|
|
|
|
|
if (sig == null || sig.Params.Count != 2)
|
2011-11-21 17:36:23 +08:00
|
|
|
|
return false;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (sig.RetType.ElementType != ElementType.Void)
|
2011-11-21 17:36:23 +08:00
|
|
|
|
return false;
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (sig.Params[0].ElementType != ElementType.Object)
|
2012-11-04 07:50:24 +08:00
|
|
|
|
return false;
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (!sig.Params[1].FullName.Contains("EventArgs"))
|
2011-11-21 17:36:23 +08:00
|
|
|
|
return false;
|
|
|
|
|
return true;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void prepareRenameGenericParams(IEnumerable<MGenericParamDef> genericParams, INameChecker checker) {
|
2012-07-07 13:11:32 +08:00
|
|
|
|
prepareRenameGenericParams(genericParams, checker, null);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void prepareRenameGenericParams(IEnumerable<MGenericParamDef> genericParams, INameChecker checker, IEnumerable<MGenericParamDef> otherGenericParams) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
var usedNames = new Dictionary<string, bool>(StringComparer.Ordinal);
|
|
|
|
|
var nameCreator = new GenericParamNameCreator();
|
|
|
|
|
|
|
|
|
|
if (otherGenericParams != null) {
|
|
|
|
|
foreach (var param in otherGenericParams) {
|
|
|
|
|
var gpInfo = memberInfos.gparam(param);
|
|
|
|
|
usedNames[gpInfo.newName] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (var param in genericParams) {
|
|
|
|
|
var gpInfo = memberInfos.gparam(param);
|
|
|
|
|
if (!checker.isValidGenericParamName(gpInfo.oldName) || usedNames.ContainsKey(gpInfo.oldName)) {
|
|
|
|
|
string newName;
|
|
|
|
|
do {
|
|
|
|
|
newName = nameCreator.create();
|
|
|
|
|
} while (usedNames.ContainsKey(newName));
|
|
|
|
|
usedNames[newName] = true;
|
|
|
|
|
gpInfo.rename(newName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void initializeWindowsFormsFieldsAndProps() {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var ourFields = new FieldDefinitionAndDeclaringTypeDict<MFieldDef>();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var fieldDef in type.AllFields)
|
2012-11-02 22:57:11 +08:00
|
|
|
|
ourFields.add(fieldDef.FieldDef, fieldDef);
|
|
|
|
|
var ourMethods = new MethodDefinitionAndDeclaringTypeDict<MMethodDef>();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var methodDef in type.AllMethods)
|
2012-11-02 22:57:11 +08:00
|
|
|
|
ourMethods.add(methodDef.MethodDef, methodDef);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
foreach (var methodDef in type.AllMethods) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (methodDef.MethodDef.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (methodDef.MethodDef.IsStatic || methodDef.MethodDef.IsVirtual)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = methodDef.MethodDef.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
for (int i = 2; i < instructions.Count; i++) {
|
|
|
|
|
var call = instructions[i];
|
|
|
|
|
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!isWindowsFormsSetNameMethod(call.Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var ldstr = instructions[i - 1];
|
|
|
|
|
if (ldstr.OpCode.Code != Code.Ldstr)
|
|
|
|
|
continue;
|
|
|
|
|
var fieldName = ldstr.Operand as string;
|
|
|
|
|
if (fieldName == null || !checker.isValidFieldName(fieldName))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var instr = instructions[i - 2];
|
2012-11-04 07:50:24 +08:00
|
|
|
|
IField fieldRef = null;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (instr.OpCode.Code == Code.Call || instr.OpCode.Code == Code.Callvirt) {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var calledMethod = instr.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (calledMethod == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var calledMethodDef = ourMethods.find(calledMethod);
|
|
|
|
|
if (calledMethodDef == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
fieldRef = getFieldReference(calledMethodDef.MethodDef);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
var propDef = calledMethodDef.Property;
|
|
|
|
|
if (propDef == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
memberInfos.prop(propDef).suggestedName = fieldName;
|
|
|
|
|
fieldName = "_" + fieldName;
|
|
|
|
|
}
|
|
|
|
|
else if (instr.OpCode.Code == Code.Ldfld) {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
fieldRef = instr.Operand as IField;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fieldRef == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var fieldDef = ourFields.find(fieldRef);
|
|
|
|
|
if (fieldDef == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
var fieldInfo = memberInfos.field(fieldDef);
|
|
|
|
|
|
|
|
|
|
if (fieldInfo.renamed)
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-11-23 18:34:11 +08:00
|
|
|
|
fieldInfo.suggestedName = variableNameState.getNewFieldName(fieldInfo.oldName, new NameCreator2(fieldName));
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static IField getFieldReference(MethodDef method) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method == null || method.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = method.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
int index = 0;
|
|
|
|
|
var ldarg0 = DotNetUtils.getInstruction(instructions, ref index);
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (ldarg0 == null || ldarg0.GetParameterIndex() != 0)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
|
|
|
|
var ldfld = DotNetUtils.getInstruction(instructions, ref index);
|
|
|
|
|
if (ldfld == null || ldfld.OpCode.Code != Code.Ldfld)
|
|
|
|
|
return null;
|
|
|
|
|
var ret = DotNetUtils.getInstruction(instructions, ref index);
|
2012-03-18 19:52:55 +08:00
|
|
|
|
if (ret == null)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (ret.IsStloc()) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var local = ret.GetLocal(method.Body.LocalList);
|
2012-03-18 19:52:55 +08:00
|
|
|
|
ret = DotNetUtils.getInstruction(instructions, ref index);
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (ret == null || !ret.IsLdloc())
|
2012-03-18 19:52:55 +08:00
|
|
|
|
return null;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (ret.GetLocal(method.Body.LocalList) != local)
|
2012-03-18 19:52:55 +08:00
|
|
|
|
return null;
|
|
|
|
|
ret = DotNetUtils.getInstruction(instructions, ref index);
|
|
|
|
|
}
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (ret == null || ret.OpCode.Code != Code.Ret)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
return ldfld.Operand as IField;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2011-11-23 18:34:11 +08:00
|
|
|
|
public void initializeEventHandlerNames() {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var ourFields = new FieldDefinitionAndDeclaringTypeDict<MFieldDef>();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var fieldDef in type.AllFields)
|
2012-11-02 22:57:11 +08:00
|
|
|
|
ourFields.add(fieldDef.FieldDef, fieldDef);
|
|
|
|
|
var ourMethods = new MethodDefinitionAndDeclaringTypeDict<MMethodDef>();
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var methodDef in type.AllMethods)
|
2012-11-02 22:57:11 +08:00
|
|
|
|
ourMethods.add(methodDef.MethodDef, methodDef);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
initVbEventHandlers(ourFields, ourMethods);
|
|
|
|
|
initFieldEventHandlers(ourFields, ourMethods);
|
|
|
|
|
initTypeEventHandlers(ourFields, ourMethods);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VB initializes the handlers in the property setter, where it first removes the handler
|
|
|
|
|
// from the previous control, and then adds the handler to the new control.
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void initVbEventHandlers(FieldDefinitionAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefinitionAndDeclaringTypeDict<MMethodDef> ourMethods) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
foreach (var propDef in type.AllProperties) {
|
2011-12-19 22:43:40 +08:00
|
|
|
|
var setterDef = propDef.SetMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (setterDef == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
string eventName;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var handler = getVbHandler(setterDef.MethodDef, out eventName);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (handler == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var handlerDef = ourMethods.find(handler);
|
|
|
|
|
if (handlerDef == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (!checker.isValidEventName(eventName))
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-11-21 17:56:18 +08:00
|
|
|
|
memberInfos.method(handlerDef).suggestedName = string.Format("{0}_{1}", memberInfos.prop(propDef).newName, eventName);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static IMethod getVbHandler(MethodDef method, out string eventName) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
eventName = null;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method.Body == null)
|
2012-11-04 07:50:24 +08:00
|
|
|
|
return null;
|
|
|
|
|
var sig = method.MethodSig;
|
|
|
|
|
if (sig == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (sig.RetType.ElementType != ElementType.Void)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-05 05:41:45 +08:00
|
|
|
|
if (sig.Params.Count != 1)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (method.Body.LocalList.Count != 1)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (!isEventHandlerType(method.Body.LocalList[0].Type))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
|
|
|
|
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = method.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
int index = 0;
|
|
|
|
|
|
|
|
|
|
int newobjIndex = findInstruction(instructions, index, Code.Newobj);
|
|
|
|
|
if (newobjIndex == -1 || findInstruction(instructions, newobjIndex + 1, Code.Newobj) != -1)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!isEventHandlerCtor(instructions[newobjIndex].Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
|
|
|
|
if (newobjIndex < 1)
|
|
|
|
|
return null;
|
|
|
|
|
var ldvirtftn = instructions[newobjIndex - 1];
|
|
|
|
|
if (ldvirtftn.OpCode.Code != Code.Ldvirtftn && ldvirtftn.OpCode.Code != Code.Ldftn)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var handlerMethod = ldvirtftn.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (handlerMethod == null)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!new SigComparer().Equals(method.DeclaringType, handlerMethod.DeclaringType))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
|
|
|
|
index = newobjIndex;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
IField addField, removeField;
|
|
|
|
|
IMethod addMethod, removeMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (!findEventCall(instructions, ref index, out removeField, out removeMethod))
|
|
|
|
|
return null;
|
|
|
|
|
if (!findEventCall(instructions, ref index, out addField, out addMethod))
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
if (findInstruction(instructions, index, Code.Callvirt) != -1)
|
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!new SigComparer().Equals(addField, removeField))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!new SigComparer().Equals(method.DeclaringType, addField.DeclaringType))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!new SigComparer().Equals(addMethod.DeclaringType, removeMethod.DeclaringType))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!Utils.StartsWith(addMethod.Name.String, "add_", StringComparison.Ordinal))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!Utils.StartsWith(removeMethod.Name.String, "remove_", StringComparison.Ordinal))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
eventName = addMethod.Name.String.Substring(4);
|
|
|
|
|
if (eventName != removeMethod.Name.String.Substring(7))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return null;
|
|
|
|
|
if (eventName == "")
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
return handlerMethod;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static bool findEventCall(IList<Instruction> instructions, ref int index, out IField field, out IMethod calledMethod) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
field = null;
|
|
|
|
|
calledMethod = null;
|
|
|
|
|
|
|
|
|
|
int callvirt = findInstruction(instructions, index, Code.Callvirt);
|
|
|
|
|
if (callvirt < 2)
|
|
|
|
|
return false;
|
|
|
|
|
index = callvirt + 1;
|
|
|
|
|
|
|
|
|
|
var ldloc = instructions[callvirt - 1];
|
|
|
|
|
if (ldloc.OpCode.Code != Code.Ldloc_0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
var ldfld = instructions[callvirt - 2];
|
|
|
|
|
if (ldfld.OpCode.Code != Code.Ldfld)
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
field = ldfld.Operand as IField;
|
|
|
|
|
calledMethod = instructions[callvirt].Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return field != null && calledMethod != null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int findInstruction(IList<Instruction> instructions, int index, Code code) {
|
|
|
|
|
for (int i = index; i < instructions.Count; i++) {
|
|
|
|
|
if (instructions[i].OpCode.Code == code)
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void initFieldEventHandlers(FieldDefinitionAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefinitionAndDeclaringTypeDict<MMethodDef> ourMethods) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
foreach (var methodDef in type.AllMethods) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (methodDef.MethodDef.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (methodDef.MethodDef.IsStatic)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = methodDef.MethodDef.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
for (int i = 0; i < instructions.Count - 6; i++) {
|
|
|
|
|
// We're looking for this code pattern:
|
|
|
|
|
// ldarg.0
|
|
|
|
|
// ldfld field
|
|
|
|
|
// ldarg.0
|
|
|
|
|
// ldftn method / ldarg.0 + ldvirtftn
|
|
|
|
|
// newobj event_handler_ctor
|
|
|
|
|
// callvirt add_SomeEvent
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (instructions[i].GetParameterIndex() != 0)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
int index = i + 1;
|
|
|
|
|
|
|
|
|
|
var ldfld = instructions[index++];
|
|
|
|
|
if (ldfld.OpCode.Code != Code.Ldfld)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var fieldRef = ldfld.Operand as IField;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (fieldRef == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var fieldDef = ourFields.find(fieldRef);
|
|
|
|
|
if (fieldDef == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (instructions[index++].GetParameterIndex() != 0)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
IMethod methodRef;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
var instr = instructions[index + 1];
|
|
|
|
|
if (instr.OpCode.Code == Code.Ldvirtftn) {
|
2012-01-22 03:31:47 +08:00
|
|
|
|
if (!isThisOrDup(instructions[index++]))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
var ldvirtftn = instructions[index++];
|
2012-11-04 07:50:24 +08:00
|
|
|
|
methodRef = ldvirtftn.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
var ldftn = instructions[index++];
|
|
|
|
|
if (ldftn.OpCode.Code != Code.Ldftn)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
methodRef = ldftn.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
if (methodRef == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var handlerMethod = ourMethods.find(methodRef);
|
|
|
|
|
if (handlerMethod == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var newobj = instructions[index++];
|
|
|
|
|
if (newobj.OpCode.Code != Code.Newobj)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!isEventHandlerCtor(newobj.Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var call = instructions[index++];
|
|
|
|
|
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var addHandler = call.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (addHandler == null)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!Utils.StartsWith(addHandler.Name.String, "add_", StringComparison.Ordinal))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var eventName = addHandler.Name.String.Substring(4);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (!checker.isValidEventName(eventName))
|
|
|
|
|
continue;
|
|
|
|
|
|
2011-11-21 17:56:18 +08:00
|
|
|
|
memberInfos.method(handlerMethod).suggestedName = string.Format("{0}_{1}", memberInfos.field(fieldDef).newName, eventName);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void initTypeEventHandlers(FieldDefinitionAndDeclaringTypeDict<MFieldDef> ourFields, MethodDefinitionAndDeclaringTypeDict<MMethodDef> ourMethods) {
|
2011-11-21 17:36:23 +08:00
|
|
|
|
var checker = NameChecker;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
|
|
|
|
|
foreach (var methodDef in type.AllMethods) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (methodDef.MethodDef.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (methodDef.MethodDef.IsStatic)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
var method = methodDef.MethodDef;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = method.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
for (int i = 0; i < instructions.Count - 5; i++) {
|
|
|
|
|
// ldarg.0
|
|
|
|
|
// ldarg.0 / dup
|
|
|
|
|
// ldarg.0 / dup
|
|
|
|
|
// ldvirtftn handler
|
|
|
|
|
// newobj event handler ctor
|
|
|
|
|
// call add_Xyz
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (instructions[i].GetParameterIndex() != 0)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
int index = i + 1;
|
|
|
|
|
|
2012-01-22 03:31:47 +08:00
|
|
|
|
if (!isThisOrDup(instructions[index++]))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
IMethod handler;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (instructions[index].OpCode.Code == Code.Ldftn) {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
handler = instructions[index++].Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
else {
|
2012-01-22 03:31:47 +08:00
|
|
|
|
if (!isThisOrDup(instructions[index++]))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
var instr = instructions[index++];
|
|
|
|
|
if (instr.OpCode.Code != Code.Ldvirtftn)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
handler = instr.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
if (handler == null)
|
|
|
|
|
continue;
|
2011-12-17 02:33:44 +08:00
|
|
|
|
var handlerDef = ourMethods.find(handler);
|
|
|
|
|
if (handlerDef == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var newobj = instructions[index++];
|
|
|
|
|
if (newobj.OpCode.Code != Code.Newobj)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!isEventHandlerCtor(newobj.Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var call = instructions[index++];
|
|
|
|
|
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var addMethod = call.Operand as IMethod;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (addMethod == null)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!Utils.StartsWith(addMethod.Name.String, "add_", StringComparison.Ordinal))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var eventName = addMethod.Name.String.Substring(4);
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (!checker.isValidEventName(eventName))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
memberInfos.method(handlerDef).suggestedName = string.Format("{0}_{1}", newName, eventName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-01-22 03:31:47 +08:00
|
|
|
|
static bool isThisOrDup(Instruction instr) {
|
2012-11-04 07:50:24 +08:00
|
|
|
|
return instr.GetParameterIndex() == 0 || instr.OpCode.Code == Code.Dup;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static bool isEventHandlerCtor(IMethod method) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (method == null)
|
|
|
|
|
return false;
|
|
|
|
|
if (method.Name != ".ctor")
|
|
|
|
|
return false;
|
|
|
|
|
if (!DotNetUtils.isMethod(method, "System.Void", "(System.Object,System.IntPtr)"))
|
|
|
|
|
return false;
|
|
|
|
|
if (!isEventHandlerType(method.DeclaringType))
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static bool isEventHandlerType(IType type) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return type.FullName.EndsWith("EventHandler", StringComparison.Ordinal);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
string findWindowsFormsClassName(MTypeDef type) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var methodDef in type.AllMethods) {
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (methodDef.MethodDef.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (methodDef.MethodDef.IsStatic || methodDef.MethodDef.IsVirtual)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
var instructions = methodDef.MethodDef.Body.Instructions;
|
2011-11-18 23:55:54 +08:00
|
|
|
|
for (int i = 2; i < instructions.Count; i++) {
|
|
|
|
|
var call = instructions[i];
|
|
|
|
|
if (call.OpCode.Code != Code.Call && call.OpCode.Code != Code.Callvirt)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!isWindowsFormsSetNameMethod(call.Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
var ldstr = instructions[i - 1];
|
|
|
|
|
if (ldstr.OpCode.Code != Code.Ldstr)
|
|
|
|
|
continue;
|
|
|
|
|
var className = ldstr.Operand as string;
|
|
|
|
|
if (className == null)
|
|
|
|
|
continue;
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (instructions[i - 2].GetParameterIndex() != 0)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
findInitializeComponentMethod(type, methodDef);
|
|
|
|
|
return className;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-02 22:57:11 +08:00
|
|
|
|
void findInitializeComponentMethod(MTypeDef type, MMethodDef possibleInitMethod) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
foreach (var methodDef in type.AllMethods) {
|
2012-11-02 22:57:11 +08:00
|
|
|
|
if (methodDef.MethodDef.Name != ".ctor")
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
if (methodDef.MethodDef.Body == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
2012-11-06 22:58:55 +08:00
|
|
|
|
foreach (var instr in methodDef.MethodDef.Body.Instructions) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (instr.OpCode.Code != Code.Call && instr.OpCode.Code != Code.Callvirt)
|
|
|
|
|
continue;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (!MethodEqualityComparer.CompareDeclaringTypes.Equals(possibleInitMethod.MethodDef, instr.Operand as IMethod))
|
2011-11-18 23:55:54 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
memberInfos.method(possibleInitMethod).suggestedName = "InitializeComponent";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-04 07:50:24 +08:00
|
|
|
|
static bool isWindowsFormsSetNameMethod(IMethod method) {
|
2011-11-18 23:55:54 +08:00
|
|
|
|
if (method == null)
|
|
|
|
|
return false;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (method.Name.String != "set_Name")
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return false;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
var sig = method.MethodSig;
|
|
|
|
|
if (sig == null)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return false;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (sig.RetType.ElementType != ElementType.Void)
|
|
|
|
|
return false;
|
|
|
|
|
if (sig.Params.Count != 1)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return false;
|
2012-11-04 07:50:24 +08:00
|
|
|
|
if (sig.Params[0].ElementType != ElementType.String)
|
2011-11-18 23:55:54 +08:00
|
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|